module
Docs::B_COMPILATION_AND_BUILD
Overview
B. Compilation, Linking & Build System
LibGodot connects three different compilation layers into a unified build system:
- C++ GDExtension Loader Bridge (
src/bridge/crystal_bridge.cpp) - Crystal Game / Test / Example DLLs (
game.dll) - Godot Engine Dynamic Library (
libgodot.dll)
1. Compiling the C++ Loader Bridge (crystal_bridge.dll)
The bridge is compiled with MinGW-w64 g++ (or MSVC / clang) into bin/crystal_bridge.dll:
g++ -shared -O3 src/bridge/crystal_bridge.cpp -o bin/crystal_bridge.dll -lgc
Why is a separate loader bridge required?
- Boehm GC Bootstrapping: Crystal DLLs dynamically loaded into an external host
process (like
godot.exe) do not run Crystal's native executable CRT initialization. The bridge explicitly callsGC_init()before invoking any Crystal exported symbol. - Zero C++ Headers in Crystal: The bridge maps Godot's complex C++ GDExtension
API and function pointers into a clean, flat C-ABI structure (
BridgeAPI), allowing Crystal to interact with Godot without any C++ header dependencies. - Exception & Crash Guarding: The bridge wraps instance dispatches in structured guards, preventing unhandled engine crashes when user scripts fail.
2. The Shadow Copying Reload Mechanism
Under Windows, when a process loads a DLL via LoadLibraryA, the operating system
places an exclusive shared-read lock on the file. Any attempt by the Crystal compiler
to overwrite game.dll while Godot is open results in:
Error: Access is denied. (ERROR_SHARING_VIOLATION / Windows error 32)
To solve this, crystal_bridge.cpp implements Shadow Copy Loading in development mode:
- When
crystal_bridge.dllinitializes, it checks forLIBGODOT_RELEASE. If absent, shadow loading is enabled. - Before loading
bin/game.dll, the bridge copiesbin/game.dllto:bin/game_loaded_<PID>_<TIMESTAMP>.dll - The bridge calls
LoadLibraryAon the shadow copy, leavingbin/game.dllunlocked! - The Crystal compiler can now freely rebuild
bin/game.dllat any time while the Godot editor is still running. - Old shadow copies from terminated processes are automatically pruned at startup.
In release builds (LIBGODOT_RELEASE=1), shadow copying is disabled to eliminate disk I/O.
3. Compiling Crystal Game Code (game.dll)
Crystal compiles user nodes into a dynamic library via:
crystal build --cross-compile --link-flags="-shared" src/main.cr -o bin/game.dll
Crystal exports two primary C-ABI entry points:
crystal_godot_init(api : LibBridge::BridgeAPI*) : Int32: Called by the loader bridge immediately after loading. Crystal stores theBridgeAPIpointer, iterates overClassRegistry, registers all custom classes, properties, and signals withClassDB, and registers offline XML documentation withEditorHelp.crystal_godot_cleanup : Void: Called when the library unloads during engine shutdown.
4. Editor Build Hook (EditorPlugin._build)
The Godot editor plugin located at addons/crystal_integration/crystal_integration.gd
intercepts Godot's build pipeline:
- It overrides
EditorPlugin._build(). - Whenever the developer presses F5 (Play Project) or F6 (Play Scene), the
plugin executes
crystal buildin the background. - If compilation succeeds, Godot continues launching the scene with the updated DLL.
- If compilation fails, the output is printed directly to the Godot Editor Output Dock, and scene launching is cleanly halted.
5. Build System Synchronization (make all)
The root Makefile orchestrates compilation across the entire workspace:
make bridge: Buildsbin/crystal_bridge.dll.make test_project: Buildstest/bin/game.dll.make examples: Builds all showcase projects inexamples/.make template: Buildstemplate/bin/game.dll.make sync: Synchronizescrystal_bridge.dll, runtime DLLs (gc.dll,iconv-2.dll,pcre2-8.dll), andcrystal.gdextensionacrossbin/,test/bin/,template/bin/, andexamples/*/bin/.
Rule: Always execute
make allrather than partial builds to guarantee all consumer directories and bridge DLLs remain synchronized.
Defined in:
libgodot/docs.crClass Method Summary
-
.rules : Array(String)
Dummy method for documentation visibility