diff options
author | Peter Waller <p@pwaller.net> | 2024-04-27 11:41:46 +0100 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2024-05-10 17:22:20 +0200 |
commit | 3c03811683fecb816d2b8eb01e918f83956c7220 (patch) | |
tree | 8296ea3f20484db9268c7ffb52dc3976b8c519ae | |
parent | 45ada9cefd97511e0e9bfab147d046efef53d6b9 (diff) |
llvmPackages_*.libcxx: include libcxxabi within libcxx
Key test case: nixpkgs#pkgsStatic.pkgsLLVM.ncurses Prior to this patch, this fails with errors such as: ``` error: undefined symbol: __cxa_throw ``` I think this is a reasonable solution because in #292043, libcxxabi was 'merged into libcxx', however, the commit message suggests that only dynamic linking was accounted for, because it says: ``` * linux/freebsd `libc++.so` is a linker script `LINK(libc++.so.1, -lc++abi)` making `-lc++` sufficient. ``` Whereas, I found that if I tried linking a "hello world" C++ program with a static hostPlatform, it failed unless -lc++abi was passed. Signed-off-by: Peter Waller <p@pwaller.net>
-rw-r--r-- | pkgs/development/compilers/llvm/common/libcxx/default.nix | 31 | ||||
-rw-r--r-- | pkgs/test/cc-wrapper/default.nix | 11 |
2 files changed, 42 insertions, 0 deletions
diff --git a/pkgs/development/compilers/llvm/common/libcxx/default.nix b/pkgs/development/compilers/llvm/common/libcxx/default.nix index 0e91f50551c55..5b4c2ca56ae1a 100644 --- a/pkgs/development/compilers/llvm/common/libcxx/default.nix +++ b/pkgs/development/compilers/llvm/common/libcxx/default.nix @@ -67,6 +67,12 @@ let cxxCMakeFlags = [ "-DLIBCXX_CXX_ABI=${cxxabiName}" + ] ++ lib.optionals (cxxabi == null && lib.versionAtLeast release_version "16") [ + # Note: llvm < 16 doesn't support this flag (or it's broken); handled in postInstall instead. + # Include libc++abi symbols within libc++.a for static linking libc++; + # dynamic linking includes them through libc++.so being a linker script + # which includes both shared objects. + "-DLIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY=ON" ] ++ lib.optionals (cxxabi != null) [ "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${lib.getDev cxxabi}/include" ] ++ lib.optionals (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) [ @@ -126,6 +132,31 @@ stdenv.mkDerivation (rec { postInstall = lib.optionalString (cxxabi != null) '' lndir ${lib.getDev cxxabi}/include $dev/include/c++/v1 lndir ${lib.getLib cxxabi}/lib $out/lib + libcxxabi=$out/lib/lib${cxxabi.libName}.a + '' + # LIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY=ON doesn't work for LLVM < 16 or + # external cxxabi libraries so merge libc++abi.a into libc++.a ourselves. + + # GNU binutils emits objects in LIFO order in MRI scripts so after the merge + # the objects are in reversed order so a second MRI script is required so the + # objects in the archive are listed in proper order (libc++.a, libc++abi.a) + + lib.optionalString (cxxabi != null || lib.versionOlder release_version "16") '' + libcxxabi=''${libcxxabi-$out/lib/libc++abi.a} + if [[ -f $out/lib/libc++.a && -e $libcxxabi ]]; then + $AR -M <<MRI + create $out/lib/libc++.a + addlib $out/lib/libc++.a + addlib $libcxxabi + save + end + MRI + $AR -M <<MRI + create $out/lib/libc++.a + addlib $out/lib/libc++.a + save + end + MRI + fi ''; passthru = { diff --git a/pkgs/test/cc-wrapper/default.nix b/pkgs/test/cc-wrapper/default.nix index a0088751d4a24..6a0b11a6cc974 100644 --- a/pkgs/test/cc-wrapper/default.nix +++ b/pkgs/test/cc-wrapper/default.nix @@ -46,6 +46,17 @@ in stdenv.mkDerivation { $READELF -d ./atomics.so | grep libatomic.so && echo "ok" >&2 || echo "failed" >&2 ''} + # Test that linking libc++ works, and statically. + ${lib.optionalString isCxx '' + echo "checking whether can link with libc++... " >&2 + NIX_DEBUG=1 $CXX ${./cxx-main.cc} -c -o cxx-main.o + NIX_DEBUG=1 $CC cxx-main.o -lc++ -o cxx-main + NIX_DEBUG=1 $CC cxx-main.o ${lib.getLib stdenv.cc.libcxx}/lib/libc++.a -o cxx-main-static + ${emulator} ./cxx-main + ${emulator} ./cxx-main-static + rm cxx-main{,-static,.o} + ''} + ${lib.optionalString (stdenv.isDarwin && stdenv.cc.isClang) '' echo "checking whether compiler can build with CoreFoundation.framework... " >&2 mkdir -p foo/lib |