godot-cpp icon indicating copy to clipboard operation
godot-cpp copied to clipboard

Linking error on macOS with Clang: missing TLS wrapper __ZTW symbols for Wrapped class.

Open soonsolidchentuo opened this issue 1 month ago • 0 comments

Godot version

4.5.1.stable.official.f62fdbde1

godot-cpp version

4.5 commit: da26c1732ee8656ef9ccad587cbdd55acf8637c8

System information

macOS (Intel x86_64), Clang compiler.

Issue description

Linking error on macOS (Clang x86_64): missing TLS wrapper __ZTW symbols for Wrapped class

I am encountering a runtime linking error when compiling a GDExtension on macOS (Intel x86_64) using Clang against the latest godot-cpp master branch (targeting Godot 4.5.1).

Despite compiling both godot-cpp and my extension with target=template_debug and ensuring -fvisibility=default is set, the linker fails to find the Thread Local Storage (TLS) wrapper functions for the godot::Wrapped class variables when loading the dylib.

Error Message:

Error: Can't open dynamic library: .../libjrpg_core_sdk.dylib. 
Error: dlopen(...): symbol not found in flat namespace '__ZTWN5godot7Wrapped34_constructing_extension_class_nameE'

Investigation & Findings:

  1. I inspected the generated static library libgodot-cpp.macos.template_debug.x86_64.a using nm -a.
  2. The output shows that the thread_local variables themselves are present (marked as S - data section), but their corresponding TLS wrapper functions (mangled as __ZTW...) are missing entirely.
  3. It appears that the macOS Clang compiler is optimizing out (dead-stripping) these TLS wrapper functions because they are not explicitly called within the godot-cpp translation units.
  4. Adding __attribute__((used)) to the variables in wrapped.cpp did not fix it.

Workaround: I was only able to make it work by manually implementing the wrapper functions in wrapped.cpp via extern "C" to match the mangled names expected by the linker:

// Manual workaround in wrapped.cpp
extern "C" {
    void* __attribute__((visibility("default"))) __attribute__((used)) 
    _ZTWN5godot7Wrapped34_constructing_extension_class_nameE() {
        return (void*)&godot::Wrapped::_constructing_extension_class_name;
    }
    // ... same for _constructing_class_binding_callbacks
}

This suggests that godot-cpp needs a more robust way to ensure these TLS wrappers are generated and exported in static libraries on macOS/Clang.

Steps to reproduce

  1. Clone godot-cpp (master branch).
  2. Use Godot 4.5.1 (stable/official) to dump the extension_api.json.
  3. Compile godot-cpp on macOS (Intel x86_64) with Clang:
    scons platform=macos target=template_debug arch=x86_64 use_llvm=yes
    
  4. Compile a GDExtension project linking against this library (also using template_debug and clang++).
  5. Run the project in Godot Editor.
  6. Observe the dlopen error in the console regarding symbol not found in flat namespace '__ZTW...'.

Minimal reproduction project

N/A

soonsolidchentuo avatar Dec 03 '25 12:12 soonsolidchentuo