From 205beacc5bc37faf7ef82d4c55ec08b730fcb76a Mon Sep 17 00:00:00 2001 From: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> Date: Tue, 12 Sep 2023 15:33:49 +0200 Subject: [PATCH 1/6] Replace `ERR_FAIL_COND` with `ERR_FAIL_NULL` where applicable (cherry picked from commit 1e5767693e45f58e2ffdc45d4c4f26057e25a2d6) --- binding_generator.py | 4 ++-- include/godot_cpp/classes/ref.hpp | 2 +- include/godot_cpp/core/class_db.hpp | 2 +- include/godot_cpp/core/memory.hpp | 2 +- include/godot_cpp/templates/cowdata.hpp | 6 +++--- include/godot_cpp/templates/list.hpp | 2 +- include/godot_cpp/templates/rid_owner.hpp | 6 +++--- include/godot_cpp/templates/thread_work_pool.hpp | 8 ++++---- src/core/class_db.cpp | 4 ++-- src/core/memory.cpp | 4 ++-- src/godot.cpp | 2 +- 11 files changed, 21 insertions(+), 21 deletions(-) diff --git a/binding_generator.py b/binding_generator.py index 7491103e..54ae9af6 100644 --- a/binding_generator.py +++ b/binding_generator.py @@ -1519,13 +1519,13 @@ def generate_engine_class_source(class_api, used_classes, fully_used_classes, us f"\t\tGDExtensionObjectPtr singleton_obj = internal::gdextension_interface_global_get_singleton({class_name}::get_class_static()._native_ptr());" ) result.append("#ifdef DEBUG_ENABLED") - result.append("\t\tERR_FAIL_COND_V(singleton_obj == nullptr, nullptr);") + result.append("\t\tERR_FAIL_NULL_V(singleton_obj, nullptr);") result.append("#endif // DEBUG_ENABLED") result.append( f"\t\tsingleton = reinterpret_cast<{class_name} *>(internal::gdextension_interface_object_get_instance_binding(singleton_obj, internal::token, &{class_name}::_gde_binding_callbacks));" ) result.append("#ifdef DEBUG_ENABLED") - result.append("\t\tERR_FAIL_COND_V(singleton == nullptr, nullptr);") + result.append("\t\tERR_FAIL_NULL_V(singleton, nullptr);") result.append("#endif // DEBUG_ENABLED") result.append("\t}") result.append("\treturn singleton;") diff --git a/include/godot_cpp/classes/ref.hpp b/include/godot_cpp/classes/ref.hpp index f30928ac..f3fc3e94 100644 --- a/include/godot_cpp/classes/ref.hpp +++ b/include/godot_cpp/classes/ref.hpp @@ -63,7 +63,7 @@ class Ref { } void ref_pointer(T *p_ref) { - ERR_FAIL_COND(!p_ref); + ERR_FAIL_NULL(p_ref); if (p_ref->init_ref()) { reference = p_ref; diff --git a/include/godot_cpp/core/class_db.hpp b/include/godot_cpp/core/class_db.hpp index 26dfb7eb..5c3f2dbc 100644 --- a/include/godot_cpp/core/class_db.hpp +++ b/include/godot_cpp/core/class_db.hpp @@ -257,7 +257,7 @@ MethodBind *ClassDB::bind_static_method(StringName p_class, N p_method_name, M p template MethodBind *ClassDB::bind_vararg_method(uint32_t p_flags, StringName p_name, M p_method, const MethodInfo &p_info, const std::vector &p_default_args, bool p_return_nil_is_variant) { MethodBind *bind = create_vararg_method_bind(p_method, p_info, p_return_nil_is_variant); - ERR_FAIL_COND_V(!bind, nullptr); + ERR_FAIL_NULL_V(bind, nullptr); bind->set_name(p_name); bind->set_default_arguments(p_default_args); diff --git a/include/godot_cpp/core/memory.hpp b/include/godot_cpp/core/memory.hpp index dd4a155d..548f3301 100644 --- a/include/godot_cpp/core/memory.hpp +++ b/include/godot_cpp/core/memory.hpp @@ -146,7 +146,7 @@ T *memnew_arr_template(size_t p_elements, const char *p_descr = "") { size_t len = sizeof(T) * p_elements; uint64_t *mem = (uint64_t *)Memory::alloc_static(len, true); T *failptr = nullptr; // Get rid of a warning. - ERR_FAIL_COND_V(!mem, failptr); + ERR_FAIL_NULL_V(mem, failptr); *(mem - 1) = p_elements; if (!std::is_trivially_destructible::value) { diff --git a/include/godot_cpp/templates/cowdata.hpp b/include/godot_cpp/templates/cowdata.hpp index d3ea982b..121351b8 100644 --- a/include/godot_cpp/templates/cowdata.hpp +++ b/include/godot_cpp/templates/cowdata.hpp @@ -294,7 +294,7 @@ Error CowData::resize(int p_size) { if (current_size == 0) { // alloc from scratch uint32_t *ptr = (uint32_t *)Memory::alloc_static(alloc_size, true); - ERR_FAIL_COND_V(!ptr, ERR_OUT_OF_MEMORY); + ERR_FAIL_NULL_V(ptr, ERR_OUT_OF_MEMORY); *(ptr - 1) = 0; // size, currently none new (ptr - 2) SafeNumeric(1); // refcount @@ -302,7 +302,7 @@ Error CowData::resize(int p_size) { } else { uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true); - ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY); + ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY); new (_ptrnew - 2) SafeNumeric(rc); // refcount _ptr = (T *)(_ptrnew); @@ -332,7 +332,7 @@ Error CowData::resize(int p_size) { if (alloc_size != current_alloc_size) { uint32_t *_ptrnew = (uint32_t *)Memory::realloc_static(_ptr, alloc_size, true); - ERR_FAIL_COND_V(!_ptrnew, ERR_OUT_OF_MEMORY); + ERR_FAIL_NULL_V(_ptrnew, ERR_OUT_OF_MEMORY); new (_ptrnew - 2) SafeNumeric(rc); // refcount _ptr = (T *)(_ptrnew); diff --git a/include/godot_cpp/templates/list.hpp b/include/godot_cpp/templates/list.hpp index 36285f8b..2c8a7c87 100644 --- a/include/godot_cpp/templates/list.hpp +++ b/include/godot_cpp/templates/list.hpp @@ -221,7 +221,7 @@ private: int size_cache = 0; bool erase(const Element *p_I) { - ERR_FAIL_COND_V(!p_I, false); + ERR_FAIL_NULL_V(p_I, false); ERR_FAIL_COND_V(p_I->data != this, false); if (first == p_I) { diff --git a/include/godot_cpp/templates/rid_owner.hpp b/include/godot_cpp/templates/rid_owner.hpp index 93a83567..005fc876 100644 --- a/include/godot_cpp/templates/rid_owner.hpp +++ b/include/godot_cpp/templates/rid_owner.hpp @@ -186,12 +186,12 @@ public: } void initialize_rid(RID p_rid) { T *mem = get_or_null(p_rid, true); - ERR_FAIL_COND(!mem); + ERR_FAIL_NULL(mem); memnew_placement(mem, T); } void initialize_rid(RID p_rid, const T &p_value) { T *mem = get_or_null(p_rid, true); - ERR_FAIL_COND(!mem); + ERR_FAIL_NULL(mem); memnew_placement(mem, T(p_value)); } @@ -374,7 +374,7 @@ public: _FORCE_INLINE_ void replace(const RID &p_rid, T *p_new_ptr) { T **ptr = alloc.get_or_null(p_rid); - ERR_FAIL_COND(!ptr); + ERR_FAIL_NULL(ptr); *ptr = p_new_ptr; } diff --git a/include/godot_cpp/templates/thread_work_pool.hpp b/include/godot_cpp/templates/thread_work_pool.hpp index 85245b4f..a3efd42e 100644 --- a/include/godot_cpp/templates/thread_work_pool.hpp +++ b/include/godot_cpp/templates/thread_work_pool.hpp @@ -96,7 +96,7 @@ class ThreadWorkPool { public: template void begin_work(uint32_t p_elements, C *p_instance, M p_method, U p_userdata) { - ERR_FAIL_COND(!threads); // never initialized + ERR_FAIL_NULL(threads); // Never initialized. ERR_FAIL_COND(current_work != nullptr); index.store(0, std::memory_order_release); @@ -123,18 +123,18 @@ public: } bool is_done_dispatching() const { - ERR_FAIL_COND_V(current_work == nullptr, true); + ERR_FAIL_NULL_V(current_work, true); return index.load(std::memory_order_acquire) >= current_work->max_elements; } uint32_t get_work_index() const { - ERR_FAIL_COND_V(current_work == nullptr, 0); + ERR_FAIL_NULL_V(current_work, 0); uint32_t idx = index.load(std::memory_order_acquire); return Math::min(idx, current_work->max_elements); } void end_work() { - ERR_FAIL_COND(current_work == nullptr); + ERR_FAIL_NULL(current_work); for (uint32_t i = 0; i < threads_working; i++) { threads[i].completed.wait(); threads[i].work = nullptr; diff --git a/src/core/class_db.cpp b/src/core/class_db.cpp index e8bb40c6..863d97bf 100644 --- a/src/core/class_db.cpp +++ b/src/core/class_db.cpp @@ -77,7 +77,7 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf if (p_setter != String("")) { setter = get_method(p_class, p_setter); - ERR_FAIL_COND_MSG(!setter, String("Setter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_setter, p_class, p_pinfo.name))); + ERR_FAIL_NULL_MSG(setter, String("Setter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_setter, p_class, p_pinfo.name))); size_t exp_args = 1 + (p_index >= 0 ? 1 : 0); ERR_FAIL_COND_MSG((int)exp_args != setter->get_argument_count(), String("Setter method '{0}::{1}()' must take a single argument.").format(Array::make(p_class, p_setter))); @@ -86,7 +86,7 @@ void ClassDB::add_property(const StringName &p_class, const PropertyInfo &p_pinf ERR_FAIL_COND_MSG(p_getter == String(""), String("Getter method must be specified for '{0}::{1}'.").format(Array::make(p_class, p_pinfo.name))); MethodBind *getter = get_method(p_class, p_getter); - ERR_FAIL_COND_MSG(!getter, String("Getter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_getter, p_class, p_pinfo.name))); + ERR_FAIL_NULL_MSG(getter, String("Getter method '{0}::{1}()' not found for property '{2}::{3}'.").format(Array::make(p_class, p_getter, p_class, p_pinfo.name))); { size_t exp_args = 0 + (p_index >= 0 ? 1 : 0); ERR_FAIL_COND_MSG((int)exp_args != getter->get_argument_count(), String("Getter method '{0}::{1}()' must not take any argument.").format(Array::make(p_class, p_getter))); diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 17b06964..80e71ec5 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -42,7 +42,7 @@ void *Memory::alloc_static(size_t p_bytes, bool p_pad_align) { #endif void *mem = internal::gdextension_interface_mem_alloc(p_bytes + (prepad ? PAD_ALIGN : 0)); - ERR_FAIL_COND_V(!mem, nullptr); + ERR_FAIL_NULL_V(mem, nullptr); if (prepad) { uint8_t *s8 = (uint8_t *)mem; @@ -71,7 +71,7 @@ void *Memory::realloc_static(void *p_memory, size_t p_bytes, bool p_pad_align) { if (prepad) { mem -= PAD_ALIGN; mem = (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes + PAD_ALIGN); - ERR_FAIL_COND_V(!mem, nullptr); + ERR_FAIL_NULL_V(mem, nullptr); return mem + PAD_ALIGN; } else { return (uint8_t *)internal::gdextension_interface_mem_realloc(mem, p_bytes); diff --git a/src/godot.cpp b/src/godot.cpp index 9855f656..bc0a3c69 100644 --- a/src/godot.cpp +++ b/src/godot.cpp @@ -403,7 +403,7 @@ GDExtensionBool GDExtensionBinding::init(GDExtensionInterfaceGetProcAddress p_ge r_initialization->deinitialize = deinitialize_level; r_initialization->minimum_initialization_level = minimum_initialization_level; - ERR_FAIL_COND_V_MSG(init_callback == nullptr, false, "Initialization callback must be defined."); + ERR_FAIL_NULL_V_MSG(init_callback, false, "Initialization callback must be defined."); Variant::init_bindings(); register_engine_classes(); From 59ebcfd7448d376efe3b87a70388da6876a76e36 Mon Sep 17 00:00:00 2001 From: A Thousand Ships <96648715+AThousandShips@users.noreply.github.com> Date: Tue, 19 Sep 2023 15:20:02 +0200 Subject: [PATCH 2/6] Fix allocation size overflow check in `CowData` (cherry picked from commit 06ffc7e9522d749afb9489c9739538e562799a93) --- include/godot_cpp/templates/cowdata.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/include/godot_cpp/templates/cowdata.hpp b/include/godot_cpp/templates/cowdata.hpp index 121351b8..9b36538d 100644 --- a/include/godot_cpp/templates/cowdata.hpp +++ b/include/godot_cpp/templates/cowdata.hpp @@ -102,6 +102,10 @@ private: } _FORCE_INLINE_ bool _get_alloc_size_checked(size_t p_elements, size_t *out) const { + if (unlikely(p_elements == 0)) { + *out = 0; + return true; + } #if defined(__GNUC__) size_t o; size_t p; @@ -113,13 +117,12 @@ private: if (__builtin_add_overflow(o, static_cast(32), &p)) { return false; // No longer allocated here. } - return true; #else // Speed is more important than correctness here, do the operations unchecked // and hope for the best. *out = _get_alloc_size(p_elements); - return true; #endif + return *out; } void _unref(void *p_data); From f8054cca80dae553dd0cd8d020c7ac42655123d8 Mon Sep 17 00:00:00 2001 From: Adam Scott Date: Thu, 17 Aug 2023 09:28:44 -0400 Subject: [PATCH 3/6] Add support to import custom variables from parent SConstruct (redux) (cherry picked from commit 982e01ec7f2eb38b725282e82584cbce201c0cce) --- SConstruct | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/SConstruct b/SConstruct index e8817b07..b86ccf6f 100644 --- a/SConstruct +++ b/SConstruct @@ -21,6 +21,10 @@ env.PrependENVPath("PATH", os.getenv("PATH")) # Custom options and profile flags. customs = ["custom.py"] +try: + customs += Import("customs") +except: + pass profile = ARGUMENTS.get("profile", "") if profile: if os.path.isfile(profile): From ec6e51b3a4bbd649655ed9343bfc3171ce2cb856 Mon Sep 17 00:00:00 2001 From: David Snopek Date: Thu, 6 Jul 2023 21:39:19 -0500 Subject: [PATCH 4/6] Handle missing instance binding callbacks by finding the closest parent (cherry picked from commit 52ca3ef547b5586fd0a085c5b01a08b8f95332ca) --- src/core/class_db.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/core/class_db.cpp b/src/core/class_db.cpp index 863d97bf..702df993 100644 --- a/src/core/class_db.cpp +++ b/src/core/class_db.cpp @@ -318,7 +318,18 @@ GDExtensionClassCallVirtual ClassDB::get_virtual_func(void *p_userdata, GDExtens const GDExtensionInstanceBindingCallbacks *ClassDB::get_instance_binding_callbacks(const StringName &p_class) { std::unordered_map::iterator callbacks_it = instance_binding_callbacks.find(p_class); - ERR_FAIL_COND_V_MSG(callbacks_it == instance_binding_callbacks.end(), nullptr, String("Cannot find instance binding callbacks for class '{0}'.").format(Array::make(p_class))); + if (likely(callbacks_it != instance_binding_callbacks.end())) { + return callbacks_it->second; + } + + // If we don't have an instance binding callback for the given class, find the closest parent where we do. + StringName class_name = p_class; + do { + class_name = get_parent_class(class_name); + ERR_FAIL_COND_V_MSG(class_name == StringName(), nullptr, String("Cannot find instance binding callbacks for class '{0}'.").format(Array::make(p_class))); + callbacks_it = instance_binding_callbacks.find(class_name); + } while (callbacks_it == instance_binding_callbacks.end()); + return callbacks_it->second; } From 857d8e3a568d2919017f7aae06bf5d980baba8f0 Mon Sep 17 00:00:00 2001 From: Matthew Murphy Date: Fri, 27 Jan 2023 23:43:01 -0500 Subject: [PATCH 5/6] Fix variant call compiler error Co-authored-by: David Snopek (cherry picked from commit ca3e25de040c87de1a9bb332c62cfaef0d44fe75) --- include/godot_cpp/variant/variant.hpp | 20 ++++++++++++++------ src/variant/variant.cpp | 4 ++-- test/project/main.gd | 7 +++++++ test/src/example.cpp | 6 ++++++ test/src/example.h | 3 +++ 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/include/godot_cpp/variant/variant.hpp b/include/godot_cpp/variant/variant.hpp index 06ba75f6..0a2b3d14 100644 --- a/include/godot_cpp/variant/variant.hpp +++ b/include/godot_cpp/variant/variant.hpp @@ -255,25 +255,33 @@ public: bool operator!=(const Variant &other) const; bool operator<(const Variant &other) const; - void call(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error); + void callp(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error); template Variant call(const StringName &method, Args... args) { + std::array vargs = { args... }; + std::array argptrs; + for (size_t i = 0; i < vargs.size(); i++) { + argptrs[i] = &vargs[i]; + } Variant result; GDExtensionCallError error; - std::array call_args = { Variant(args)... }; - call(method, call_args.data(), call_args.size(), result, error); + callp(method, argptrs.data(), argptrs.size(), result, error); return result; } - static void call_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error); + static void callp_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error); template static Variant call_static(Variant::Type type, const StringName &method, Args... args) { + std::array vargs = { args... }; + std::array argptrs; + for (size_t i = 0; i < vargs.size(); i++) { + argptrs[i] = &vargs[i]; + } Variant result; GDExtensionCallError error; - std::array call_args = { Variant(args)... }; - call_static(type, method, call_args.data(), call_args.size(), result, error); + callp_static(type, method, argptrs.data(), argptrs.size(), sizeof...(args), result, error); return result; } diff --git a/src/variant/variant.cpp b/src/variant/variant.cpp index a73db740..641f59c7 100644 --- a/src/variant/variant.cpp +++ b/src/variant/variant.cpp @@ -549,11 +549,11 @@ bool Variant::operator<(const Variant &other) const { return result.operator bool(); } -void Variant::call(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) { +void Variant::callp(const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) { internal::gdextension_interface_variant_call(_native_ptr(), method._native_ptr(), reinterpret_cast(args), argcount, r_ret._native_ptr(), &r_error); } -void Variant::call_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) { +void Variant::callp_static(Variant::Type type, const StringName &method, const Variant **args, int argcount, Variant &r_ret, GDExtensionCallError &r_error) { internal::gdextension_interface_variant_call_static(static_cast(type), method._native_ptr(), reinterpret_cast(args), argcount, r_ret._native_ptr(), &r_error); } diff --git a/test/project/main.gd b/test/project/main.gd index 12f535f1..eb8dbb9d 100644 --- a/test/project/main.gd +++ b/test/project/main.gd @@ -2,6 +2,9 @@ extends "res://test_base.gd" var custom_signal_emitted = null +class TestClass: + func test(p_msg: String) -> String: + return p_msg + " world" func _ready(): var example: Example = $Example @@ -137,6 +140,10 @@ func _ready(): assert_equal(new_tilemap.tile_set, new_tileset) new_tilemap.queue_free() + # Test variant call. + var test_obj = TestClass.new() + assert_equal(example.test_variant_call(test_obj), "hello world") + # Constants. assert_equal(Example.FIRST, 0) assert_equal(Example.ANSWER_TO_EVERYTHING, 42) diff --git a/test/src/example.cpp b/test/src/example.cpp index 599b34bd..475eed2b 100644 --- a/test/src/example.cpp +++ b/test/src/example.cpp @@ -152,6 +152,8 @@ void Example::_bind_methods() { ClassDB::bind_method(D_METHOD("test_add_child", "node"), &Example::test_add_child); ClassDB::bind_method(D_METHOD("test_set_tileset", "tilemap", "tileset"), &Example::test_set_tileset); + ClassDB::bind_method(D_METHOD("test_variant_call", "variant"), &Example::test_variant_call); + ClassDB::bind_method(D_METHOD("test_bitfield", "flags"), &Example::test_bitfield); ClassDB::bind_method(D_METHOD("test_rpc", "value"), &Example::test_rpc); @@ -391,6 +393,10 @@ void Example::test_set_tileset(TileMap *p_tilemap, const Ref &p_tileset p_tilemap->set_tileset(p_tileset); } +Variant Example::test_variant_call(Variant p_variant) { + return p_variant.call("test", "hello"); +} + BitField Example::test_bitfield(BitField flags) { return flags; } diff --git a/test/src/example.h b/test/src/example.h index 6223a14e..cab7d22f 100644 --- a/test/src/example.h +++ b/test/src/example.h @@ -21,6 +21,7 @@ #include #include #include +#include #include @@ -133,6 +134,8 @@ public: void test_add_child(Node *p_node); void test_set_tileset(TileMap *p_tilemap, const Ref &p_tileset) const; + Variant test_variant_call(Variant p_variant); + BitField test_bitfield(BitField flags); // RPC From 0b1c8bcac303dbe628649e64c0f4629011c4826e Mon Sep 17 00:00:00 2001 From: Nick Maltbie Date: Wed, 20 Sep 2023 01:08:09 -0700 Subject: [PATCH 6/6] Added fix for javascript build for godot 4.x Added changes to tools/javascript.py to add PFlags to fix SharedArrayBuffer memory error. Corrected some small errors in tools/javascript.py to support new target names. Also updated ci to include validation for web build. (cherry picked from commit 2b4bcbb0ce69b8b7b2db226d3b01ea2134fdacfc) --- .github/workflows/ci.yml | 17 +++++++++++++++++ test/project/example.gdextension | 2 ++ tools/javascript.py | 15 ++++++--------- 3 files changed, 25 insertions(+), 9 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 750d0587..36f8c08a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,8 +78,18 @@ jobs: run-tests: false cache-name: ios-arm64 + - 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 + run-tests: false + cache-name: javascript-wasm32 + env: SCONS_CACHE: ${{ github.workspace }}/.scons-cache/ + EM_VERSION: 3.1.45 + EM_CACHE_FOLDER: "emsdk-cache" steps: - name: Checkout @@ -104,6 +114,13 @@ jobs: sudo apt-get update -qq sudo apt-get install -qqq build-essential pkg-config + - name: Web dependencies + if: ${{ matrix.platform == 'javascript' }} + uses: mymindstorm/setup-emsdk@v12 + with: + version: ${{env.EM_VERSION}} + actions-cache-folder: ${{env.EM_CACHE_FOLDER}} + - name: Install scons run: | python -m pip install scons==4.0.0 diff --git a/test/project/example.gdextension b/test/project/example.gdextension index 99c1746d..d4234613 100644 --- a/test/project/example.gdextension +++ b/test/project/example.gdextension @@ -21,3 +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" diff --git a/tools/javascript.py b/tools/javascript.py index 1d8009eb..e8f6af1c 100644 --- a/tools/javascript.py +++ b/tools/javascript.py @@ -1,8 +1,9 @@ import os +from SCons.Util import WhereIs def exists(env): - return "EM_CONFIG" in os.environ + return WhereIs("emcc") is not None def generate(env): @@ -10,9 +11,6 @@ def generate(env): print("Only wasm32 supported on web. Exiting.") env.Exit(1) - if "EM_CONFIG" in os.environ: - env["ENV"] = os.environ - env["CC"] = "emcc" env["CXX"] = "em++" env["AR"] = "emar" @@ -26,6 +24,10 @@ def generate(env): env["ARCOM_POSIX"] = env["ARCOM"].replace("$TARGET", "$TARGET.posix").replace("$SOURCES", "$SOURCES.posix") env["ARCOM"] = "${TEMPFILE(ARCOM_POSIX)}" + # 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" @@ -39,9 +41,4 @@ def generate(env): env.Replace(SHLINKFLAGS="$LINKFLAGS") env.Replace(SHLINKFLAGS="$LINKFLAGS") - if env["target"] == "debug": - env.Append(CCFLAGS=["-O0", "-g"]) - elif env["target"] == "release": - env.Append(CCFLAGS=["-O3"]) - env.Append(CPPDEFINES=["WEB_ENABLED", "UNIX_ENABLED"])