[.NET] Add support for web export using static LibGodot#118976
[.NET] Add support for web export using static LibGodot#118976NoctemCat wants to merge 1 commit into
Conversation
That's a super weird limitation, why? |
This comment was marked as outdated.
This comment was marked as outdated.
49d54d7 to
dd4d2b9
Compare
Sorry, it was because of the I tried exporting again with custom cache removed and it worked. And once again thanks to @GabCoolDude for testing the export on Windows from a different drive. |
dd4d2b9 to
1f504d0
Compare
|
Fixed a couple of bugs and ported a new demo https://noctemcat.itch.io/port-chickensoft-demo from https://github.com/chickensoft-games/GameDemo Fixed bugs:
|
Co-authored-by: GabCoolDude <gabrielfreville@proton.me>
1f504d0 to
f680cb4
Compare
|
Changes:
|
|
Small cleanup I found while looking through this PR:
I verified the patch with: PYTHONPYCACHEPREFIX=$PWD/.pycache python3 -m py_compile platform_methods.py
git diff --checkPatch: From d153b0070c7947afc2f8789de6a8a25a8dcab3d2 Mon Sep 17 00:00:00 2001
From: Admin <ADMIN@Macbooks-MacBook-Pro.local>
Date: Sun, 10 May 2026 18:14:52 -0500
Subject: [PATCH] Fix web mono export cleanup nits
---
.../mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Browser.targets | 2 +-
platform_methods.py | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Browser.targets b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Browser.targets
index 34ee9d4..081ce7a 100644
--- a/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Browser.targets
+++ b/modules/mono/editor/Godot.NET.Sdk/Godot.NET.Sdk/Sdk/Browser.targets
@@ -51,6 +51,6 @@
<Target Name="GodotCheckLibGodotPath" BeforeTargets="Build">
<Error Text="Cannot build with empty 'BaseLibGodotPath'." Condition=" $(_BaseLibGodotPath) == '' " />
- <Error Text="Cannot find 'libgodot.a' in expected placee." Condition=" !Exists('$(_BaseLibGodotPath)\libgodot.a') " />
+ <Error Text="Cannot find 'libgodot.a' in expected place." Condition=" !Exists('$(_BaseLibGodotPath)\libgodot.a') " />
</Target>
</Project>
diff --git a/platform_methods.py b/platform_methods.py
index e1e7188..c7e8c8b 100644
--- a/platform_methods.py
+++ b/platform_methods.py
@@ -185,7 +185,7 @@ def combine_libs_ar(target, source, env):
if isinstance(lib, str) and (lib.endswith(".a") or lib.endswith(".lib")):
paths.append(lib)
- with tempfile.NamedTemporaryFile(mode="w", suffix=".mri", delete_on_close=False) as fp:
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".mri", delete=False) as fp:
fp.write(f"create {lib_path}\n")
for path in paths:
fp.write(f"addlib {path}\n")
--
2.39.2 (Apple Git-143)
|
|
I've done some testing with a rather complex multiplayer project. Most things seem to work fine out of the box. The .NET runtime + the GodotSharp bindings are ~10mb in size and perform better than the 60mb Mono JIT version from #106125. The engine itself is ~60mb instead of ~40mb because of missing LTO however. Some notes:
Honestly I'm quite impressed how well this works already. This whole PR is very close to clicking export -> it just works at this point. Of course the browser-wasm target itself is still full of smaller issues, but that's up to Microsoft to fix, as this PR makes full use of the unmodified .NET runtime which is officially supported by them. Another sidenote (not really related to this PR): since GDExtensions will most likely remain unsupported here, it might be worth considering supporting a simple way to convert GDExtensions into engine modules. |
This PR serves as an alternative to #106125.
Overview
Uses static LibGodot to link Godot as a library for web export.
A huge portion of this PR was adding LibGodot support to web platform and figuring out a way to pass a static library to the final step. In comparison the changes to the way mono itself works are minor.
LibGodot setup itself doesn't use the module mono and instead uses a simple interface written natively in C#. To initialize the module mono it now exports a function when LibGodot is enabled that can be called to set the initialization function for the module, this indirection allows us to call it early from the C# side and be sure that the module mono will safely check it later, and if it is set it will call it when the module begin initializing. Doing it this way preserves the normal order
GDMono::initializeis initialized. The initialization function itself passes normal initialization fromInitializeFromGameProject.Works:
[JSExport]/[JSImport].RunAOTCompilation.browser-wasmpublish with a statically linked Godot to it, so everything that works onbrowser-wasmshould work here, this was briefly tested withSystem.Security.CryptographyandSystem.Net.Http.HttpClient.Downsides:
Major downsides:
-sMAIN_MODULEflag.Objectwithout namespace, so it causes duplicate symbols forObjectvtable. If C# WASM will move to CoreCLR .NET WebAssembly on CoreCLR interpreter dotnet/runtime#121511 after updating Emscripten to be new enough to use--allow-multiple-definition[lld][WebAssembly] Add allow-multiple-definition flag llvm/llvm-project#97699 this won't be a problem.Small downsides:
ltolibrary.wasm-toolsworkload.WasmCachePath, on Windows this path needs to be on the same drive as the drive C# is installed on.webxrfor the same reasonproxy_to_pthreadis also incompatible.C#->JS->C#orJS->C#->JS, withjsThreadBlockingMode: 'ThrowWhenBlockingWait'it allows syncC#->JSandJS->C#, but that's all. More info [browser][MT] WebGL with threads - requestAnimationFrame dotnet/runtime#101421 (comment) and this seems also correct https://dev.to/lostbeard/blazor-wasms-deputy-thread-model-will-break-javascript-interop-heres-why-that-matters-1n9n.Hacks:
_export_beginafter extracting templates. It's needed for passing the path to the extracted static library inExportPlugin.cs._ExportBegin. I think it is possible to add a separate step after extracting templates, but before_export_filebegins, but I'm not sure.Closes: #70796.
Demo repo: https://github.com/NoctemCat/DotnetWebExportDemo.
Thanks to @GabCoolDude for help writing it, testing export on Windows, and testing it overall.