I have a strange issue that occurs during linking.
I have a header file that contains the following definition foo.hpp
:
struct Foo { static __thread int x; }
And a source file which references that variable plugin.cpp
:
#include "foo.hpp"
void bar() { int y = Foo::x; }
It compiles fine with:
$CXX -stdlib=libc++ -std=c++11 -fvisibility=hidden -fPIC -o plugin.cpp.o -c plugin.cpp
But when I try to link as a dynamic library:
$CXX -stdlib=libc++ -std=c++11 -fvisibility=hidden -dynamiclib -Wl,-undefined,dynamic_lookup -o libext.dylib ext.cpp.o
I get:
ld: illegal thread local variable reference to regular symbol __ZN3Foo1xE for architecture x86_64
However the llvm bytecode implies that the compiler is correctly seeing Foo::x
as a TLS variable.
$CXX -stdlib=libc++ -std=c++11 -fvisibility=hidden -fPIC -S -emit-llvm -o -
... omitted
@_ZN3Foo1xE = external thread_local global i32
... omitted
; Function Attrs: nounwind ssp uwtable
define hidden void @_Z3barv() #0 {
%y = alloca i32, align 4
%1 = load i32* @_ZN3Foo1xE, align 4
store i32 %1, i32* %y, align 4
ret void
}
What could be causing this linker issue, and is there a workaround? I can't seem to find any bug reports related to this.
Notes:
EDIT The same problem exists when referencing a global (instead of static class) variable.
When I use thread_local
in place of __thread
, this works fine, however thread_local
does not work with the version of LLVM that ships with Xcode.
Apples executable file format (MACH-O I believe) does not allow for Thread local storage. Its a pain in the ass. You have to create space in the threading library's memory allocation and hide the thread local variables in there. Its very very obscure.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With