Trying to build multiple GDExtentions lib

Godot Version

4.2 (on Manjaro Linux)

Question

Hello ! First post here :slight_smile:

So I’m trying to build multiple gdextensions lib, the goal is to have a β€œcommon” lib I reuse in all my game projects and another specific for each project.
I’ve made for this post a generic version of the architecture looking like that:

β”œβ”€β”€ SConstruct
β”œβ”€β”€ a
β”‚   β”œβ”€β”€ a_test.h
β”‚   β”œβ”€β”€ a_test.cpp
β”‚   β”œβ”€β”€ register_types.h
β”‚   β”œβ”€β”€ register_types.cpp
β”‚   └── SConscript
 ──b
β”‚   β”œβ”€β”€ b_test.h
β”‚   β”œβ”€β”€ b_test.cpp
β”‚   β”œβ”€β”€ register_types.h
β”‚   β”œβ”€β”€ register_types.cpp
β”‚   └── SConscript

With a being the β€œcommon” lib and b being the specific lib.

In a_test.h I’m defining a class inheriting from a Godot Node:

class aTest : public Node {
    GDCLASS(aTest, Node)

protected:
    static void _bind_methods();
};

And in b_test.h a class inheriting aTest:

class bTest : public aTest {
    GDCLASS(bTest, aTest)

protected:
    static void _bind_methods();
};

Here are the scons files:

scons

SConstruct

#!/usr/bin/env python
import os
import sys

env = SConscript("godot-cpp/SConstruct")

# env['CCCOMSTR'] = "Compiling $TARGET"
# env['LINKCOMSTR'] = "Linking $TARGET"
# env.Append(LINKFLAGS=['-Wl,-z,defs'])
# env.Append(LINKFLAGS=['-Wl,--start-group'])

subdirs = [
    'a',
    'b'
]

# The exports attribute allows you to pass variables to the subdir SConscripts
for dir in subdirs:
    SConscript( os.path.join(dir, 'SConscript'), exports = ['env'])

a/SConscript

#!/usr/bin/env python
import os
import sys

Import('env')

# For reference:
# - CCFLAGS are compilation flags shared between C and C++
# - CFLAGS are for C-specific compilation flags
# - CXXFLAGS are for C++-specific compilation flags
# - CPPFLAGS are for pre-processor flags
# - CPPDEFINES are for pre-processor defines
# - LINKFLAGS are for linking flags

# tweak this if you want to use different folders, or more folders, to store your source code in.
sources = [
    Glob("*.cpp"),]

env.Append(CPPPATH=Glob('.'))

nenv = env.Clone()

lib_folder = "../project/bin/"
if nenv["platform"] == "macos":
    lib_name = "a.{}.{}.framework/liboldworld.{}.{}".format(
            nenv["platform"], nenv["target"], nenv["platform"], nenv["target"]
        )
else:
    lib_name = "a{}{}".format(nenv["suffix"], nenv["SHLIBSUFFIX"])
    
library = nenv.SharedLibrary(
        lib_folder+"lib"+lib_name,
        source=sources,
)

Default(library)

b/SConscript

#!/usr/bin/env python
import os
import sys

Import('env')

# For reference:
# - CCFLAGS are compilation flags shared between C and C++
# - CFLAGS are for C-specific compilation flags
# - CXXFLAGS are for C++-specific compilation flags
# - CPPFLAGS are for pre-processor flags
# - CPPDEFINES are for pre-processor defines
# - LINKFLAGS are for linking flags

env.Append(CPPPATH=[".."])


owenv = env.Clone()
owenv.Append(LIBS=["a.linux.editor.dev.x86_64"], LIBPATH=["../project/bin/"])

# tweak this if you want to use different folders, or more folders, to store your source code in.
sources = [
    Glob("*.cpp")]

if owenv["platform"] == "macos":
    library = owenv.SharedLibrary(
        "../project/bin/b.{}.{}.framework/b.{}.{}".format(
            owenv["platform"], owenv["target"], owenv["platform"], owenv["target"]
        ),
        source=sources,
    )
else:
    library = owenv.SharedLibrary(
        "../project/bin/b{}{}".format(owenv["suffix"], owenv["SHLIBSUFFIX"]),
        source=sources,
    )

Default(library)

So the compilation works fine with no error, but when I launch Godot I get:

Can’t open dynamic library: /[mypath]/gdextensionmultiplelibs/project/bin/libb.linux.editor.dev.x86_64.so. Error: /[mypath]/gdextensionmultiplelibs/project/bin/libb.linux.editor.dev.x86_64.so: undefined symbol: _ZN5godot5aTest13_bind_methodsEv.
core/extension/gdextension.cpp:719 - GDExtension dynamic library not found: /run/media/paul/Developpement/gdextensionmultiplelibs/project/bin/libb.linux.editor.dev.x86_64.so
Failed loading resource: res://bin/b.gdextension. Make sure resources have been imported by opening the project in the editor at least once.

And I don’t understand what is missing for Godot to see _ZN5godot5aTest13_bind_methodsEv, I’ve check with nm and readelf and the a lib does contain it.

I’ve also made a repo with all the code of this example if you want to test building yourself: Pikario / GDExtensionMultipleLibs Β· GitLab

Thank you for your answers!

If this is a dynamic Library the .so needs to be within the LD_LIBRARY_PATH variable while running the executable. Unless there is a way to statically link it.

Thank you for your answer.
Just tried to do export LD_LIBRARY_PATH=[path to the project]/project/bin and then launched godot in the same shell with Godot_v4.2.2-stable_linux.x86_64 -e project/project.godot, same error :confused:

I’m thinking it can be that the b lib is loaded by Godot before the a lib? How can I choose the order? Is there a value I can put in the .gdextension?