godot-cpp icon indicating copy to clipboard operation
godot-cpp copied to clipboard

emsdkHack.cmake variables not propagated outside the godot-cpp library

Open lechaosx opened this issue 4 months ago • 9 comments

Godot version

v4.4.1.stable.nixpkgs [49a5bc7b6]

godot-cpp version

godot-4.4.1-stable

System information

NixOS 25.05.20250721.92c2e04 (Warbler)

Issue description

I'm unable to properly compile GDExtension project for web with CMake. It seems that the variables from emsdkHack.cmake should enable compilation of shared libraries with emscripten, but the variables are set to the godot-cpp project directory scope, not at the top-level GDExtension project scope where it's needed and expected. The only thing that is properly set is the TARGET_SUPPORTS_SHARED_LIBS global property as global properties do not follow directory scopes. This way, the project compiles with warning

em++: warning: linking a library with `-shared` will emit a static object file.  This is a form of emulation to support existing build systems.  If you want to build a runtime shared library use the SIDE_MODULE setting. [-Wemcc]

and the output library is unusable with godot. If I manually include the emsdkHack.cmake file after my top level project call, the compilation passes without a problem. Even with library generated this way, the Remote Deploy -> Run in Browser is not loading and returning Uncaught (in promise) undefined in Firefox console. This might be unrelated issue or result of invalid compilation.

Steps to reproduce

  1. Either enter dev environment via nix develop or have prerequisites defined in flake.nix in your PATH via your favourite approach.

To reproduce the failing build:

  1. emcmake cmake --preset default -B build-emscripten
  2. cmake --build build-emscripten
  3. Uncomment the include in top level CMakeLists.txt and compile again for successful build

To try the extension in the editor, also compile it natively: 4. cmake --preset default 5. cmake --build build 6. Open the editor and run the main scene, or alternatively Remote Deploy -> Run in Browser

Minimal reproduction project

gdextension-emscripten-cmake-repro.zip

lechaosx avatar Aug 14 '25 20:08 lechaosx

I'll have a look as soon as I can, life is chaos right now, so might take me a week. In the meantime, what version of emscripten are you running? same as listed for godot? https://docs.godotengine.org/en/stable/contributing/development/compiling/compiling_for_web.html edit: actually as per my own comments on that page, I ended up matching the github actions version of 3.1.64

enetheru avatar Aug 14 '25 23:08 enetheru

I use emscripten 4.0.8, which might cause the secondary issue where the web preview won't load. I will try it with 3.1.64. EDIT: I can now confirm that it behaves exactly the same with 3.1.64 on my setup EDIT 2: In pursue to resolve the secondary issue, I tried to recompile also the export templates with emscripten 3.1.64. This failed because the nix package for this version seems to be bundled with incompatible version of binaryen. This issue seem to originate from accidentally misstagged commit https://github.com/emscripten-core/emscripten/issues/22249. I tried to compile both the export templates and the gdextension with emscripten 3.1.73. The compilation passes, but both Chrome and Firefox won't load the project with Uncaught (in promise) undefined in console.

lechaosx avatar Aug 15 '25 06:08 lechaosx

This: Uncaught (in promise) undefined Is probably what I am seeing here Uncaught (in promise) LinkError: imported shared memory but unshared required I can compile and export the minimal project, normally. But I havent yet been able to get it to work for emscripten, yet. I think I'm going to have to add a build_profile.json because its painful to sit through a full compile each time i test something.

enetheru avatar Oct 18 '25 11:10 enetheru

You are right about the variables not being counted, naming them cache internal is likely the right way to go. I put the min project in a repo and you can see the inimal changes I made. Most notably is the method of inclusion of the hack https://github.com/enetheru/issue-1830

For code injection to work, it needs to be included in a specific way to alter the behaviour so it isnt overwritten by the toolchain when the project variables are instantiated.

enetheru avatar Oct 18 '25 11:10 enetheru

But I cant seem to get 4.4.1 to work at all, i get errors like i have a mismatch between versions, like missing functions etc. ERROR: Attempt to get non-existent interface function: 'alid_html_color'.

but i can get loading of the extension.

enetheru avatar Oct 18 '25 12:10 enetheru

Testing both scons and cmake using the integration testing i found a discrepancy. I was missing the -sUSE_PTHREADS=1 on the linker side.

enetheru avatar Oct 19 '25 04:10 enetheru

Got it. By default thread support is enabled, and the export must also match or it fails with the load problem. Adding use threads to the link options for the final output, and enabling thread support in the export options should make it work.

target_link_options( hello
    PRIVATE
        -sUSE_PTHREADS=1
)

I'll make a PR to fix the thread issue

enetheru avatar Oct 19 '25 04:10 enetheru

Wow, thanks for looking into it! I actually got it to work with your notes! The changes in the repo you sent are very minimal and I still need to uncomment the inclusion of the hack to compile it properly. Is this intended? I also noticed that in the hello.gdextension file, you have

res://hello/libhello.emscripten.template_debug.wasm32

but on my machine, it creates

libhello.web.template_debug.wasm32

Not sure if GODOTCPP_SUFFIX changed between versions or something is different on my setup.

I also noticed weird thing. On my machine, browsers (firefox and chrome) don't like when the binary ends with .wasm32. I get

Uncaught (in promise) Error: 404 : http://localhost:8060/libhello.web.template_debug.wasm32

in console. When I rename the file extension and also the resource reference in hello.gdextension to .wasm, it loads just fine.

lechaosx avatar Oct 20 '25 18:10 lechaosx

The changes in the repo you sent are very minimal and I still need to uncomment the inclusion of the hack to compile it properly. Is this intended?

sorry, once i identified the issue i stopped updating the example you provided and pivoted to creating the PR.

in console. When I rename the file extension and also the resource reference in hello.gdextension to .wasm, it loads just fine.

I noticed that difference too, but forgot to fix it. i'm glad you got things working :)

enetheru avatar Oct 20 '25 21:10 enetheru