Skip to content

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

@soonsolidchentuo

Description

@soonsolidchentuo

Godot version

4.5.1.stable.official.f62fdbde1

godot-cpp version

4.5 commit: da26c17

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions