diff --git a/.github/workflows/emscripten-patches/embind/bind.cpp b/.github/workflows/emscripten-patches/embind/bind.cpp new file mode 100644 index 00000000000..eb440f7560e --- /dev/null +++ b/.github/workflows/emscripten-patches/embind/bind.cpp @@ -0,0 +1,205 @@ +// Copyright 2012 The Emscripten Authors. All rights reserved. +// Emscripten is available under two separate licenses, the MIT license and the +// University of Illinois/NCSA Open Source License. Both these licenses can be +// found in the LICENSE file. + +#include +#ifdef USE_CXA_DEMANGLE +#include <../lib/libcxxabi/include/cxxabi.h> +#endif +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace emscripten; +using namespace internal; + +static char* pointerToHexString(const void* ptr) { + static const char hexDigits[] = "0123456789abcdef"; + uintptr_t address = reinterpret_cast(ptr); + char str[20] = "0x"; // Includes the "0x" prefix + int index = 2; + bool leadingZero = true; // Used to skip leading zeros + + // Convert the address to a hexadecimal string + for (int i = (sizeof(address) * 2) - 1; i >= 0; --i) { + char hexChar = hexDigits[(address >> (i * 4)) & 0xF]; + if (hexChar != '0' || !leadingZero || i == 0) { // Ensures at least one zero in the final character + str[index++] = hexChar; + leadingZero = false; + } + } + str[index] = '\0'; + + return strdup(str); +} + +extern "C" { +const char* EMSCRIPTEN_KEEPALIVE __getTypeName(const std::type_info* ti) { + if (has_unbound_type_names) { +#ifdef USE_CXA_DEMANGLE + int stat; + char* demangled = abi::__cxa_demangle(ti->name(), NULL, NULL, &stat); + if (stat == 0 && demangled) { + return demangled; + } + + switch (stat) { + case -1: + return strdup(""); + case -2: + return strdup(""); + case -3: + return strdup(""); + default: + return strdup(""); + } +#else + return strdup(ti->name()); +#endif + } else { + //cjh char str[80]; + // sprintf(str, "%p", reinterpret_cast(ti)); + // return strdup(str); + return pointerToHexString(reinterpret_cast(ti)); + } +} + +static InitFunc* init_funcs = nullptr; + +EMSCRIPTEN_KEEPALIVE void _embind_initialize_bindings() { + for (auto* f = init_funcs; f; f = f->next) { + f->init_func(); + } +} + +void _embind_register_bindings(InitFunc* f) { + f->next = init_funcs; + init_funcs = f; +} + +} + +namespace { +template static void register_integer(const char* name) { + using namespace internal; + _embind_register_integer(TypeID::get(), name, sizeof(T), std::numeric_limits::min(), + std::numeric_limits::max()); +} + +template static void register_bigint(const char* name) { + using namespace internal; + _embind_register_bigint(TypeID::get(), name, sizeof(T), std::numeric_limits::min(), + std::numeric_limits::max()); +} + +template static void register_float(const char* name) { + using namespace internal; + _embind_register_float(TypeID::get(), name, sizeof(T)); +} + +// matches typeMapping in embind.js +enum TypedArrayIndex { + Int8Array, + Uint8Array, + Int16Array, + Uint16Array, + Int32Array, + Uint32Array, + Float32Array, + Float64Array, + // Only available if WASM_BIGINT + Int64Array, + Uint64Array, +}; + +template constexpr TypedArrayIndex getTypedArrayIndex() { + static_assert(internal::typeSupportsMemoryView(), "type does not map to a typed array"); + return std::is_floating_point::value + ? (sizeof(T) == 4 ? Float32Array : Float64Array) + : (sizeof(T) == 1 + ? (std::is_signed::value ? Int8Array : Uint8Array) + : (sizeof(T) == 2 ? (std::is_signed::value ? Int16Array : Uint16Array) + : (sizeof(T) == 4 ? (std::is_signed::value ? Int32Array : Uint32Array) + : (std::is_signed::value ? Int64Array : Uint64Array)))); +} + +template static void register_memory_view(const char* name) { + using namespace internal; + _embind_register_memory_view(TypeID>::get(), getTypedArrayIndex(), name); +} +} // namespace + +EMSCRIPTEN_BINDINGS(builtin) { + using namespace emscripten::internal; + + _embind_register_void(TypeID::get(), "void"); + + _embind_register_bool(TypeID::get(), "bool", sizeof(bool), true, false); + + register_integer("char"); + register_integer("signed char"); + register_integer("unsigned char"); + register_integer("short"); + register_integer("unsigned short"); + register_integer("int"); + register_integer("unsigned int"); +#if __wasm64__ + register_bigint("long"); + register_bigint("unsigned long"); +#else + register_integer("long"); + register_integer("unsigned long"); +#endif + + register_bigint("int64_t"); + register_bigint("uint64_t"); + + register_float("float"); + register_float("double"); + +/*cjh + _embind_register_std_string(TypeID::get(), "std::string"); + _embind_register_std_string( + TypeID>::get(), "std::basic_string"); + _embind_register_std_wstring(TypeID::get(), sizeof(wchar_t), "std::wstring"); + _embind_register_std_wstring(TypeID::get(), sizeof(char16_t), "std::u16string"); + _embind_register_std_wstring(TypeID::get(), sizeof(char32_t), "std::u32string"); +*/ + _embind_register_emval(TypeID::get(), "emscripten::val"); +/*cjh + // Some of these types are aliases for each other. Luckily, + // embind.js's _embind_register_memory_view ignores duplicate + // registrations rather than asserting, so the first + // register_memory_view call for a particular type will take + // precedence. + + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + + register_memory_view("emscripten::memory_view"); + register_memory_view("emscripten::memory_view"); + */ +} diff --git a/.github/workflows/web-interface-check.yml b/.github/workflows/web-interface-check.yml index 1c257bfc4ec..1c375f16152 100644 --- a/.github/workflows/web-interface-check.yml +++ b/.github/workflows/web-interface-check.yml @@ -78,6 +78,20 @@ jobs: which emcc emcc -v + - name: Apply emscripten patches + run: | + echo "Save bind.cpp ..." + cp $EMSDK/upstream/emscripten/system/lib/embind/bind.cpp $EMSDK/upstream/emscripten/system/lib/embind/bind.cpp.bak + echo "Apply embind bind.cpp patches ..." + cp -f ./engine-HEAD/.github/workflows/emscripten-patches/embind/bind.cpp $EMSDK/upstream/emscripten/system/lib/embind/ + echo "Apply patches DONE!" + cat $EMSDK/upstream/emscripten/system/lib/embind/bind.cpp + echo "Restore patches ..." + rm $EMSDK/upstream/emscripten/system/lib/embind/bind.cpp + mv $EMSDK/upstream/emscripten/system/lib/embind/bind.cpp.bak $EMSDK/upstream/emscripten/system/lib/embind/bind.cpp + echo "Restore patches DONE!" + cat $EMSDK/upstream/emscripten/system/lib/embind/bind.cpp + - name: Install ninja run: | if ! command -v ninja &> /dev/null; then @@ -91,7 +105,7 @@ jobs: - name: Build Spine WASM run: | - cd ./native/cocos/editor-support/spine-wasm + cd ./engine-HEAD/native/cocos/editor-support/spine-wasm mkdir build-wasm cd build-wasm emcmake cmake .. -GNinja @@ -100,7 +114,7 @@ jobs: - name: Build Spine ASMJS run: | - cd ./native/cocos/editor-support/spine-wasm + cd ./engine-HEAD/native/cocos/editor-support/spine-wasm sed -i 's/set(BUILD_WASM 1)/set(BUILD_WASM 0)/g' CMakeLists.txt mkdir build-asmjs cd build-asmjs @@ -111,15 +125,15 @@ jobs: - name: Copy files to external directory run: | mkdir dist - cp ./native/cocos/editor-support/spine-wasm/build-wasm/spine.wasm ./dist/ - cp ./native/cocos/editor-support/spine-wasm/build-wasm/spine.js ./dist/spine.wasm.js - cp ./native/cocos/editor-support/spine-wasm/build-asmjs/spine.js.mem ./dist/ - cp ./native/cocos/editor-support/spine-wasm/build-asmjs/spine.js ./dist/spine.asm.js + cp ./engine-HEAD/native/cocos/editor-support/spine-wasm/build-wasm/spine.wasm ./dist/ + cp ./engine-HEAD/native/cocos/editor-support/spine-wasm/build-wasm/spine.js ./dist/spine.wasm.js + cp ./engine-HEAD/native/cocos/editor-support/spine-wasm/build-asmjs/spine.js.mem ./dist/ + cp ./engine-HEAD/native/cocos/editor-support/spine-wasm/build-asmjs/spine.js ./dist/spine.asm.js echo "-------- Before replace spine wasm -----------" - ls -l ./native/external/emscripten/spine/ - cp -f ./dist/* ./native/external/emscripten/spine/ + ls -l ./engine-HEAD/native/external/emscripten/spine/ + cp -f ./dist/* ./engine-HEAD/native/external/emscripten/spine/ echo "-------- After replace spine wasm ------------" - ls -l ./native/external/emscripten/spine/ + ls -l ./engine-HEAD/native/external/emscripten/spine/ echo "-----------------------------------------------" - name: Upload Artifact