Homebrew package maintainers suggested the change for gcc 7.5.0 originated with the gcc source. I believe they're saying that the gcc source will now define _GLIBCXX_HAVE_TLS to 1 by default on OSX. Please can anyone confirm if this is true / intended? If it *is* intended I will have to dig further into why my clang build against that std lib now seg faults. On Thu, 19 Dec 2019 at 17:25, Dave Gittins <dave.gittins@xxxxxxxxx> wrote: > > I am having a problem building on OSX with clang, against the gcc > standard library (there are project constraints behind why I am doing > this). I am using homebrew packages for both clang and gcc. This > pattern worked fine until a recent gcc package upgrade and I would at > least like to understand better what has happened. I don't believe > there's anything wrong in gcc - however, I was hoping someone could > help me understand the *intended* situation so I can decide what to > do... > > Here's my example.cpp: > #include <mutex> > #include <iostream> > int main() > { > std::once_flag flag; > std::call_once(flag, [](){ std::cout << "Foo\n"; }); > return 0; > } > > If I build and run with any of (homebrew) clang 7.1.0, gcc 7.4.0 or > gcc 7.5.0, it builds and runs fine: > > /usr/local/Cellar/llvm@7/7.1.0_1/bin/clang++ -std=c++17 example.cpp -o example > > /usr/local/Cellar/gcc@7/7.4.0_2/bin/g++-7 -std=c++17 example.cpp -o example > > /usr/local/Cellar/gcc@7/7.5.0/bin/g++-7 -std=c++17 example.cpp -o example > > If I build with clang, but link against the gcc 7.4.0 std lib, it also > builds and runs fine: > > /usr/local/Cellar/llvm@7/7.1.0_1/bin/clang++ -isystem /usr/local/Cellar/gcc@7/7.4.0_2/include/c++/7.4.0 -isystem /usr/local/Cellar/gcc@7/7.4.0_2/include/c++/7.4.0/x86_64-apple-darwin18.5.0 -isystem /usr/local/Cellar/gcc@7/7.4.0_2/include/c++/7.4.0/backward -L /usr/local/Cellar/gcc@7/7.4.0_2/lib/gcc/7 -nostdinc++ -stdlib=libstdc++ -std=c++17 example.cpp -o example > > In this case, the executable has the following undefined symbols which > are provided by the runtime stdc++ library: > > nm example | grep __once > U __ZSt14__once_functor > U ___once_proxy > > nm /usr/local/Cellar/gcc\@7/7.4.0_2/lib/gcc/7/libstdc++.6.dylib | grep __once > 0000000000139420 S __ZSt14__once_functor > 00000000001357c0 s > __ZZN12_GLOBAL__N_127__get_once_functor_lock_ptrEvE23__once_functor_lock_ptr > 00000000001354b0 d > __ZZN9__gnu_cxx18__common_pool_baseINS_6__poolELb1EE18_S_initialize_onceEvE6__once > 00000000000bb590 T ___once_proxy > > However, if I now upgrade my homebrew gcc package to 7.5.0, things > change. I see that in this new version, _GLIBCXX_HAVE_TLS is #defined > as 1 in c++config.h (where previously it was undefined). Building with > gcc, <mutex> is now using __once_call and we link to the emulated TLS > versions from the standard library: > > /usr/local/Cellar/gcc@7/7.5.0/bin/g++-7 -std=c++17 example.cpp -o example > > nm example | grep __once > U ___emutls_v._ZSt11__once_call > U ___emutls_v._ZSt15__once_callable > U ___once_proxy > > nm /usr/local/Cellar/gcc\@7/7.5.0/lib/gcc/7/libstdc++.6.dylib | grep __once > 0000000000135160 d > __ZZN9__gnu_cxx18__common_pool_baseINS_6__poolELb1EE18_S_initialize_onceEvE6__once > 00000000001357a0 D ___emutls_v._ZSt11__once_call > 0000000000135780 D ___emutls_v._ZSt15__once_callable > 00000000000b7f90 T ___once_proxy > > > However, if I build with clang, I get unresolved symbols - the > compiler emits an object file that depends on _ZSt11__once_call, > instead of ___emutls_v._ZSt11__once_call: > > /usr/local/Cellar/llvm@7/7.1.0_1/bin/clang++ -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0 -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0/x86_64-apple-darwin18.7.0 -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0/backward -L /usr/local/Cellar/gcc@7/7.5.0/lib/gcc/7 -nostdinc++ -stdlib=libstdc++ -std=c++17 example.cpp -o example > Undefined symbols for architecture x86_64: > "std::__once_call", referenced from: > void std::call_once<main::$_0>(std::once_flag&, main::$_0&&) in > example-cba81f.o > "std::__once_callable", referenced from: > void std::call_once<main::$_0>(std::once_flag&, main::$_0&&) in > example-cba81f.o > void std::call_once<main::$_0>(std::once_flag&, > main::$_0&&)::'lambda0'()::operator()() const in example-cba81f.o > ld: symbol(s) not found for architecture x86_64 > clang-7: error: linker command failed with exit code 1 (use -v to see > invocation) > > I thought maybe I could fix this by adding -femulated-tls. This seems > to cause the compiler to link to the correct symbol name in the > standard lib, but it segfaults at runtime when calling call_once: > > /usr/local/Cellar/llvm@7/7.1.0_1/bin/clang++ -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0 -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0/x86_64-apple-darwin18.7.0 -isystem /usr/local/Cellar/gcc@7/7.5.0/include/c++/7.5.0/backward -L /usr/local/Cellar/gcc@7/7.5.0/lib/gcc/7 -nostdinc++ -stdlib=libstdc++ -std=c++17 example.cpp -o example -femulated-tls > > ./example > Segmentation fault: 11 (core dumped) > > > > I am unclear on the following: > 1. Is it valid/sensible to define _GLIBCXX_HAVE_TLS for the gcc build > on OSX? I asked this also on the homebrew forum: > https://discourse.brew.sh/t/is-it-deliberate-that-the-gcc-7-7-5-formula-now-has-glibcxx-have-tls-defined/6500 > 2. Is there any performance or functionality reason to force the > decision on whether this should be defined or not? > 3. Given that it works if I build with gcc 7.5.0 against its own std > lib, why does the clang build with -femulated-tls segfault? > > > As I said above I realise this is an issue with how these compiler > packages are being built and what I am trying to do with them, not a > gcc problem - and it may just be unsupported. However I would be very > appreciative of any insight on my above questions or suggestions of > where to go from here. > > Dave