| Website | Discord |
|---|
Successfuly ported Godot Sandbox and Tiny Lobby using this technique with no modification to current codebase, only additions.
5 Steps to Success in Godot from loser GDExtension to winner Module.
Port your GDExtension addon to modules with minimal changes. The idea is that you will create a wrapper module that statically links with your addon, and for this you also need to build your addon statically. Thats it.
This repo contains a sample wrapper module (note the name of the folder containing all files is important). The module name is my_module.
The files in the modules are:
gdextension_static_library_loader.h- this is a copy paste fromgdextension_library_loader.hfrom godot source code. It enables loading static libraries instead of dynamic ones.gdextension_static_library_loader.cpp- this is a copy paste fromgdextension_library_loader.cppfrom godot source code. It enables loading static libraries instead of dynamic ones.register_types.h- This is the wrapper module you are creating. Changemy_moduleandMY_MODULEwith your module name.register_types.cpp- This is the wrapper module. You need to call your function from the gdextension. Replacemy_addon_library_initwith the function you defined in thegdextensioninentry_symbolandmy_modulewith your module name (this name will appear in Godot somewhere).SCsub- This file is used for Godot Module building. Theget_suffixfunction replicates whatgodot-cppdoes with suffixes. This loads 2 static libs. Godot-cpp and your library.
In order to build your library statically, add the following to your SConstruct where you already build dynamic lib:
eg.
# Dynamic lib
if env["platform"] == "macos" or env["platform"] == "ios":
library = env.SharedLibrary(
"bin/addons/godot_sandbox/bin/libgodot_riscv{}.framework/libgodot_riscv{}".format(
env["suffix"], env["suffix"]
),
source=sources,
)
else:
library = env.SharedLibrary(
"bin/addons/godot_sandbox/bin/libgodot_riscv{}{}".format(env["suffix"], env["SHLIBSUFFIX"]),
source=sources,
)
Default(library)
# Static lib
if env["platform"] == "macos" or env["platform"] == "ios":
library = env.StaticLibrary(
"bin/addons/godot_sandbox/bin/libgodot_riscv{}.framework/libgodot_riscv{}{}".format(
env["suffix"], env["suffix"], env["LIBSUFFIX"]
),
source=sources,
)
else:
library = env.StaticLibrary(
"bin/addons/godot_sandbox/bin/libgodot_riscv{}{}".format(env["suffix"], env["LIBSUFFIX"]),
source=sources,
)
Default(library)Here we are building both static and dynamic lib. Then in the github actions export stage, we separate the two and upload static to another folder and dynamic to another folder:
- name: Upload Artifact
uses: actions/upload-artifact@v4
with:
name: godot-sandbox-linux-${{ matrix.arch }}-${{ matrix.precision }}
path: |
${{ github.workspace }}/bin/**/*.so
if-no-files-found: error
- name: Upload Artifact Static
uses: actions/upload-artifact@v4
with:
name: static-sandbox-linux-${{ matrix.arch }}-${{ matrix.precision }}
path: |
${{ github.workspace }}/bin/**/*.a
${{ github.workspace }}/ext/godot-cpp/**/*.a
if-no-files-found: error Then, at the end, you package everything with the my_module wrapper. So you would distribute a module with the godot-cpp static lib and your library built statically. Example of this can be found in godot-sandbox.
Eg. you copy your static lib and godot-cpp static into the my_module folder. As help, I put godot-cpp destination folder in the ext folder, and put a godot-cpp-static-libs.txt here to know where to place them. I also put in the my_library folder a file called my_static_lib.txt to see where to put your static libs.
Then, you copy the my_module folder at the end to the godot modules folder. Then you run the build command, enabling your module:
scons module_sandbox_enabled=True target=editorAnd that's it! You now have a module wrapper that installs an addon.
If you have icons in your library, you need to simply make a icons folder and place the icons there.
I got help designing and doing this from David Snopek (dsnopek), K. S. Ernest (iFire) Lee, Alf-André Walla (fwsGonzo).