Преглед на файлове

Merge pull request #1803 from dsnopek/4.3-cherrypicks-5

Cherry-picks for the godot-cpp 4.3 branch - 5th batch
David Snopek преди 2 месеца
родител
ревизия
d5cc777a89

+ 11 - 11
.github/workflows/ci.yml

@@ -21,7 +21,7 @@ jobs:
       matrix:
         include:
           - name: 🐧 Linux (GCC)
-            os: ubuntu-20.04
+            os: ubuntu-22.04
             platform: linux
             artifact-name: godot-cpp-linux-glibc2.27-x86_64-release
             artifact-path: bin/libgodot-cpp.linux.template_release.x86_64.a
@@ -29,7 +29,7 @@ jobs:
             cache-name: linux-x86_64
 
           - name: 🐧 Linux (GCC, Double Precision)
-            os: ubuntu-20.04
+            os: ubuntu-22.04
             platform: linux
             artifact-name: godot-cpp-linux-glibc2.27-x86_64-double-release
             artifact-path: bin/libgodot-cpp.linux.template_release.double.x86_64.a
@@ -38,7 +38,7 @@ jobs:
             cache-name: linux-x86_64-f64
 
           - name: 🏁 Windows (x86_64, MSVC)
-            os: windows-2019
+            os: windows-2022
             platform: windows
             artifact-name: godot-cpp-windows-msvc2019-x86_64-release
             artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.lib
@@ -46,7 +46,7 @@ jobs:
             cache-name: windows-x86_64-msvc
 
           - name: 🏁 Windows (x86_64, MinGW)
-            os: windows-2019
+            os: windows-2022
             platform: windows
             artifact-name: godot-cpp-linux-mingw-x86_64-release
             artifact-path: bin/libgodot-cpp.windows.template_release.x86_64.a
@@ -64,7 +64,7 @@ jobs:
             cache-name: macos-universal
 
           - name: 🤖 Android (arm64)
-            os: ubuntu-20.04
+            os: ubuntu-22.04
             platform: android
             artifact-name: godot-cpp-android-arm64-release
             artifact-path: bin/libgodot-cpp.android.template_release.arm64.a
@@ -82,7 +82,7 @@ jobs:
             cache-name: ios-arm64
 
           - name: 🌐 Web (wasm32)
-            os: ubuntu-20.04
+            os: ubuntu-22.04
             platform: web
             artifact-name: godot-cpp-web-wasm32-release
             artifact-path: bin/libgodot-cpp.web.template_release.wasm32.a
@@ -183,7 +183,7 @@ jobs:
 
   linux-cmake:
     name: 🐧 Build (Linux, GCC, CMake)
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-22.04
     steps:
       - name: Checkout
         uses: actions/checkout@v4
@@ -207,7 +207,7 @@ jobs:
 
   linux-cmake-ninja:
     name: 🐧 Build (Linux, GCC, CMake Ninja)
-    runs-on: ubuntu-20.04
+    runs-on: ubuntu-22.04
     steps:
       - name: Checkout
         uses: actions/checkout@v4
@@ -231,7 +231,7 @@ jobs:
 
   windows-msvc-cmake:
     name: 🏁 Build (Windows, MSVC, CMake)
-    runs-on: windows-2019
+    runs-on: windows-2022
     steps:
       - name: Checkout
         uses: actions/checkout@v4
@@ -240,10 +240,10 @@ jobs:
 
       - name: Build godot-cpp
         run: |
-          cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 16 2019" .
+          cmake -DCMAKE_BUILD_TYPE=Release -G"Visual Studio 17 2022" .
           cmake --build . --verbose --config Release
 
       - name: Build test GDExtension library
         run: |
-          cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -G"Visual Studio 16 2019" .
+          cd test && cmake -DCMAKE_BUILD_TYPE=Release -DGODOT_HEADERS_PATH="../godot-headers" -DCPP_BINDINGS_PATH=".." -G"Visual Studio 17 2022" .
           cmake --build . --verbose --config Release

+ 10 - 15
README.md

@@ -7,6 +7,8 @@
 > from Godot's `master` branch.
 >
 > For users of stable branches, switch to the branch matching your target Godot version:
+> - [`4.4`](https://github.com/godotengine/godot-cpp/tree/4.4)
+> - [`4.3`](https://github.com/godotengine/godot-cpp/tree/4.3)
 > - [`4.2`](https://github.com/godotengine/godot-cpp/tree/4.2)
 > - [`4.1`](https://github.com/godotengine/godot-cpp/tree/4.1)
 > - [`4.0`](https://github.com/godotengine/godot-cpp/tree/4.0)
@@ -49,20 +51,13 @@ Godot version.**
 
 ## Compatibility
 
-> [!WARNING]
->
-> The GDExtension API is brand new in Godot 4.0, and is still
-considered in **beta** stage, despite Godot 4.0 itself being released.
->
-> This applies to both the GDExtension interface header, the API JSON, and this
-first-party `godot-cpp` extension.
->
-> Some compatibility breakage is to be expected as GDExtension and `godot-cpp`
-> get more used, documented, and critical issues get resolved. See the
-> [Godot issue tracker](https://github.com/godotengine/godot/issues?q=is%3Aissue+is%3Aopen+label%3Atopic%3Agdextension)
-> and the [godot-cpp issue tracker](https://github.com/godotengine/godot-cpp/issues)
-> for a list of known issues, and be sure to provide feedback on issues and PRs
-> which affect your use of this extension.
+GDExtensions targeting an earlier version of Godot should work in later minor versions,
+but not vice-versa. For example, a GDExtension targeting Godot 4.2 should work just fine
+in Godot 4.3, but one targeting Godot 4.3 won't work in Godot 4.2.
+
+There is one exception to this: extensions targeting Godot 4.0 will _not_ work with
+Godot 4.1 and later.
+See [Updating your GDExtension for 4.1](https://docs.godotengine.org/en/latest/tutorials/migrating/upgrading_to_godot_4.1.html#updating-your-gdextension-for-godot-4-1).
 
 ## Contributing
 
@@ -145,4 +140,4 @@ See the [godot-cpp-template](https://github.com/godotengine/godot-cpp-template)
 generic reusable template.
 
 Or checkout the code for the [Summator example](https://github.com/paddy-exe/GDExtensionSummator)
-as shown in the [official documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/gdextension/gdextension_cpp_example.html).
+as shown in the [official documentation](https://docs.godotengine.org/en/latest/tutorials/scripting/cpp/gdextension_cpp_example.html).

+ 10 - 0
binding_generator.py

@@ -1591,6 +1591,16 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us
         result.append(f"\t~{class_name}();")
         result.append("")
 
+    if class_name == "Object":
+        result.append('\tString _to_string() const { return "<" + get_class() + "#" + itos(get_instance_id()) + ">"; }')
+        result.append("")
+
+    if class_name == "Node":
+        result.append(
+            '\tString _to_string() const { return (!get_name().is_empty() ? String(get_name()) + ":" : "") + Object::_to_string(); }'
+        )
+        result.append("")
+
     result.append("public:")
 
     # Special cases.

+ 1 - 5
include/godot_cpp/classes/wrapped.hpp

@@ -94,7 +94,7 @@ protected:
 	bool _property_can_revert(const StringName &p_name) const { return false; }
 	bool _property_get_revert(const StringName &p_name, Variant &r_property) const { return false; }
 	void _validate_property(PropertyInfo &p_property) const {}
-	String _to_string() const { return "[" + String(get_class_static()) + ":" + itos(get_instance_id()) + "]"; }
+	String _to_string() const { return "<Wrapped#0>"; }
 
 	static void notification_bind(GDExtensionClassInstancePtr p_instance, int32_t p_what, GDExtensionBool p_reversed) {}
 	static GDExtensionBool set_bind(GDExtensionClassInstancePtr p_instance, GDExtensionConstStringNamePtr p_name, GDExtensionConstVariantPtr p_value) { return false; }
@@ -123,10 +123,6 @@ public:
 		return string_name;
 	}
 
-	uint64_t get_instance_id() const {
-		return 0;
-	}
-
 	// Must be public but you should not touch this.
 	GodotObject *_owner = nullptr;
 };

+ 4 - 4
include/godot_cpp/core/engine_ptrcall.hpp

@@ -56,10 +56,10 @@ O *_call_native_mb_ret_obj(const GDExtensionMethodBindPtr mb, void *instance, co
 
 template <typename R, typename... Args>
 R _call_native_mb_ret(const GDExtensionMethodBindPtr mb, void *instance, const Args &...args) {
-	R ret;
+	typename PtrToArg<R>::EncodeT ret;
 	std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
 	internal::gdextension_interface_object_method_bind_ptrcall(mb, instance, mb_args.data(), &ret);
-	return ret;
+	return static_cast<R>(ret);
 }
 
 template <typename... Args>
@@ -70,10 +70,10 @@ void _call_native_mb_no_ret(const GDExtensionMethodBindPtr mb, void *instance, c
 
 template <typename R, typename... Args>
 R _call_utility_ret(GDExtensionPtrUtilityFunction func, const Args &...args) {
-	R ret;
+	typename PtrToArg<R>::EncodeT ret;
 	std::array<GDExtensionConstTypePtr, sizeof...(Args)> mb_args = { { (GDExtensionConstTypePtr)args... } };
 	func(&ret, mb_args.data(), mb_args.size());
-	return ret;
+	return static_cast<R>(ret);
 }
 
 template <typename... Args>

+ 54 - 46
include/godot_cpp/core/method_bind.hpp

@@ -48,14 +48,14 @@
 namespace godot {
 
 class MethodBind {
+	uint32_t hint_flags = METHOD_FLAGS_DEFAULT;
 	StringName name;
 	StringName instance_class;
 	int argument_count = 0;
-	uint32_t hint_flags = METHOD_FLAGS_DEFAULT;
 
 	bool _static = false;
-	bool _is_const = false;
-	bool _has_return = false;
+	bool _const = false;
+	bool _returns = false;
 	bool _vararg = false;
 
 	std::vector<StringName> argument_names;
@@ -63,20 +63,20 @@ class MethodBind {
 	std::vector<Variant> default_arguments;
 
 protected:
+	void _set_const(bool p_const);
+	void _set_static(bool p_static);
+	void _set_returns(bool p_returns);
+	void _set_vararg(bool p_vararg);
 	virtual GDExtensionVariantType gen_argument_type(int p_arg) const = 0;
 	virtual PropertyInfo gen_argument_type_info(int p_arg) const = 0;
-	void generate_argument_types(int p_count);
-	void set_const(bool p_const);
-	void set_return(bool p_return);
-	void set_static(bool p_static);
-	void set_vararg(bool p_vararg);
-	void set_argument_count(int p_count);
+	void _generate_argument_types(int p_count);
+
+	void set_argument_count(int p_count) { argument_count = p_count; }
 
 public:
-	StringName get_name() const;
-	void set_name(const StringName &p_name);
-	_FORCE_INLINE_ int get_default_argument_count() const { return (int)default_arguments.size(); }
 	_FORCE_INLINE_ const std::vector<Variant> &get_default_arguments() const { return default_arguments; }
+	_FORCE_INLINE_ int get_default_argument_count() const { return (int)default_arguments.size(); }
+
 	_FORCE_INLINE_ Variant has_default_argument(int p_arg) const {
 		const int num_default_args = (int)(default_arguments.size());
 		const int idx = p_arg - (argument_count - num_default_args);
@@ -97,19 +97,6 @@ public:
 			return default_arguments[idx];
 		}
 	}
-	_FORCE_INLINE_ StringName get_instance_class() const { return instance_class; }
-	_FORCE_INLINE_ void set_instance_class(StringName p_class) { instance_class = p_class; }
-
-	_FORCE_INLINE_ int get_argument_count() const { return argument_count; }
-	_FORCE_INLINE_ bool is_const() const { return _is_const; }
-	_FORCE_INLINE_ bool is_static() const { return _static; }
-	_FORCE_INLINE_ bool is_vararg() const { return _vararg; }
-	_FORCE_INLINE_ bool has_return() const { return _has_return; }
-	_FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDEXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDEXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDEXTENSION_METHOD_FLAG_STATIC : 0); }
-	_FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; }
-	void set_argument_names(const std::vector<StringName> &p_names);
-	std::vector<StringName> get_argument_names() const;
-	void set_default_arguments(const std::vector<Variant> &p_default_arguments) { default_arguments = p_default_arguments; }
 
 	_FORCE_INLINE_ GDExtensionVariantType get_argument_type(int p_argument) const {
 		ERR_FAIL_COND_V(p_argument < -1 || p_argument > argument_count, GDEXTENSION_VARIANT_TYPE_NIL);
@@ -117,7 +104,6 @@ public:
 	}
 
 	PropertyInfo get_argument_info(int p_argument) const;
-	virtual GDExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0;
 
 	std::vector<PropertyInfo> get_arguments_info_list() const {
 		std::vector<PropertyInfo> vec;
@@ -128,6 +114,31 @@ public:
 		}
 		return vec;
 	}
+
+	void set_argument_names(const std::vector<StringName> &p_names);
+	std::vector<StringName> get_argument_names() const;
+
+	virtual GDExtensionClassMethodArgumentMetadata get_argument_metadata(int p_argument) const = 0;
+
+	_FORCE_INLINE_ void set_hint_flags(uint32_t p_hint_flags) { hint_flags = p_hint_flags; }
+	_FORCE_INLINE_ uint32_t get_hint_flags() const { return hint_flags | (is_const() ? GDEXTENSION_METHOD_FLAG_CONST : 0) | (is_vararg() ? GDEXTENSION_METHOD_FLAG_VARARG : 0) | (is_static() ? GDEXTENSION_METHOD_FLAG_STATIC : 0); }
+	_FORCE_INLINE_ StringName get_instance_class() const { return instance_class; }
+	_FORCE_INLINE_ void set_instance_class(StringName p_class) { instance_class = p_class; }
+
+	_FORCE_INLINE_ int get_argument_count() const { return argument_count; }
+
+	virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionCallError &r_error) const = 0;
+	virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) const = 0;
+
+	StringName get_name() const;
+	void set_name(const StringName &p_name);
+	_FORCE_INLINE_ bool is_const() const { return _const; }
+	_FORCE_INLINE_ bool is_static() const { return _static; }
+	_FORCE_INLINE_ bool is_vararg() const { return _vararg; }
+	_FORCE_INLINE_ bool has_return() const { return _returns; }
+
+	void set_default_arguments(const std::vector<Variant> &p_default_arguments) { default_arguments = p_default_arguments; }
+
 	std::vector<GDExtensionClassMethodArgumentMetadata> get_arguments_metadata_list() const {
 		std::vector<GDExtensionClassMethodArgumentMetadata> vec;
 		// First element is return value
@@ -138,9 +149,6 @@ public:
 		return vec;
 	}
 
-	virtual Variant call(GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionCallError &r_error) const = 0;
-	virtual void ptrcall(GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return) const = 0;
-
 	static void bind_call(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstVariantPtr *p_args, GDExtensionInt p_argument_count, GDExtensionVariantPtr r_return, GDExtensionCallError *r_error);
 	static void bind_ptrcall(void *p_method_userdata, GDExtensionClassInstancePtr p_instance, const GDExtensionConstTypePtr *p_args, GDExtensionTypePtr r_return);
 
@@ -182,8 +190,8 @@ public:
 			const MethodInfo &p_method_info,
 			bool p_return_nil_is_variant) :
 			method(p_method) {
-		set_vararg(true);
-		set_const(true);
+		_set_vararg(true);
+		_set_const(true);
 		set_argument_count(p_method_info.arguments.size());
 		if (p_method_info.arguments.size()) {
 			arguments = p_method_info.arguments;
@@ -196,8 +204,8 @@ public:
 			set_argument_names(names);
 		}
 
-		generate_argument_types((int)p_method_info.arguments.size());
-		set_return(should_returns);
+		_generate_argument_types((int)p_method_info.arguments.size());
+		_set_returns(should_returns);
 	}
 
 	~MethodBindVarArgBase() {}
@@ -334,7 +342,7 @@ public:
 
 	MethodBindT(void (MB_T::*p_method)(P...)) {
 		method = p_method;
-		generate_argument_types(sizeof...(P));
+		_generate_argument_types(sizeof...(P));
 		set_argument_count(sizeof...(P));
 	}
 };
@@ -410,9 +418,9 @@ public:
 
 	MethodBindTC(void (MB_T::*p_method)(P...) const) {
 		method = p_method;
-		generate_argument_types(sizeof...(P));
+		_generate_argument_types(sizeof...(P));
 		set_argument_count(sizeof...(P));
-		set_const(true);
+		_set_const(true);
 	}
 };
 
@@ -493,9 +501,9 @@ public:
 
 	MethodBindTR(R (MB_T::*p_method)(P...)) {
 		method = p_method;
-		generate_argument_types(sizeof...(P));
+		_generate_argument_types(sizeof...(P));
 		set_argument_count(sizeof...(P));
-		set_return(true);
+		_set_returns(true);
 	}
 };
 
@@ -576,10 +584,10 @@ public:
 
 	MethodBindTRC(R (MB_T::*p_method)(P...) const) {
 		method = p_method;
-		generate_argument_types(sizeof...(P));
+		_generate_argument_types(sizeof...(P));
 		set_argument_count(sizeof...(P));
-		set_return(true);
-		set_const(true);
+		_set_returns(true);
+		_set_const(true);
 	}
 };
 
@@ -648,9 +656,9 @@ public:
 
 	MethodBindTS(void (*p_function)(P...)) {
 		function = p_function;
-		generate_argument_types(sizeof...(P));
+		_generate_argument_types(sizeof...(P));
 		set_argument_count(sizeof...(P));
-		set_static(true);
+		_set_static(true);
 	}
 };
 
@@ -717,10 +725,10 @@ public:
 
 	MethodBindTRS(R (*p_function)(P...)) {
 		function = p_function;
-		generate_argument_types(sizeof...(P));
+		_generate_argument_types(sizeof...(P));
 		set_argument_count(sizeof...(P));
-		set_static(true);
-		set_return(true);
+		_set_static(true);
+		_set_returns(true);
 	}
 };
 

+ 3 - 0
include/godot_cpp/core/method_ptrcall.hpp

@@ -122,6 +122,9 @@ MAKE_PTRARGCONV(uint16_t, int64_t);
 MAKE_PTRARGCONV(int16_t, int64_t);
 MAKE_PTRARGCONV(uint32_t, int64_t);
 MAKE_PTRARGCONV(int32_t, int64_t);
+MAKE_PTRARGCONV(char16_t, int64_t);
+MAKE_PTRARGCONV(char32_t, int64_t);
+MAKE_PTRARGCONV(wchar_t, int64_t);
 MAKE_PTRARG(int64_t);
 MAKE_PTRARG(uint64_t);
 // Float types

+ 1 - 0
include/godot_cpp/variant/projection.hpp

@@ -153,6 +153,7 @@ struct [[nodiscard]] Projection {
 
 	Projection();
 	Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_z, const Vector4 &p_w);
+	Projection(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_xw, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_yw, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_zw, real_t p_wx, real_t p_wy, real_t p_wz, real_t p_ww);
 	Projection(const Transform3D &p_transform);
 	~Projection();
 };

+ 1 - 1
src/core/class_db.cpp

@@ -389,7 +389,7 @@ void ClassDB::initialize_class(const ClassInfo &p_cl) {
 }
 
 void ClassDB::initialize(GDExtensionInitializationLevel p_level) {
-	for (const std::pair<StringName, ClassInfo> pair : classes) {
+	for (const std::pair<const StringName, ClassInfo> &pair : classes) {
 		const ClassInfo &cl = pair.second;
 		if (cl.level != p_level) {
 			continue;

+ 13 - 17
src/core/method_bind.cpp

@@ -32,32 +32,28 @@
 
 namespace godot {
 
-StringName MethodBind::get_name() const {
-	return name;
+void MethodBind::_set_const(bool p_const) {
+	_const = p_const;
 }
 
-void MethodBind::set_name(const StringName &p_name) {
-	name = p_name;
-}
-
-void MethodBind::set_argument_count(int p_count) {
-	argument_count = p_count;
+void MethodBind::_set_static(bool p_static) {
+	_static = p_static;
 }
 
-void MethodBind::set_const(bool p_const) {
-	_is_const = p_const;
+void MethodBind::_set_returns(bool p_returns) {
+	_returns = p_returns;
 }
 
-void MethodBind::set_return(bool p_return) {
-	_has_return = p_return;
+void MethodBind::_set_vararg(bool p_vararg) {
+	_vararg = p_vararg;
 }
 
-void MethodBind::set_static(bool p_static) {
-	_static = p_static;
+StringName MethodBind::get_name() const {
+	return name;
 }
 
-void MethodBind::set_vararg(bool p_vararg) {
-	_vararg = p_vararg;
+void MethodBind::set_name(const StringName &p_name) {
+	name = p_name;
 }
 
 void MethodBind::set_argument_names(const std::vector<StringName> &p_names) {
@@ -68,7 +64,7 @@ std::vector<StringName> MethodBind::get_argument_names() const {
 	return argument_names;
 }
 
-void MethodBind::generate_argument_types(int p_count) {
+void MethodBind::_generate_argument_types(int p_count) {
 	set_argument_count(p_count);
 
 	if (argument_types != nullptr) {

+ 7 - 0
src/variant/projection.cpp

@@ -913,6 +913,13 @@ Projection::Projection(const Vector4 &p_x, const Vector4 &p_y, const Vector4 &p_
 	columns[3] = p_w;
 }
 
+Projection::Projection(real_t p_xx, real_t p_xy, real_t p_xz, real_t p_xw, real_t p_yx, real_t p_yy, real_t p_yz, real_t p_yw, real_t p_zx, real_t p_zy, real_t p_zz, real_t p_zw, real_t p_wx, real_t p_wy, real_t p_wz, real_t p_ww) {
+	columns[0] = Vector4(p_xx, p_xy, p_xz, p_xw);
+	columns[1] = Vector4(p_yx, p_yy, p_yz, p_yw);
+	columns[2] = Vector4(p_zx, p_zy, p_zz, p_zw);
+	columns[3] = Vector4(p_wx, p_wy, p_wz, p_ww);
+}
+
 Projection::Projection(const Transform3D &p_transform) {
 	const Transform3D &tr = p_transform;
 	real_t *m = &columns[0][0];

+ 1 - 2
test/project/main.gd

@@ -18,8 +18,7 @@ func _ready():
 
 	# To string.
 	assert_equal(example.to_string(),'[ GDExtension::Example <--> Instance ID:%s ]' % example.get_instance_id())
-	# It appears there's a bug with instance ids :-(
-	#assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:[Wrapped:%s]' % $Example/ExampleMin.get_instance_id())
+	assert_equal($Example/ExampleMin.to_string(), 'ExampleMin:<ExampleMin#%s>' % $Example/ExampleMin.get_instance_id())
 
 	# Call static methods.
 	assert_equal(Example.test_static(9, 100), 109);

+ 7 - 7
tools/android.py

@@ -11,6 +11,11 @@ def options(opts):
         "Target Android API level",
         "21",
     )
+    opts.Add(
+        "ndk_version",
+        "Fully qualified version of ndk to use for compilation.",
+        "23.2.8568313",
+    )
     opts.Add(
         "ANDROID_HOME",
         "Path to your Android SDK installation. By default, uses ANDROID_HOME from your defined environment variables.",
@@ -22,14 +27,9 @@ def exists(env):
     return get_android_ndk_root(env) is not None
 
 
-# This must be kept in sync with the value in https://github.com/godotengine/godot/blob/master/platform/android/detect.py#L58.
-def get_ndk_version():
-    return "23.2.8568313"
-
-
 def get_android_ndk_root(env):
     if env["ANDROID_HOME"]:
-        return env["ANDROID_HOME"] + "/ndk/" + get_ndk_version()
+        return env["ANDROID_HOME"] + "/ndk/" + env["ndk_version"]
     else:
         return os.environ.get("ANDROID_NDK_ROOT")
 
@@ -68,7 +68,7 @@ def generate(env):
 
     if not os.path.exists(toolchain):
         print("ERROR: Could not find NDK toolchain at " + toolchain + ".")
-        print("Make sure NDK version " + get_ndk_version() + " is installed.")
+        print("Make sure NDK version " + env["ndk_version"] + " is installed.")
         env.Exit(1)
 
     env.PrependENVPath("PATH", toolchain + "/bin")  # This does nothing half of the time, but we'll put it here anyways

+ 14 - 0
tools/godotcpp.py

@@ -2,6 +2,7 @@ import os
 import platform
 import sys
 
+from SCons import __version__ as scons_raw_version
 from SCons.Action import Action
 from SCons.Builder import Builder
 from SCons.Errors import UserError
@@ -424,6 +425,8 @@ def make_doc_source(target, source, env):
 
 
 def generate(env):
+    env.scons_version = env._get_major_minor_revision(scons_raw_version)
+
     # Default num_jobs to local cpu count if not user specified.
     # SCons has a peculiarity where user-specified options won't be overridden
     # by SetOption, so we can rely on this to know if we should use our default.
@@ -481,6 +484,17 @@ def generate(env):
     else:  # Release
         opt_level = "speed"
 
+    # Allow marking includes as external/system to avoid raising warnings.
+    if env.scons_version < (4, 2):
+        env["_CPPEXTINCFLAGS"] = "${_concat(EXTINCPREFIX, CPPEXTPATH, EXTINCSUFFIX, __env__, RDirs, TARGET, SOURCE)}"
+    else:
+        env["_CPPEXTINCFLAGS"] = (
+            "${_concat(EXTINCPREFIX, CPPEXTPATH, EXTINCSUFFIX, __env__, RDirs, TARGET, SOURCE, affect_signature=False)}"
+        )
+    env["CPPEXTPATH"] = []
+    env["EXTINCPREFIX"] = "-isystem "
+    env["EXTINCSUFFIX"] = ""
+
     env["optimize"] = ARGUMENTS.get("optimize", opt_level)
     env["debug_symbols"] = get_cmdline_bool("debug_symbols", env.dev_build)
 

+ 2 - 0
tools/ios.py

@@ -36,9 +36,11 @@ def generate(env):
     if env["ios_simulator"]:
         sdk_name = "iphonesimulator"
         env.Append(CCFLAGS=["-mios-simulator-version-min=" + env["ios_min_version"]])
+        env.Append(LINKFLAGS=["-mios-simulator-version-min=" + env["ios_min_version"]])
     else:
         sdk_name = "iphoneos"
         env.Append(CCFLAGS=["-miphoneos-version-min=" + env["ios_min_version"]])
+        env.Append(LINKFLAGS=["-miphoneos-version-min=" + env["ios_min_version"]])
 
     if sys.platform == "darwin":
         if env["IOS_SDK_PATH"] == "":

+ 5 - 0
tools/windows.py

@@ -125,6 +125,11 @@ def generate(env):
         if env["silence_msvc"] and not env.GetOption("clean"):
             silence_msvc(env)
 
+        if not env["use_llvm"]:
+            env.AppendUnique(CCFLAGS=["/experimental:external", "/external:anglebrackets"])
+        env.AppendUnique(CCFLAGS=["/external:W0"])
+        env["EXTINCPREFIX"] = "/external:I"
+
     elif (sys.platform == "win32" or sys.platform == "msys") and not env["mingw_prefix"]:
         env["use_mingw"] = True
         mingw.generate(env)