From 3c03811683fecb816d2b8eb01e918f83956c7220 Mon Sep 17 00:00:00 2001 From: Peter Waller
Date: Sat, 27 Apr 2024 11:41:46 +0100 Subject: 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
---
.../compilers/llvm/common/libcxx/default.nix | 31 ++++++++++++++++++++++
pkgs/test/cc-wrapper/default.nix | 11 ++++++++
2 files changed, 42 insertions(+)
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 <