У меня странная проблема, возникающая во время связывания.
У меня есть файл заголовка, который содержит следующее определение foo.hpp
:
struct Foo { static __thread int x; }
И исходный файл, который ссылается на эту переменную plugin.cpp
:
#include "foo.hpp"
void bar() { int y = Foo::x; }
Скомпилируется с помощью:
$CXX -stdlib=libc++ -std=c++11 -fvisibility=hidden -fPIC -o plugin.cpp.o -c plugin.cpp
Но когда я пытаюсь подключиться как динамическая библиотека:
$CXX -stdlib=libc++ -std=c++11 -fvisibility=hidden -dynamiclib -Wl,-undefined,dynamic_lookup -o libext.dylib ext.cpp.o
Я получаю:
ld: ссылка на локальную переменную нелегального потока на обычный символ __ZN3Foo1xE для архитектуры x86_64
Однако байт-код llvm подразумевает, что компилятор правильно видит Foo::x
как переменную TLS.
$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
}
Что может быть причиной этой проблемы с компоновщиком, и есть ли обходной путь? Кажется, я не могу найти никаких сообщений об ошибках, связанных с этим.
Примечания:
- Это чистое использование Apple LLVM 7.0.0
- У меня нет проблем с связыванием с помощью gcc 5 или gcc 4.9.3 на OS X
ИЗМЕНИТЬ Та же проблема существует при ссылке на глобальную переменную (вместо статического класса).
Когда я использую thread_local
вместо __thread
, это отлично работает, однако thread_local
не работает с версией LLVM, которая поставляется с Xcode.