How to Export gdext-nim Extensions to WebAssembly Using Emscripten
To export gdext-nim extensions to WebAssembly, configure your config.nims with Emscripten toolchain settings including -s SIDE_MODULE=1, compile with gdextwiz build -d:platform=web, and enable Extensions Support and Thread Support in the Godot HTML5 export preset.
The godot-nim/gdext-nim framework allows you to write Godot 4 extensions in Nim, but exporting these extensions to the web requires specific Emscripten configuration to produce WebAssembly side-modules. When targeting the web platform, gdext-nim compiles your Nim code to C, then uses Emscripten (emcc) to generate a Wasm side-module that Godot loads at runtime alongside the HTML5 engine build.
Prerequisites: Installing Emscripten
Follow the official Emscripten download guide to install the toolchain. Ensure the emcc command is available on your system PATH and that the EMSDK environment variables are properly exported. gdext-nim relies on these tools being accessible when the platform = web build setting is detected.
Configuring the WebAssembly Toolchain
In your project root, create or modify config.nims to inject Emscripten-specific flags. According to the building-and-exporting guide in docs/building-and-exporting-guide.md (lines 71-85), you must configure the Nim compiler to use emcc as both the compiler and linker when targeting the web platform.
Example config.nims:
# config.nims
import gdext/buildconf
let setting = BuildSettings(
name: "MyExtension",
extpath: projectDir() & "/myextension.gdextension",
updateMethod: inject
)
configure(setting):
case setting.platform
of web:
--cpu: wasm32
--cc: clang
when buildOS == "windows":
--clang.exe: emcc.bat
--clang.linkerexe: emcc.bat
else:
--clang.exe: emcc
--clang.linkerexe: emcc
# Required side-module flags for Godot GDExtensions
--passC: "-s SIDE_MODULE=1 -s SUPPORT_LONGJMP='wasm'"
--passL: "-s SIDE_MODULE=1 -s SUPPORT_LONGJMP='wasm' -s WASM_BIGINT"
This configuration tells the Nim compiler to generate Wasm32 bytecode and passes the critical SIDE_MODULE=1 flag to Emscripten, which produces a dynamic library that Godot can load at runtime rather than a standalone executable.
Compiling the Extension with gdextwiz
Use the gdextwiz CLI tool to compile your extension for the web target. As documented in docs/tools/gdextwiz.md (lines 44-58), the tool automatically discovers your bootstrap.nim entry point and applies the settings from config.nims.
Build commands:
# Debug build for testing
gdextwiz build -d:platform=web
# Optimized release build for final export
gdextwiz build -d:platform=web -d:target=release
The gdextwiz command invokes emcc with the flags defined in your configure() block, generating libmyextension.wasm in the res://nim/lib/ directory.
Exporting for Godot HTML5
The final step requires configuring the Godot editor to package your Wasm side-module with the HTML5 export. According to docs/building-and-exporting-guide.md (lines 96-99), you must enable specific variant options in the export preset:
- Open Project → Export and add a Web preset.
- In the Variant section, enable Extensions Support.
- Enable Thread Support (required for WebAssembly side-modules to function).
When you click Export Project, Godot copies the generated .wasm file into the export folder and references it through the automatically generated .gdextension file (controlled by BuildSettings.extpath and updateMethod). The entry point in this file points to res://nim/lib/libmyextension.wasm.
Understanding the Side-Module Architecture
gdext-nim builds a WebAssembly side-module rather than a whole-program Wasm executable. This architectural choice, implemented via the -s SIDE_MODULE=1 flag, allows Godot to load your extension dynamically at runtime while keeping the engine core separate. The side-module approach enables hot-reloading capabilities and reduces initial bundle size.
The flags -s SUPPORT_LONGJMP='wasm' and -s WASM_BIGINT are mandatory for threading support in WebAssembly side-modules. gdext-nim automatically injects these when the web platform is detected in your configure() block, ensuring compatibility with Godot's multi-threaded HTML5 builds.
Summary
- Install Emscripten and ensure
emccis available on your systemPATHbefore building. - Configure
config.nimswith--cpu: wasm32,--cc: clang, and Emscripten paths to target WebAssembly. - Pass
-s SIDE_MODULE=1 -s SUPPORT_LONGJMP='wasm' -s WASM_BIGINTtoemccvia--passCand--passLto generate a loadable side-module. - Use
gdextwiz build -d:platform=webto compile your extension; the tool handles the Nim-to-C-to-Wasm pipeline automatically. - Enable Extensions Support and Thread Support in the Godot HTML5 export preset to allow the engine to load your Wasm side-module.
- The
.gdextensionfile is auto-generated based onBuildSettings, pointing to the compiledlibmyextension.wasminres://nim/lib/.
Frequently Asked Questions
What is a WebAssembly side-module and why does gdext-nim use one?
A WebAssembly side-module is a dynamically linkable Wasm binary that exports symbols for a host environment to load at runtime. gdext-nim uses this architecture—enabled by the -s SIDE_MODULE=1 flag—to produce a GDExtension library that Godot loads on demand, keeping the engine core separate from extension code and enabling hot-reloading functionality in the HTML5 export.
Why do I need to enable Thread Support in the Godot export preset?
WebAssembly side-modules require threading primitives to interface correctly with Godot's multi-threaded architecture. The -s SUPPORT_LONGJMP='wasm' and -s WASM_BIGINT flags generate the necessary threading metadata in the Wasm binary, but Godot's HTML5 export must explicitly enable Thread Support in the Variant settings to instantiate and run threaded side-modules in the browser.
Can I customize the location of the generated .gdextension file?
Yes. In your config.nims, set the extpath field in BuildSettings to your desired file path, and adjust updateMethod to control how gdext-nim modifies the file. Use updateMethod = inject to preserve existing custom entries while updating paths, or overwrite to regenerate the file completely. The default behavior uses create to generate a new file at the specified path.
Where does gdext-nim place the compiled WebAssembly binary?
By default, gdextwiz outputs the compiled Wasm file to res://nim/lib/lib{name}.wasm, where {name} matches your BuildSettings.name value. The auto-generated .gdextension file references this path automatically, ensuring Godot locates and loads the side-module when the HTML5 project starts.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →