From 03ea71774281ca3d889b584cfffd648173b73483 Mon Sep 17 00:00:00 2001 From: Mikael Hermansson Date: Thu, 12 Oct 2023 16:00:48 +0200 Subject: [PATCH 1/8] Declare explicit specializations for `CharStringT` (cherry picked from commit 6e05b978b8a824a892db328d12b2e418b4ac5eab) --- include/godot_cpp/variant/char_string.hpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/include/godot_cpp/variant/char_string.hpp b/include/godot_cpp/variant/char_string.hpp index f8f51696..fef6a718 100644 --- a/include/godot_cpp/variant/char_string.hpp +++ b/include/godot_cpp/variant/char_string.hpp @@ -120,6 +120,18 @@ protected: void copy_from(const T *p_cstr); }; +template <> +const char *CharStringT::get_data() const; + +template <> +const char16_t *CharStringT::get_data() const; + +template <> +const char32_t *CharStringT::get_data() const; + +template <> +const wchar_t *CharStringT::get_data() const; + typedef CharStringT CharString; typedef CharStringT Char16String; typedef CharStringT Char32String; From 62cb5eac475659e95f342dcc4e017acd1e9eb248 Mon Sep 17 00:00:00 2001 From: Fabio Alessandrelli Date: Sun, 15 Oct 2023 12:01:45 +0200 Subject: [PATCH 2/8] [SCons] Rename javascript tool to web And clean it up a bit. (cherry picked from commit 18bfa133ab3b6687fd742076cfd20ad7784d058d) --- .github/workflows/ci.yml | 10 +++++----- test/project/example.gdextension | 4 ++-- tools/godotcpp.py | 4 ++-- tools/{javascript.py => web.py} | 32 ++++++++++++++++---------------- 4 files changed, 25 insertions(+), 25 deletions(-) rename tools/{javascript.py => web.py} (69%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 36f8c08a..1f316ff7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,11 +80,11 @@ jobs: - name: 🌐 Web (wasm32) os: ubuntu-20.04 - platform: javascript - artifact-name: godot-cpp-javascript-wasm32-release - artifact-path: bin/libgodot-cpp.javascript.template_release.wasm32.a + platform: web + artifact-name: godot-cpp-web-wasm32-release + artifact-path: bin/libgodot-cpp.web.template_release.wasm32.a run-tests: false - cache-name: javascript-wasm32 + cache-name: web-wasm32 env: SCONS_CACHE: ${{ github.workspace }}/.scons-cache/ @@ -115,7 +115,7 @@ jobs: sudo apt-get install -qqq build-essential pkg-config - name: Web dependencies - if: ${{ matrix.platform == 'javascript' }} + if: ${{ matrix.platform == 'web' }} uses: mymindstorm/setup-emsdk@v12 with: version: ${{env.EM_VERSION}} diff --git a/test/project/example.gdextension b/test/project/example.gdextension index d4234613..30279e6d 100644 --- a/test/project/example.gdextension +++ b/test/project/example.gdextension @@ -21,5 +21,5 @@ android.debug.x86_64 = "res://bin/libgdexample.android.template_debug.x86_64.so" android.release.x86_64 = "res://bin/libgdexample.android.template_release.x86_64.so" android.debug.arm64 = "res://bin/libgdexample.android.template_debug.arm64.so" android.release.arm64 = "res://bin/libgdexample.android.template_release.arm64.so" -web.debug.wasm32 = "res://bin/libgdexample.javascript.template_debug.wasm32.wasm" -web.release.wasm32 = "res://bin/libgdexample.javascript.template_release.wasm32.wasm" +web.debug.wasm32 = "res://bin/libgdexample.web.template_debug.wasm32.wasm" +web.release.wasm32 = "res://bin/libgdexample.web.template_release.wasm32.wasm" diff --git a/tools/godotcpp.py b/tools/godotcpp.py index 969f8c41..d6128820 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -33,7 +33,7 @@ def validate_parent_dir(key, val, env): raise UserError("'%s' is not a directory: %s" % (key, os.path.dirname(val))) -platforms = ("linux", "macos", "windows", "android", "ios", "javascript") +platforms = ("linux", "macos", "windows", "android", "ios", "web") # CPU architecture options. architecture_array = [ @@ -214,7 +214,7 @@ def generate(env): env["arch"] = "universal" elif env["platform"] == "android": env["arch"] = "arm64" - elif env["platform"] == "javascript": + elif env["platform"] == "web": env["arch"] = "wasm32" else: host_machine = platform.machine().lower() diff --git a/tools/javascript.py b/tools/web.py similarity index 69% rename from tools/javascript.py rename to tools/web.py index e8f6af1c..a4620c37 100644 --- a/tools/javascript.py +++ b/tools/web.py @@ -11,34 +11,34 @@ def generate(env): print("Only wasm32 supported on web. Exiting.") env.Exit(1) + # Emscripten toolchain env["CC"] = "emcc" env["CXX"] = "em++" env["AR"] = "emar" env["RANLIB"] = "emranlib" - env.Append(CPPFLAGS=["-s", "SIDE_MODULE=1"]) - env.Append(LINKFLAGS=["-s", "SIDE_MODULE=1"]) - env["SHOBJSUFFIX"] = ".bc" - env["SHLIBSUFFIX"] = ".wasm" + # Use TempFileMunge since some AR invocations are too long for cmd.exe. # Use POSIX-style paths, required with TempFileMunge. env["ARCOM_POSIX"] = env["ARCOM"].replace("$TARGET", "$TARGET.posix").replace("$SOURCES", "$SOURCES.posix") env["ARCOM"] = "${TEMPFILE(ARCOM_POSIX)}" + # All intermediate files are just object files. + env["OBJSUFFIX"] = ".o" + env["SHOBJSUFFIX"] = ".o" + + # Static libraries clang-style. + env["LIBPREFIX"] = "lib" + env["LIBSUFFIX"] = ".a" + + # Shared library as wasm. + env["SHLIBSUFFIX"] = ".wasm" + # Thread support (via SharedArrayBuffer). env.Append(CCFLAGS=["-s", "USE_PTHREADS=1"]) env.Append(LINKFLAGS=["-s", "USE_PTHREADS=1"]) - # All intermediate files are just LLVM bitcode. - env["OBJPREFIX"] = "" - env["OBJSUFFIX"] = ".bc" - env["PROGPREFIX"] = "" - # Program() output consists of multiple files, so specify suffixes manually at builder. - env["PROGSUFFIX"] = "" - env["LIBPREFIX"] = "lib" - env["LIBSUFFIX"] = ".a" - env["LIBPREFIXES"] = ["$LIBPREFIX"] - env["LIBSUFFIXES"] = ["$LIBSUFFIX"] - env.Replace(SHLINKFLAGS="$LINKFLAGS") - env.Replace(SHLINKFLAGS="$LINKFLAGS") + # Build as side module (shared library). + env.Append(CPPFLAGS=["-s", "SIDE_MODULE=1"]) + env.Append(LINKFLAGS=["-s", "SIDE_MODULE=1"]) env.Append(CPPDEFINES=["WEB_ENABLED", "UNIX_ENABLED"]) From f7ffc4fe4dcda59a3e9fd0c7250972238cdf8e04 Mon Sep 17 00:00:00 2001 From: David Snopek Date: Wed, 11 Oct 2023 22:59:59 -0500 Subject: [PATCH 3/8] Automatically register only engine classes whose header has been included (cherry picked from commit b507b3e5913344a97e90ba27b221e28924f555ab) --- binding_generator.py | 64 +------------------ .../classes/editor_plugin_registration.hpp | 62 ++++++++++++++++++ include/godot_cpp/classes/wrapped.hpp | 21 ++++++ include/godot_cpp/core/class_db.hpp | 11 ++-- include/godot_cpp/godot.hpp | 3 - ...gin.cpp => editor_plugin_registration.cpp} | 6 +- src/classes/wrapped.cpp | 29 +++++++++ src/godot.cpp | 4 +- 8 files changed, 122 insertions(+), 78 deletions(-) create mode 100644 include/godot_cpp/classes/editor_plugin_registration.hpp rename src/classes/{editor_plugin.cpp => editor_plugin_registration.cpp} (95%) diff --git a/binding_generator.py b/binding_generator.py index 54ae9af6..18db9fd0 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -130,8 +130,6 @@ def get_file_list(api_filepath, output_dir, headers=False, sources=False): if sources: utility_functions_source_path = source_gen_folder / "variant" / "utility_functions.cpp" files.append(str(utility_functions_source_path.as_posix())) - register_engine_classes_source_path = source_gen_folder / "register_engine_classes.cpp" - files.append(str(register_engine_classes_source_path.as_posix())) return files @@ -1170,10 +1168,6 @@ def generate_engine_classes_bindings(api, output_dir, use_template_get_node): generate_engine_class_source(class_api, used_classes, fully_used_classes, use_template_get_node) ) - register_engine_classes_filename = Path(output_dir) / "src" / "register_engine_classes.cpp" - with register_engine_classes_filename.open("w+", encoding="utf-8") as source_file: - source_file.write(generate_register_engine_classes_source(api)) - for native_struct in api["native_structures"]: struct_name = native_struct["name"] snake_struct_name = camel_to_snake(struct_name) @@ -1248,7 +1242,7 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append(f"#include ") if class_name == "EditorPlugin": - result.append("#include ") + result.append("#include ") if len(fully_used_classes) > 0: result.append("") @@ -1400,30 +1394,6 @@ def generate_engine_class_header(class_api, used_classes, fully_used_classes, us result.append("};") result.append("") - if class_name == "EditorPlugin": - result.append("class EditorPlugins {") - result.append("private:") - result.append("\tstatic Vector plugin_classes;") - result.append("") - result.append("public:") - result.append("\tstatic void add_plugin_class(const StringName &p_class_name);") - result.append("\tstatic void remove_plugin_class(const StringName &p_class_name);") - result.append("\tstatic void deinitialize(GDExtensionInitializationLevel p_level);") - result.append("") - - result.append("\ttemplate ") - result.append("\tstatic void add_by_type() {") - result.append("\t\tadd_plugin_class(T::get_class_static());") - result.append("\t}") - - result.append("\ttemplate ") - result.append("\tstatic void remove_by_type() {") - result.append("\t\tremove_plugin_class(T::get_class_static());") - result.append("\t}") - - result.append("};") - result.append("") - result.append("} // namespace godot") result.append("") @@ -1648,38 +1618,6 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us return "\n".join(result) -def generate_register_engine_classes_source(api): - includes = [] - registrations = [] - - for class_api in api["classes"]: - if class_api["name"] == "ClassDB": - continue - - class_name = class_api["name"] - snake_class_name = camel_to_snake(class_name) - - includes.append(f"#include ") - registrations.append(f"\tClassDB::register_engine_class<{class_name}>();") - - result = [] - add_header(f"register_engine_classes.cpp", result) - - result.append("#include ") - result.append("") - result = result + includes - result.append("") - result.append("namespace godot {") - result.append("") - result.append("void GDExtensionBinding::register_engine_classes() {") - result = result + registrations - result.append("}") - result.append("") - result.append("} // namespace godot ") - - return "\n".join(result) - - def generate_global_constants(api, output_dir): include_gen_folder = Path(output_dir) / "include" / "godot_cpp" / "classes" source_gen_folder = Path(output_dir) / "src" / "classes" diff --git a/include/godot_cpp/classes/editor_plugin_registration.hpp b/include/godot_cpp/classes/editor_plugin_registration.hpp new file mode 100644 index 00000000..1ccde314 --- /dev/null +++ b/include/godot_cpp/classes/editor_plugin_registration.hpp @@ -0,0 +1,62 @@ +/**************************************************************************/ +/* editor_plugin_registration.hpp */ +/**************************************************************************/ +/* This file is part of: */ +/* GODOT ENGINE */ +/* https://godotengine.org */ +/**************************************************************************/ +/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ +/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */ +/* */ +/* Permission is hereby granted, free of charge, to any person obtaining */ +/* a copy of this software and associated documentation files (the */ +/* "Software"), to deal in the Software without restriction, including */ +/* without limitation the rights to use, copy, modify, merge, publish, */ +/* distribute, sublicense, and/or sell copies of the Software, and to */ +/* permit persons to whom the Software is furnished to do so, subject to */ +/* the following conditions: */ +/* */ +/* The above copyright notice and this permission notice shall be */ +/* included in all copies or substantial portions of the Software. */ +/* */ +/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */ +/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */ +/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ +/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */ +/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */ +/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */ +/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +/**************************************************************************/ + +#ifndef GODOT_EDITOR_PLUGIN_REGISTRATION_HPP +#define GODOT_EDITOR_PLUGIN_REGISTRATION_HPP + +#include + +namespace godot { + +class EditorPlugin; +class StringName; + +class EditorPlugins { +private: + static Vector plugin_classes; + +public: + static void add_plugin_class(const StringName &p_class_name); + static void remove_plugin_class(const StringName &p_class_name); + static void deinitialize(GDExtensionInitializationLevel p_level); + + template + static void add_by_type() { + add_plugin_class(T::get_class_static()); + } + template + static void remove_by_type() { + remove_plugin_class(T::get_class_static()); + } +}; + +} // namespace godot + +#endif // GODOT_EDITOR_PLUGIN_REGISTRATION_HPP diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 00d36798..83a6fe09 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -95,6 +95,26 @@ public: GodotObject *_owner = nullptr; }; +namespace internal { + +typedef void (*EngineClassRegistrationCallback)(); +void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback); +void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks); +void register_engine_classes(); + +template +struct EngineClassRegistration { + EngineClassRegistration() { + add_engine_class_registration_callback(&EngineClassRegistration::callback); + } + + static void callback() { + register_engine_class(T::get_class_static(), &T::_gde_binding_callbacks); + } +}; + +} // namespace internal + } // namespace godot #define GDCLASS(m_class, m_inherits) \ @@ -308,6 +328,7 @@ public: // Don't use this for your classes, use GDCLASS() instead. #define GDEXTENSION_CLASS_ALIAS(m_class, m_alias_for, m_inherits) \ private: \ + inline static ::godot::internal::EngineClassRegistration _gde_engine_class_registration_helper; \ void operator=(const m_class &p_rval) {} \ \ protected: \ diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index 5c3f2dbc..46032fb9 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -122,8 +122,10 @@ public: static void register_class(bool p_virtual = false); template static void register_abstract_class(); - template - static void register_engine_class(); + + _FORCE_INLINE_ static void _register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) { + instance_binding_callbacks[p_name] = p_callbacks; + } template static MethodBind *bind_method(N p_method_name, M p_method, VarArgs... p_args); @@ -226,11 +228,6 @@ void ClassDB::register_abstract_class() { ClassDB::_register_class(); } -template -void ClassDB::register_engine_class() { - instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks; -} - template MethodBind *ClassDB::bind_method(N p_method_name, M p_method, VarArgs... p_args) { Variant args[sizeof...(p_args) + 1] = { p_args..., Variant() }; // +1 makes sure zero sized arrays are also supported. diff --git a/include/godot_cpp/godot.hpp b/include/godot_cpp/godot.hpp index 2e28ad3f..1478403b 100644 --- a/include/godot_cpp/godot.hpp +++ b/include/godot_cpp/godot.hpp @@ -191,9 +191,6 @@ enum ModuleInitializationLevel { }; class GDExtensionBinding { -private: - static void register_engine_classes(); - public: using Callback = void (*)(ModuleInitializationLevel p_level); diff --git a/src/classes/editor_plugin.cpp b/src/classes/editor_plugin_registration.cpp similarity index 95% rename from src/classes/editor_plugin.cpp rename to src/classes/editor_plugin_registration.cpp index ca98a892..99819bee 100644 --- a/src/classes/editor_plugin.cpp +++ b/src/classes/editor_plugin_registration.cpp @@ -1,5 +1,5 @@ /**************************************************************************/ -/* editor_plugin.cpp */ +/* editor_plugin_registration.cpp */ /**************************************************************************/ /* This file is part of: */ /* GODOT ENGINE */ @@ -28,9 +28,9 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ -#include +#include -#include +#include namespace godot { diff --git a/src/classes/wrapped.cpp b/src/classes/wrapped.cpp index 62088a51..2c5e1b60 100644 --- a/src/classes/wrapped.cpp +++ b/src/classes/wrapped.cpp @@ -28,12 +28,16 @@ /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /**************************************************************************/ +#include + #include #include #include +#include + namespace godot { const StringName *Wrapped::_get_extension_class_name() const { @@ -60,4 +64,29 @@ void postinitialize_handler(Wrapped *p_wrapped) { p_wrapped->_postinitialize(); } +namespace internal { + +std::vector &get_engine_class_registration_callbacks() { + static std::vector engine_class_registration_callbacks; + return engine_class_registration_callbacks; +} + +void add_engine_class_registration_callback(EngineClassRegistrationCallback p_callback) { + get_engine_class_registration_callbacks().push_back(p_callback); +} + +void register_engine_class(const StringName &p_name, const GDExtensionInstanceBindingCallbacks *p_callbacks) { + ClassDB::_register_engine_class(p_name, p_callbacks); +} + +void register_engine_classes() { + std::vector &engine_class_registration_callbacks = get_engine_class_registration_callbacks(); + for (EngineClassRegistrationCallback cb : engine_class_registration_callbacks) { + cb(); + } + engine_class_registration_callbacks.clear(); +} + +} // namespace internal + } // namespace godot diff --git a/src/godot.cpp b/src/godot.cpp index bc0a3c69..14214c0d 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -30,7 +30,7 @@ #include -#include +#include #include #include #include @@ -406,7 +406,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge ERR_FAIL_NULL_V_MSG(init_callback, false, "Initialization callback must be defined."); Variant::init_bindings(); - register_engine_classes(); + godot::internal::register_engine_classes(); return true; } From 7704a9d05450b520ec81087f0fdc0a84307f9b89 Mon Sep 17 00:00:00 2001 From: Thaddeus Crews Date: Mon, 2 Oct 2023 13:31:06 -0500 Subject: [PATCH 4/8] Let gdextension_dir function as only argument (cherry picked from commit 7a5cbcac21a96fcdd1a7cea0e4f81bca99d4df7a) --- tools/godotcpp.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/godotcpp.py b/tools/godotcpp.py index d6128820..ac680e15 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -273,8 +273,8 @@ def generate(env): def _godot_cpp(env): - api_file = normalize_path(env.get("custom_api_file", env.File("gdextension/extension_api.json").abspath), env) extension_dir = normalize_path(env.get("gdextension_dir", env.Dir("gdextension").abspath), env) + api_file = normalize_path(env.get("custom_api_file", env.File(extension_dir + "/extension_api.json").abspath), env) bindings = env.GodotCPPBindings( env.Dir("."), [ From 8295486fdb99e9de9315a327148348f1b3ac0f3b Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Mon, 4 Sep 2023 15:00:42 -0400 Subject: [PATCH 5/8] Refactor compiledb implementation This comment enables the possibility to build the "compile_commands.json" file by only using `scons -Q compiledb`. No need to use the argument `compiledb=yes`. And when using the `compiledb=yes`, it will create a "compiled_commands.json" automatically. (cherry picked from commit 2d5024ac8ec623b91308df6225028de30a9cf2d0) --- tools/godotcpp.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tools/godotcpp.py b/tools/godotcpp.py index ac680e15..2b0c19c3 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -263,9 +263,8 @@ def generate(env): env["OBJSUFFIX"] = suffix + env["OBJSUFFIX"] # compile_commands.json - if env.get("compiledb", False): - env.Tool("compilation_db") - env.Alias("compiledb", env.CompilationDatabase(normalize_path(env["compiledb_file"], env))) + env.Tool("compilation_db") + env.Alias("compiledb", env.CompilationDatabase(normalize_path(env["compiledb_file"], env))) # Builders env.Append(BUILDERS={"GodotCPPBindings": Builder(action=scons_generate_bindings, emitter=scons_emit_files)}) @@ -304,7 +303,13 @@ def _godot_cpp(env): if env["build_library"]: library = env.StaticLibrary(target=env.File("bin/%s" % library_name), source=sources) - env.Default(library) + default_args = [library] + + # Add compiledb if the option is set + if env.get("compiledb", False): + default_args += ["compiledb"] + + env.Default(*default_args) env.AppendUnique(LIBS=[env.File("bin/%s" % library_name)]) return library From 698da13d664cc270056b64d572ffd1250f580b45 Mon Sep 17 00:00:00 2001 From: gilzoide Date: Sun, 24 Sep 2023 17:10:29 -0300 Subject: [PATCH 6/8] Fix return value and r_valid value in Variant::iter_init and iter_next (cherry picked from commit 60dfa3445a84c479dd138c5ca26049fab69e3f01) --- src/variant/variant.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/variant/variant.cpp b/src/variant/variant.cpp index 641f59c7..db15be11 100644 --- a/src/variant/variant.cpp +++ b/src/variant/variant.cpp @@ -638,14 +638,16 @@ bool Variant::in(const Variant &index, bool *r_valid) const { bool Variant::iter_init(Variant &r_iter, bool &r_valid) const { GDExtensionBool valid; - internal::gdextension_interface_variant_iter_init(_native_ptr(), r_iter._native_ptr(), &valid); - return PtrToArg::convert(&valid); + GDExtensionBool result = internal::gdextension_interface_variant_iter_init(_native_ptr(), r_iter._native_ptr(), &valid); + r_valid = PtrToArg::convert(&valid); + return PtrToArg::convert(&result); } bool Variant::iter_next(Variant &r_iter, bool &r_valid) const { GDExtensionBool valid; - internal::gdextension_interface_variant_iter_next(_native_ptr(), r_iter._native_ptr(), &valid); - return PtrToArg::convert(&valid); + GDExtensionBool result = internal::gdextension_interface_variant_iter_next(_native_ptr(), r_iter._native_ptr(), &valid); + r_valid = PtrToArg::convert(&valid); + return PtrToArg::convert(&result); } Variant Variant::iter_get(const Variant &r_iter, bool &r_valid) const { From ef8a499eac338c3ba537e378a666b7fa52c736d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9mi=20Verschelde?= Date: Wed, 16 Aug 2023 11:47:19 +0200 Subject: [PATCH 7/8] SCons: Disable C++ exception handling by default Counterpart to https://github.com/godotengine/godot/pull/80612. (cherry picked from commit bf1c03ab5f079d0931cf4390e7435a20cfaacfbd) --- CMakeLists.txt | 26 +++++++++++++++++++++----- test/CMakeLists.txt | 17 ++++++++++++++++- tools/godotcpp.py | 18 ++++++++++++++++++ tools/windows.py | 2 +- 4 files changed, 56 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 0ee99aae..c413cecc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -72,21 +72,22 @@ endif() # Input from user for GDExtension interface header and the API JSON file set(GODOT_GDEXTENSION_DIR "gdextension" CACHE STRING "") set(GODOT_CUSTOM_API_FILE "" CACHE STRING "") -set(FLOAT_PRECISION "single" CACHE STRING "") -if ("${FLOAT_PRECISION}" STREQUAL "double") - add_definitions(-DREAL_T_IS_DOUBLE) -endif() set(GODOT_GDEXTENSION_API_FILE "${GODOT_GDEXTENSION_DIR}/extension_api.json") if (NOT "${GODOT_CUSTOM_API_FILE}" STREQUAL "") # User-defined override. set(GODOT_GDEXTENSION_API_FILE "${GODOT_CUSTOM_API_FILE}") endif() +set(FLOAT_PRECISION "single" CACHE STRING "") +if ("${FLOAT_PRECISION}" STREQUAL "double") + add_definitions(-DREAL_T_IS_DOUBLE) +endif() + set(GODOT_COMPILE_FLAGS ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # using Visual Studio C++ - set(GODOT_COMPILE_FLAGS "/EHsc /utf-8") # /GF /MP + set(GODOT_COMPILE_FLAGS "/utf-8") # /GF /MP if(CMAKE_BUILD_TYPE MATCHES Debug) set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /MDd") # /Od /RTC1 /Zi @@ -107,6 +108,21 @@ else() # GCC/Clang endif(CMAKE_BUILD_TYPE MATCHES Debug) endif() +# Disable exception handling. Godot doesn't use exceptions anywhere, and this +# saves around 20% of binary size and very significant build time (GH-80513). +option(GODOT_DISABLE_EXCEPTIONS OFF "Force disabling exception handling code") +if (GODOT_DISABLE_EXCEPTIONS) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0") + else() + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions") + endif() +else() + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc") + endif() +endif() + # Generate source from the bindings file find_package(Python3 3.4 REQUIRED) # pathlib should be present if(GENERATE_TEMPLATE_GET_NODE) diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 0538c5d7..9d692e6a 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -36,7 +36,7 @@ set(GODOT_LINKER_FLAGS ) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") # using Visual Studio C++ - set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc /WX") # /GF /MP + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /WX") # /GF /MP set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /DTYPED_METHOD_BIND") if(CMAKE_BUILD_TYPE MATCHES Debug) @@ -92,6 +92,21 @@ else() endif(CMAKE_BUILD_TYPE MATCHES Debug) endif() +# Disable exception handling. Godot doesn't use exceptions anywhere, and this +# saves around 20% of binary size and very significant build time (GH-80513). +option(GODOT_DISABLE_EXCEPTIONS OFF "Force disabling exception handling code") +if (GODOT_DISABLE_EXCEPTIONS) + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -D_HAS_EXCEPTIONS=0") + else() + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} -fno-exceptions") + endif() +else() + if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") + set(GODOT_COMPILE_FLAGS "${GODOT_COMPILE_FLAGS} /EHsc") + endif() +endif() + # Get Sources file(GLOB_RECURSE SOURCES src/*.c**) file(GLOB_RECURSE HEADERS include/*.h**) diff --git a/tools/godotcpp.py b/tools/godotcpp.py index 2b0c19c3..925b214d 100644 --- a/tools/godotcpp.py +++ b/tools/godotcpp.py @@ -175,6 +175,14 @@ def options(opts, env): ) ) + opts.Add( + BoolVariable( + "disable_exceptions", + "Force disabling exception handling code", + default=env.get("disable_exceptions", False), + ) + ) + # Add platform options for pl in platforms: tool = Tool(pl, toolpath=["tools"]) @@ -231,6 +239,16 @@ def generate(env): print("Building for architecture " + env["arch"] + " on platform " + env["platform"]) + # Disable exception handling. Godot doesn't use exceptions anywhere, and this + # saves around 20% of binary size and very significant build time. + if env["disable_exceptions"]: + if env.get("is_msvc", False): + env.Append(CPPDEFINES=[("_HAS_EXCEPTIONS", 0)]) + else: + env.Append(CXXFLAGS=["-fno-exceptions"]) + elif env.get("is_msvc", False): + env.Append(CXXFLAGS=["/EHsc"]) + tool = Tool(env["platform"], toolpath=["tools"]) if tool is None or not tool.exists(env): diff --git a/tools/windows.py b/tools/windows.py index e156aefb..d5a729c5 100644 --- a/tools/windows.py +++ b/tools/windows.py @@ -31,7 +31,7 @@ def generate(env): env.Tool("mslink") env.Append(CPPDEFINES=["TYPED_METHOD_BIND", "NOMINMAX"]) - env.Append(CCFLAGS=["/EHsc", "/utf-8"]) + env.Append(CCFLAGS=["/utf-8"]) env.Append(LINKFLAGS=["/WX"]) if env["use_clang_cl"]: From 9d813310bb6f26875892bed67df8e169dbc0b0fa Mon Sep 17 00:00:00 2001 From: David Snopek Date: Sat, 21 Oct 2023 17:54:46 -0500 Subject: [PATCH 8/8] Add protections against registering classes that didn't use GDCLASS() (cherry picked from commit a61cdc88606fbd0230555f1657d0cd635ba4bb5b) --- include/godot_cpp/classes/wrapped.hpp | 15 +++++++++++++++ include/godot_cpp/core/class_db.hpp | 1 + 2 files changed, 16 insertions(+) diff --git a/include/godot_cpp/classes/wrapped.hpp b/include/godot_cpp/classes/wrapped.hpp index 83a6fe09..ed923c1c 100644 --- a/include/godot_cpp/classes/wrapped.hpp +++ b/include/godot_cpp/classes/wrapped.hpp @@ -170,6 +170,8 @@ protected: } \ \ public: \ + typedef m_class self_type; \ + \ static void initialize_class() { \ static bool initialized = false; \ if (initialized) { \ @@ -372,6 +374,8 @@ protected: } \ \ public: \ + typedef m_class self_type; \ + \ static void initialize_class() {} \ \ static ::godot::StringName &get_class_static() { \ @@ -381,6 +385,17 @@ public: \ static ::godot::StringName &get_parent_class_static() { \ return m_inherits::get_class_static(); \ + } \ + \ + static GDExtensionObjectPtr create(void *data) { \ + return nullptr; \ + } \ + \ + static GDExtensionClassInstancePtr recreate(void *data, GDExtensionObjectPtr obj) { \ + return nullptr; \ + } \ + \ + static void free(void *data, GDExtensionClassInstancePtr ptr) { \ } \ \ static void *_gde_binding_create_callback(void *p_token, void *p_instance) { \ diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index 46032fb9..bafd2ce1 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -173,6 +173,7 @@ public: template void ClassDB::_register_class(bool p_virtual) { + static_assert(TypesAreSame::value, "Class not declared properly, please use GDCLASS."); instance_binding_callbacks[T::get_class_static()] = &T::_gde_binding_callbacks; // Register this class within our plugin