Search code examples
c++g++sconsgodotstdatomic

undefined reference to '__atomic_*' in SCons but similar questions' solution won't work


I'm trying to build Godot with SCons. Everything was working fine until I've used std::atomic in my library my custom module uses (the library is working fine with a Qt application I've created to test it). Then this error happened:

[100%] Linking Program        ==> bin/godot.x11.tools.64
/usr/bin/ld: /home/sms/Code/_BUILDS/build-PyWally-Desktop-Release/libPyWally.so: undefined reference to `__atomic_store_16'
/usr/bin/ld: /home/sms/Code/_BUILDS/build-PyWally-Desktop-Release/libPyWally.so: undefined reference to `__atomic_load_16'
collect2: error: ld returned 1 exit status
scons: *** [bin/godot.x11.tools.64] Error 1
scons: building terminated because of errors.

I was googling around and found out about atomic/architecture problems, so I've added -march=native, -mtune=native and -latomic because I have modern x64 PC/system and it shoudn't be an issue... so my SCsub looks like this (wallycontroller being my custom module, and pywally - my library):

Import('env')

sources = [
    "wallycontroller.cpp",
    "wallycontroller.cpp",
    "register_types.cpp"
]

env.Append(CPPPATH=["/usr/include/python3.10"])
env.Append(LIBS=['python3.10'])
env.Append(CCFLAGS=['-march=native', '-mtune=native', '-latomic'])

env.Append(CPPPATH=["#bin/../../PyWallie"])
env.Append(LIBPATH=["#bin/../../../_BUILDS/build-PyWally-Desktop-Release"])
env.Append(LIBS=['PyWally'])

envw = env.Clone()
envw.Append(CCFLAGS=['-O2'])

if ARGUMENTS.get('wallycontroller_shared', 'no') == 'yes':
    envw.Append(CCFLAGS=['-fPIC'])
    envw['LIBS'] = []
    envw.Append(LIBS=['python3.10'])
    envw.Append(LIBS=['PyWally'])
    shared_lib = envw.SharedLibrary(target='#bin/../../godot_modules/wallycontroller', source=sources)
    shared_lib_shim = shared_lib[0].name.rsplit('.', 1)[0]
    env.Append(LIBS=[shared_lib_shim])
    env.Append(LIBPATH=['#bin'])
else:
    envw.add_source_files(env.modules_sources, sources)

And these are my SCons arguments on build:

platform = "x11"
tools = "yes"
target = "debug"
bits = 64
custom_modules = "../godot_modules"
use_lto = "yes"
walliecontroller_shared = "yes"
udev = "no"

Any issue wasn't happening for this configuration until I've add std::atomic but it's really convenient and I wouldn't want to remove it... any help will be appreciated.


Solution

  • To help you debug, try temporarily commenting out the setting of LINKCOMSTR (should be in methods.py) so that SCons can show you the whole link line - normally Godot tries to be "helpful" and emit shorter messages, but it doesn't help when you're getting something like a link failure. You'll probably notice that it's not linking with libatomic after all. In SCons, you actually need to add that library to LIBS (without the -l) to pass it to the linker.


    A separate question is why it thinks it need it - I'm presuming the architecture you're building on has atomic support?

    With optimization disabled, GCC often calls helper functions for atomic operations instead of inlining.

    For x86-64, GCC7 and later always calls a helper function for 16-byte atomics, instead of inlining lock cmpxchg16b. (And now so it can use movaps on CPUs with AVX where that guarantees atomicity of 16-byte pure-load and pure-store.) So gcc -latomic is always necessary when compiling for x86-64, if you use 16-byte atomic objects.