thread_local is a c++11 feature that newer software is increasingly using. It is available with gcc 4.8+, and with clang since about clang-3.5. On macOS (darwin) it requires system supports that arrived in 10.7.
My goal is to get thread_local with clang-5.0 and newer on 10.6 (and 10.5). Turns out this may actually be not too hard to do. The LLVM team has enabled a form of thread_local called emulated-tls that is based on emultls.c in the llvm compiler-runtime project. This is currently enabled by default for a few OS versions. With three very simple patches, clang-5.0 can be made to support thread_local on 10.6, using emutls.c. 1. Tell clang it is allowed to support thread_local on older systems: <https://github.com/kencu/SnowLeopardPorts/blob/master/lang/llvm-5.0/files/9998-patch-tools-clang-lib-basic-targets-force-tls.diff> 2. pass the -femulated-tls flag by default on older systems: <https://github.com/kencu/SnowLeopardPorts/blob/master/lang/llvm-5.0/files/9998-patch-tools-clang-lib-basic-targets-force-tls.diff> 3. tell clang to call __cxa_thread_atexit instead of _tlv_atexit on older darwin systems that don't have _tlv_atexit <https://github.com/kencu/SnowLeopardPorts/blob/master/lang/llvm-5.0/files/9998-patch-tools-clang-lib-codegen-itanium-cxa-atexit.diff> With those minor changes, clang-5.0 supports thread_local quite nicely, it appears, to build software that requires __thread and thread_local support. This works reasonably when linked against the newer libstdc++ , using -stdlib=macports-libstdc++ as MacPorts does currently. But there is a slight issue that I'm stuck on. I prefer to use libc++. First of all, to support this, the file cxa_thread_atexit.c is not compiled into libc++abi by default on Darwin, but it's not too difficult to add it to the build and compile it in. Once that is done, software built with thread support against libc++ works for simple (automatic) destructors, but with non-trivial destructors, there is an error I can't sort out: $ ./thread-test dyld: lazy symbol binding failed: Symbol not found: ___emutls_get_address Referenced from: /usr/lib/libc++abi.dylib Expected in: flat namespace Trace/BPT trap __emutls_get_address is a function in emutls.c, from the clang-runtime library. It is indeed compiled into the thread-test program $ nm thread-test | grep emu 0000000100003e20 t ___emutls_get_address 0000000100005228 d ___emutls_v.__tls_guard 0000000100005208 d ___emutls_v.tlobj 0000000100003fb0 t _emutls_init 0000000100005248 d _emutls_init_once.once 0000000100003fd0 t _emutls_key_destructor 0000000100005258 d _emutls_mutex 00000001000052a8 b _emutls_num_object 00000001000052b0 b _emutls_pthread_key and disassembling the executable shows proper looking code (very similar to the code that is generated when linked against -stdlib=macports-libstdc++, in fact). But for some reason, libc++abi.dylib apparently can't see the symbol for ___emutls_get_address in the executable. The exact same code works normally when linked against /opt/local/lib/libgcc/libstdc++.6.dylib I tried -flat_namespace and -force_flat_namespace but that didn't fix it. So -- I thought I'd ask here in case anyone sees something silly or obvious I'm forgetting to do. Thanks to anyone who has taken the trouble to read through to this point. Ken
