about summary refs log tree commit diff
path: root/pkgs/development/compilers
diff options
context:
space:
mode:
authora-n-n-a-l-e-e <150648636+a-n-n-a-l-e-e@users.noreply.github.com>2024-03-11 03:53:37 -0700
committerGitHub <noreply@github.com>2024-03-11 03:53:37 -0700
commitce789e7e35e7cf72f5424f35d1b8b3ffcedd9226 (patch)
tree96f7a1f5689c5866d9250f142402c2b67ec38ed7 /pkgs/development/compilers
parentb2211920487890748920fcc83f9b769494bfa2d6 (diff)
llvmPackages_{12,13,14,15,16,17,git}.{libcxx,libcxxabi}: merge libcxxabi into libcxx (#292043)
- merge libcxxabi into libcxx for LLVM 12, 13, 14, 15, 16, 17, and git.
- remove the link time workaround `-lc++ -lc++abi` from 58 packages as it is no longer required.
- fixes https://github.com/NixOS/nixpkgs/issues/166205
- provides alternative fixes for. https://github.com/NixOS/nixpkgs/issues/269548 https://github.com/NixOS/nix/issues/9640
- pkgsCross.x86_64-freebsd builds work again

This change can be represented in 3 stages
1. merge libcxxabi into libcxx -- files: pkgs/development/compilers/llvm/[12, git]/{libcxx, libcxxabi}
2. update stdenv to account for merge -- files: stdenv.{adapters, cc.wrapper, darwin}
3. remove all references to libcxxabi outside of llvm (about 58 packages modified)

### merging libcxxabi into libcxx
- take the union of the libcxxabi and libcxx cmake flags
- eliminate the libcxx-headers-only package - it was only needed to break libcxx <-> libcxxabi circular dependency
- libcxx.cxxabi is removed. external cxxabi (freebsd) will symlink headers / libs into libcxx.
- darwin will re-export the libcxxabi symbols into libcxx so linking `-lc++` is sufficient.
- linux/freebsd `libc++.so` is a linker script `LINK(libc++.so.1, -lc++abi)` making `-lc++` sufficient.
- libcxx/default.nix [12, 17] are identical except for patches and `LIBCXX_ADDITIONAL_LIBRARIES` (only used in 16+)
- git/libcxx/defaul.nix  does not link with -nostdlib when useLLVM is true so flag is removed. this is not much different than before as libcxxabi used -nostdlib where libcxx did not, so libc was linked in anyway.

### stdenv changes
- darwin bootstrap, remove references to libcxxabi and cxxabi
- cc-wrapper: remove c++ link workaround when libcxx.cxxabi doesn't exist (still exists for LLVM pre 12)
- adapter: update overrideLibcxx to account for a pkgs.stdenv that only has libcxx

### 58 package updates
- remove `NIX_LDFLAGS = "-l${stdenv.cc.libcxx.cxxabi.libName}` as no longer needed
- swift, nodejs_v8 remove libcxxabi references in the clang override

https://github.com/NixOS/nixpkgs/pull/292043
Diffstat (limited to 'pkgs/development/compilers')
-rw-r--r--pkgs/development/compilers/bfc/default.nix7
-rw-r--r--pkgs/development/compilers/crystal/default.nix2
-rw-r--r--pkgs/development/compilers/llvm/12/compiler-rt/default.nix5
-rw-r--r--pkgs/development/compilers/llvm/12/default.nix17
-rw-r--r--pkgs/development/compilers/llvm/12/libcxx/default.nix143
-rw-r--r--pkgs/development/compilers/llvm/12/libcxx/gnu-install-dirs.patch100
-rw-r--r--pkgs/development/compilers/llvm/12/libcxxabi/default.nix87
-rw-r--r--pkgs/development/compilers/llvm/12/libcxxabi/gnu-install-dirs.patch34
-rw-r--r--pkgs/development/compilers/llvm/12/libunwind/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/12/llvm/default.nix4
-rw-r--r--pkgs/development/compilers/llvm/13/compiler-rt/default.nix5
-rw-r--r--pkgs/development/compilers/llvm/13/default.nix26
-rw-r--r--pkgs/development/compilers/llvm/13/libcxx/default.nix154
-rw-r--r--pkgs/development/compilers/llvm/13/libcxx/gnu-install-dirs.patch82
-rw-r--r--pkgs/development/compilers/llvm/13/libcxxabi/default.nix84
-rw-r--r--pkgs/development/compilers/llvm/13/libcxxabi/gnu-install-dirs.patch37
-rw-r--r--pkgs/development/compilers/llvm/14/compiler-rt/default.nix5
-rw-r--r--pkgs/development/compilers/llvm/14/default.nix20
-rw-r--r--pkgs/development/compilers/llvm/14/libcxx/default.nix152
-rw-r--r--pkgs/development/compilers/llvm/14/libcxx/gnu-install-dirs.patch21
-rw-r--r--pkgs/development/compilers/llvm/14/libcxxabi/default.nix103
-rw-r--r--pkgs/development/compilers/llvm/14/libcxxabi/gnu-install-dirs.patch22
-rw-r--r--pkgs/development/compilers/llvm/15/compiler-rt/default.nix5
-rw-r--r--pkgs/development/compilers/llvm/15/default.nix42
-rw-r--r--pkgs/development/compilers/llvm/15/libcxx/default.nix175
-rw-r--r--pkgs/development/compilers/llvm/15/libcxx/gnu-install-dirs.patch22
-rw-r--r--pkgs/development/compilers/llvm/15/libcxxabi/default.nix113
-rw-r--r--pkgs/development/compilers/llvm/15/libcxxabi/gnu-install-dirs.patch22
-rw-r--r--pkgs/development/compilers/llvm/16/compiler-rt/default.nix5
-rw-r--r--pkgs/development/compilers/llvm/16/default.nix42
-rw-r--r--pkgs/development/compilers/llvm/16/libcxx/default.nix166
-rw-r--r--pkgs/development/compilers/llvm/16/libcxx/gnu-install-dirs.patch22
-rw-r--r--pkgs/development/compilers/llvm/16/libcxxabi/default.nix114
-rw-r--r--pkgs/development/compilers/llvm/16/libcxxabi/gnu-install-dirs.patch22
-rw-r--r--pkgs/development/compilers/llvm/17/compiler-rt/default.nix5
-rw-r--r--pkgs/development/compilers/llvm/17/default.nix42
-rw-r--r--pkgs/development/compilers/llvm/17/libcxx/default.nix168
-rw-r--r--pkgs/development/compilers/llvm/17/libcxxabi/default.nix114
-rw-r--r--pkgs/development/compilers/llvm/17/libcxxabi/gnu-install-dirs.patch22
-rw-r--r--pkgs/development/compilers/llvm/git/compiler-rt/default.nix5
-rw-r--r--pkgs/development/compilers/llvm/git/default.nix42
-rw-r--r--pkgs/development/compilers/llvm/git/libcxx/0001-darwin-10.12-mbstate_t-fix.patch8
-rw-r--r--pkgs/development/compilers/llvm/git/libcxx/default.nix166
-rw-r--r--pkgs/development/compilers/llvm/git/libcxxabi/default.nix130
-rw-r--r--pkgs/development/compilers/llvm/git/libcxxabi/gnu-install-dirs.patch22
-rw-r--r--pkgs/development/compilers/open-watcom/v2.nix3
-rw-r--r--pkgs/development/compilers/swift/compiler/default.nix1
-rw-r--r--pkgs/development/compilers/swift/compiler/patches/swift-darwin-link-cxxabi.patch14
-rw-r--r--pkgs/development/compilers/swift/default.nix8
49 files changed, 681 insertions, 1935 deletions
diff --git a/pkgs/development/compilers/bfc/default.nix b/pkgs/development/compilers/bfc/default.nix
index 2ebf02b18138f..a61279b7bc54a 100644
--- a/pkgs/development/compilers/bfc/default.nix
+++ b/pkgs/development/compilers/bfc/default.nix
@@ -27,12 +27,7 @@ rustPlatform.buildRustPackage rec {
     zlib
   ];
 
-  env = {
-    LLVM_SYS_130_PREFIX = llvmPackages_13.llvm.dev;
-  } // lib.optionalAttrs stdenv.cc.isClang {
-    # Work around https://github.com/NixOS/nixpkgs/issues/166205.
-    NIX_LDFLAGS = "-l${stdenv.cc.libcxx.cxxabi.libName}";
-  };
+  env.LLVM_SYS_130_PREFIX = llvmPackages_13.llvm.dev;
 
   # process didn't exit successfully: <...> SIGSEGV
   doCheck = false;
diff --git a/pkgs/development/compilers/crystal/default.nix b/pkgs/development/compilers/crystal/default.nix
index c9ffed829b2d8..88439d7e66d18 100644
--- a/pkgs/development/compilers/crystal/default.nix
+++ b/pkgs/development/compilers/crystal/default.nix
@@ -152,7 +152,7 @@ let
         # Darwin links against libc++ not libstdc++. Newer versions of clang (12+) require
         # libc++abi to be linked explicitly (see https://github.com/NixOS/nixpkgs/issues/166205).
         substituteInPlace src/llvm/lib_llvm.cr \
-          --replace '@[Link("stdc++")]' '@[Link("c++", "-l${stdenv.cc.libcxx.cxxabi.libName}")]'
+          --replace '@[Link("stdc++")]' '@[Link("c++")]'
       '';
 
       # Defaults are 4
diff --git a/pkgs/development/compilers/llvm/12/compiler-rt/default.nix b/pkgs/development/compilers/llvm/12/compiler-rt/default.nix
index 4b2bdad454ae2..a3cc65e202357 100644
--- a/pkgs/development/compilers/llvm/12/compiler-rt/default.nix
+++ b/pkgs/development/compilers/llvm/12/compiler-rt/default.nix
@@ -1,5 +1,5 @@
 { lib, stdenv, llvm_meta, version, fetch
-, cmake, python3, xcbuild, libllvm, linuxHeaders, libcxxabi, libxcrypt
+, cmake, python3, xcbuild, libllvm, linuxHeaders, libxcrypt
 , doFakeLibgcc ? stdenv.hostPlatform.isFreeBSD
 }:
 
@@ -20,8 +20,7 @@ stdenv.mkDerivation {
   nativeBuildInputs = [ cmake python3 libllvm.dev ]
     ++ lib.optional stdenv.isDarwin xcbuild.xcrun;
   buildInputs =
-    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders
-    ++ lib.optional stdenv.hostPlatform.isDarwin libcxxabi;
+    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders;
 
   env.NIX_CFLAGS_COMPILE = toString [
     "-DSCUDO_DEFAULT_OPTIONS=DeleteSizeMismatch=0:DeallocationTypeMismatch=0"
diff --git a/pkgs/development/compilers/llvm/12/default.nix b/pkgs/development/compilers/llvm/12/default.nix
index a38e35e91f6d0..bd87dc5f34f03 100644
--- a/pkgs/development/compilers/llvm/12/default.nix
+++ b/pkgs/development/compilers/llvm/12/default.nix
@@ -109,7 +109,6 @@ let
       cc = tools.clang-unwrapped;
       libcxx = targetLlvmLibraries.libcxx;
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ];
       extraBuildCommands = mkExtraBuildCommands cc;
@@ -163,7 +162,6 @@ let
       libcxx = targetLlvmLibraries.libcxx;
       bintools = bintools';
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
         targetLlvmLibraries.libunwind
@@ -257,24 +255,13 @@ let
 
     libcxx = callPackage ./libcxx {
       inherit llvm_meta;
-      stdenv = if stdenv.hostPlatform.useLLVM or false
-               then overrideCC stdenv buildLlvmTools.clangNoLibcxx
-               else stdenv;
-    };
-
-    libcxxabi = callPackage ./libcxxabi {
-      inherit llvm_meta;
-      stdenv = if stdenv.hostPlatform.useLLVM or false
-               then overrideCC stdenv buildLlvmTools.clangNoLibcxx
-               else stdenv;
+      stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcxx;
     };
 
     libunwind = callPackage ./libunwind {
       inherit llvm_meta;
       inherit (buildLlvmTools) llvm;
-      stdenv = if stdenv.hostPlatform.useLLVM or false
-               then overrideCC stdenv buildLlvmTools.clangNoLibcxx
-               else stdenv;
+      stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcxx;
     };
 
     openmp = callPackage ./openmp {
diff --git a/pkgs/development/compilers/llvm/12/libcxx/default.nix b/pkgs/development/compilers/llvm/12/libcxx/default.nix
index 67e2aed35cb66..7ed4b2e94242a 100644
--- a/pkgs/development/compilers/llvm/12/libcxx/default.nix
+++ b/pkgs/development/compilers/llvm/12/libcxx/default.nix
@@ -1,68 +1,127 @@
-{ lib, stdenv, llvm_meta, fetch, cmake, python3, llvm, fixDarwinDylibNames, version
-, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else libcxxabi
-, libcxxabi, libcxxrt
+{ lib, stdenv, llvm_meta
+, fetchFromGitHub, runCommand, substitute
+, cmake, lndir, ninja, python3, fixDarwinDylibNames, version
+, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else null
+, libcxxrt, libunwind
 , enableShared ? !stdenv.hostPlatform.isStatic
 }:
 
-assert stdenv.isDarwin -> cxxabi.pname == "libcxxabi";
+# external cxxabi is not supported on Darwin as the build will not link libcxx
+# properly and not re-export the cxxabi symbols into libcxx
+# https://github.com/NixOS/nixpkgs/issues/166205
+# https://github.com/NixOS/nixpkgs/issues/269548
+assert cxxabi == null || !stdenv.hostPlatform.isDarwin;
+let
+  basename = "libcxx";
+  cxxabiName = "lib${if cxxabi == null then "cxxabi" else cxxabi.libName}";
+  runtimes = [ "libcxx" ] ++ lib.optional (cxxabi == null) "libcxxabi";
 
-stdenv.mkDerivation {
-  pname = "libcxx";
-  inherit version;
+  # Note: useLLVM is likely false for Darwin but true under pkgsLLVM
+  useLLVM = stdenv.hostPlatform.useLLVM or false;
 
-  src = fetch "libcxx" "05cx39ldlxchck454lgfly1xj0c7x65iyx4hqhiihrlg6p6qj854";
+  cxxabiCMakeFlags = lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXXABI_ENABLE_THREADS=OFF"
+    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXXABI_ENABLE_SHARED=OFF"
+  ];
 
-  postUnpack = ''
-    unpackFile ${libcxxabi.src}
-    mv libcxxabi-* libcxxabi
-    unpackFile ${llvm.src}
-    mv llvm-* llvm
-  '';
+  cxxCMakeFlags = [
+    "-DLIBCXX_CXX_ABI=${cxxabiName}"
+  ] ++ lib.optionals (cxxabi != null) [
+    "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${lib.getDev cxxabi}/include"
+  ] ++ lib.optionals (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) [
+    "-DLIBCXX_HAS_MUSL_LIBC=1"
+  ] ++ lib.optionals useLLVM [
+    "-DLIBCXX_USE_COMPILER_RT=ON"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXX_ENABLE_THREADS=OFF"
+    "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
+    "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXX_ENABLE_SHARED=OFF"
+  ];
+
+  cmakeFlags = [
+    "-DLLVM_ENABLE_RUNTIMES=${lib.concatStringsSep ";" runtimes}"
+  ] ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    # libcxxabi's CMake looks as though it treats -nostdlib++ as implying -nostdlib,
+    # but that does not appear to be the case for example when building
+    # pkgsLLVM.libcxxabi (which uses clangNoCompilerRtWithLibc).
+    "-DCMAKE_EXE_LINKER_FLAGS=-nostdlib"
+    "-DCMAKE_SHARED_LINKER_FLAGS=-nostdlib"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DCMAKE_C_COMPILER_WORKS=ON"
+    "-DCMAKE_CXX_COMPILER_WORKS=ON"
+    "-DUNIX=ON" # Required otherwise libc++ fails to detect the correct linker
+  ] ++ cxxCMakeFlags
+    ++ lib.optionals (cxxabi == null) cxxabiCMakeFlags;
+
+in
+
+stdenv.mkDerivation rec {
+  pname = basename;
+  inherit version cmakeFlags;
+
+  src = fetchFromGitHub {
+    owner = "llvm";
+    repo = "llvm-project";
+    rev = "refs/tags/llvmorg-${version}";
+    sparseCheckout = [
+      "libcxx"
+      "libcxxabi"
+      "llvm/cmake"
+      "llvm/utils"
+      "runtimes"
+    ];
+    hash = "sha256-etxgXIdWxMTmbZ83Hsc0w6Jt5OSQSUEPVEWqLkHsNBY=";
+  };
 
   outputs = [ "out" "dev" ];
 
   patches = [
-    ./gnu-install-dirs.patch
+    (substitute {
+      src = ../../common/libcxxabi/wasm.patch;
+      replacements = [
+        "--replace-fail" "/cmake/" "/llvm/cmake/"
+      ];
+    })
   ] ++ lib.optionals stdenv.hostPlatform.isMusl [
-    ../../common/libcxx/libcxx-0001-musl-hacks.patch
+    (substitute {
+      src = ../../common/libcxx/libcxx-0001-musl-hacks.patch;
+      replacements = [
+        "--replace-fail" "/include/" "/libcxx/include/"
+      ];
+    })
   ];
 
+  postPatch = ''
+    cd runtimes
+  '';
+
   preConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
     patchShebangs utils/cat_files.py
   '';
 
-  nativeBuildInputs = [ cmake python3 ]
-    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames;
+  nativeBuildInputs = [ cmake ninja python3 ]
+    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames
+    ++ lib.optional (cxxabi != null) lndir;
 
-  buildInputs = [ cxxabi ];
+  buildInputs = [ cxxabi ]
+    ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [ libunwind ];
 
-  cmakeFlags = [
-    "-DLIBCXX_CXX_ABI=${cxxabi.pname}"
-  ] ++ lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) "-DLIBCXX_HAS_MUSL_LIBC=1"
-    ++ lib.optional (stdenv.hostPlatform.useLLVM or false) "-DLIBCXX_USE_COMPILER_RT=ON"
-    ++ lib.optionals stdenv.hostPlatform.isWasm [
-      "-DLIBCXX_ENABLE_THREADS=OFF"
-      "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
-      "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
-    ] ++ lib.optional (!enableShared) "-DLIBCXX_ENABLE_SHARED=OFF";
-
-  preInstall = lib.optionalString (stdenv.isDarwin) ''
-    for file in lib/*.dylib; do
-      if [ -L "$file" ]; then continue; fi
-
-      baseName=$(basename $(${stdenv.cc.targetPrefix}otool -D $file | tail -n 1))
-      installName="$out/lib/$baseName"
-      abiName=$(echo "$baseName" | sed -e 's/libc++/libc++abi/')
-
-      for other in $(${stdenv.cc.targetPrefix}otool -L $file | awk '$1 ~ "/libc\\+\\+abi" { print $1 }'); do
-        ${stdenv.cc.targetPrefix}install_name_tool -change $other ${cxxabi}/lib/$abiName $file
-      done
-    done
+  # libc++.so is a linker script which expands to multiple libraries,
+  # libc++.so.1 and libc++abi.so or the external cxxabi. ld-wrapper doesn't
+  # support linker scripts so the external cxxabi needs to be symlinked in
+  postInstall = lib.optionalString (cxxabi != null) ''
+    lndir ${lib.getDev cxxabi}/include $out/include/c++/v1
+    lndir ${lib.getLib cxxabi}/lib $out/lib
   '';
 
   passthru = {
     isLLVM = true;
-    inherit cxxabi;
   };
 
   meta = llvm_meta // {
diff --git a/pkgs/development/compilers/llvm/12/libcxx/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/12/libcxx/gnu-install-dirs.patch
deleted file mode 100644
index 1f9de00a9d56f..0000000000000
--- a/pkgs/development/compilers/llvm/12/libcxx/gnu-install-dirs.patch
+++ /dev/null
@@ -1,100 +0,0 @@
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 9bf1a02f0908..612cd4aab76c 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -28,6 +28,8 @@ set(LIBCXX_BINARY_INCLUDE_DIR "${LIBCXX_BINARY_DIR}/include/c++build")
- if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXX_STANDALONE_BUILD)
-   project(libcxx CXX C)
- 
-+  include(GNUInstallDirs)
-+
-   set(PACKAGE_NAME libcxx)
-   set(PACKAGE_VERSION 12.0.0)
-   set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
-@@ -402,7 +404,7 @@ endif ()
- if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++)
-   set(LIBCXX_HEADER_DIR ${LLVM_BINARY_DIR})
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++)
-+  set(LIBCXX_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++)
-   if(LIBCXX_LIBDIR_SUBDIR)
-     string(APPEND LIBCXX_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR})
-     string(APPEND LIBCXX_INSTALL_LIBRARY_DIR /${LIBCXX_LIBDIR_SUBDIR})
-@@ -410,11 +412,11 @@ if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
- elseif(LLVM_LIBRARY_OUTPUT_INTDIR)
-   set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
-   set(LIBCXX_HEADER_DIR  ${LLVM_BINARY_DIR})
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX})
-+  set(LIBCXX_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXX_LIBDIR_SUFFIX})
- else()
-   set(LIBCXX_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXX_LIBDIR_SUFFIX})
-   set(LIBCXX_HEADER_DIR  ${CMAKE_BINARY_DIR})
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX})
-+  set(LIBCXX_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXX_LIBDIR_SUFFIX})
- endif()
- 
- file(MAKE_DIRECTORY "${LIBCXX_BINARY_INCLUDE_DIR}")
-diff --git a/cmake/Modules/HandleLibCXXABI.cmake b/cmake/Modules/HandleLibCXXABI.cmake
-index 5d2764e870e9..bb1ec5de6ca2 100644
---- a/cmake/Modules/HandleLibCXXABI.cmake
-+++ b/cmake/Modules/HandleLibCXXABI.cmake
-@@ -63,7 +63,7 @@ macro(setup_abi_lib abidefines abishared abistatic abifiles abidirs)
- 
-         if (LIBCXX_INSTALL_HEADERS)
-           install(FILES "${LIBCXX_BINARY_INCLUDE_DIR}/${fpath}"
--            DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1/${dstdir}
-+            DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}${CMAKE_INSTALL_INCLUDEDIR}/c++/v1/${dstdir}
-             COMPONENT cxx-headers
-             PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
-             )
-diff --git a/include/CMakeLists.txt b/include/CMakeLists.txt
-index 29a317b8ae9a..4747263cfd1b 100644
---- a/include/CMakeLists.txt
-+++ b/include/CMakeLists.txt
-@@ -252,7 +252,7 @@ if (LIBCXX_INSTALL_HEADERS)
-   foreach(file ${files})
-     get_filename_component(dir ${file} DIRECTORY)
-     install(FILES ${file}
--      DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1/${dir}
-+      DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}${CMAKE_INSTALL_INCLUDEDIR}/c++/v1/${dir}
-       COMPONENT cxx-headers
-       PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
-     )
-@@ -260,7 +260,7 @@ if (LIBCXX_INSTALL_HEADERS)
- 
-   # Install the generated header as __config.
-   install(FILES ${LIBCXX_BINARY_DIR}/__generated_config
--    DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}include/c++/v1
-+    DESTINATION ${LIBCXX_INSTALL_HEADER_PREFIX}${CMAKE_INSTALL_INCLUDEDIR}/c++/v1
-     PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
-     RENAME __config
-     COMPONENT cxx-headers)
-diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
-index 9965104cb5b2..9b55dbb1d822 100644
---- a/src/CMakeLists.txt
-+++ b/src/CMakeLists.txt
-@@ -352,21 +352,21 @@ if (LIBCXX_INSTALL_SHARED_LIBRARY)
-   install(TARGETS cxx_shared
-     ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
-     LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
--    RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}bin COMPONENT cxx)
-+    RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}${CMAKE_INSTALL_BINDIR} COMPONENT cxx)
- endif()
- 
- if (LIBCXX_INSTALL_STATIC_LIBRARY)
-   install(TARGETS cxx_static
-     ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
-     LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
--    RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}bin COMPONENT cxx)
-+    RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}${CMAKE_INSTALL_BINDIR} COMPONENT cxx)
- endif()
- 
- if(LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY)
-   install(TARGETS cxx_experimental
-     LIBRARY DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
-     ARCHIVE DESTINATION ${LIBCXX_INSTALL_PREFIX}${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
--    RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}bin COMPONENT cxx)
-+    RUNTIME DESTINATION ${LIBCXX_INSTALL_PREFIX}${CMAKE_INSTALL_BINDIR} COMPONENT cxx)
- endif()
- 
- # NOTE: This install command must go after the cxx install command otherwise
diff --git a/pkgs/development/compilers/llvm/12/libcxxabi/default.nix b/pkgs/development/compilers/llvm/12/libcxxabi/default.nix
deleted file mode 100644
index 5ebb77ad3880f..0000000000000
--- a/pkgs/development/compilers/llvm/12/libcxxabi/default.nix
+++ /dev/null
@@ -1,87 +0,0 @@
-{ lib, stdenv, llvm_meta, cmake, python3, fetch, libcxx, libunwind, llvm, version
-, enableShared ? !stdenv.hostPlatform.isStatic
-, standalone ? stdenv.hostPlatform.useLLVM or false
-, withLibunwind ? !stdenv.isDarwin && !stdenv.hostPlatform.isWasm
-}:
-
-stdenv.mkDerivation {
-  pname = "libcxxabi";
-  inherit version;
-
-  src = fetch "libcxxabi" "1l4idd8npbkm168d26kqn529yv3npsd8f2dm8a7iwyknj7iyivw8";
-
-  outputs = [ "out" "dev" ];
-
-  postUnpack = ''
-    unpackFile ${libcxx.src}
-    mv libcxx-* libcxx
-    unpackFile ${llvm.src}
-    mv llvm-* llvm
-  '' + lib.optionalString stdenv.isDarwin ''
-    export TRIPLE=x86_64-apple-darwin
-  '' + lib.optionalString stdenv.hostPlatform.isMusl ''
-    patch -p1 -d libcxx -i ${../../common/libcxx/libcxx-0001-musl-hacks.patch}
-  '' + lib.optionalString stdenv.hostPlatform.isWasm ''
-    patch -p1 -d llvm -i ${../../common/libcxxabi/wasm.patch}
-  '';
-
-  patches = [
-    ./gnu-install-dirs.patch
-  ];
-
-  nativeBuildInputs = [ cmake python3 ];
-  buildInputs = lib.optional withLibunwind libunwind;
-
-  cmakeFlags = lib.optionals standalone [
-    "-DLLVM_ENABLE_LIBCXX=ON"
-    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
-  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
-    "-DLIBCXXABI_ENABLE_THREADS=OFF"
-    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
-  ] ++ lib.optionals (!enableShared) [
-    "-DLIBCXXABI_ENABLE_SHARED=OFF"
-  ];
-
-  preInstall = lib.optionalString stdenv.isDarwin ''
-    for file in lib/*.dylib; do
-      if [ -L "$file" ]; then continue; fi
-
-      # Fix up the install name. Preserve the basename, just replace the path.
-      installName="$out/lib/$(basename $(${stdenv.cc.targetPrefix}otool -D $file | tail -n 1))"
-
-      # this should be done in CMake, but having trouble figuring out
-      # the magic combination of necessary CMake variables
-      # if you fancy a try, take a look at
-      # https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling
-      ${stdenv.cc.targetPrefix}install_name_tool -id $installName $file
-
-      # cc-wrapper passes '-lc++abi' to all c++ link steps, but that causes
-      # libcxxabi to sometimes link against a different version of itself.
-      # Here we simply make that second reference point to ourselves.
-      for other in $(${stdenv.cc.targetPrefix}otool -L $file | awk '$1 ~ "/libc\\+\\+abi" { print $1 }'); do
-        ${stdenv.cc.targetPrefix}install_name_tool -change $other $installName $file
-      done
-    done
-  '';
-
-  postInstall = ''
-    mkdir -p "$dev/include"
-    install -m 644 ../include/${if stdenv.isDarwin then "*" else "cxxabi.h"} "$dev/include"
-  '';
-
-  passthru = {
-    libName = "c++abi";
-  };
-
-  meta = llvm_meta // {
-    homepage = "https://libcxxabi.llvm.org/";
-    description = "Provides C++ standard library support";
-    longDescription = ''
-      libc++abi is a new implementation of low level support for a standard C++ library.
-    '';
-    # "All of the code in libc++abi is dual licensed under the MIT license and
-    # the UIUC License (a BSD-like license)":
-    license = with lib.licenses; [ mit ncsa ];
-    maintainers = llvm_meta.maintainers ++ [ lib.maintainers.vlstill ];
-  };
-}
diff --git a/pkgs/development/compilers/llvm/12/libcxxabi/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/12/libcxxabi/gnu-install-dirs.patch
deleted file mode 100644
index b49b1685940f8..0000000000000
--- a/pkgs/development/compilers/llvm/12/libcxxabi/gnu-install-dirs.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 426c855288fc..a9812a994f53 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -27,6 +27,8 @@ set(LIBCXXABI_LIBCXX_PATH "${CMAKE_CURRENT_LIST_DIR}/../libcxx" CACHE PATH
- if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXXABI_STANDALONE_BUILD)
-   project(libcxxabi CXX C)
- 
-+  include(GNUInstallDirs)
-+
-   set(PACKAGE_NAME libcxxabi)
-   set(PACKAGE_VERSION 11.0.0)
-   set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
-@@ -180,17 +182,17 @@ set(CMAKE_MODULE_PATH
- 
- if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++)
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++)
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++)
-   if(LIBCXX_LIBDIR_SUBDIR)
-     string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
-     string(APPEND LIBCXXABI_INSTALL_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
-   endif()
- elseif(LLVM_LIBRARY_OUTPUT_INTDIR)
-   set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX})
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXXABI_LIBDIR_SUFFIX})
- else()
-   set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX})
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXXABI_LIBDIR_SUFFIX})
- endif()
- 
- set(LIBCXXABI_INSTALL_PREFIX "" CACHE STRING "Define libc++abi destination prefix.")
diff --git a/pkgs/development/compilers/llvm/12/libunwind/default.nix b/pkgs/development/compilers/llvm/12/libunwind/default.nix
index 8ed2468769594..95e0962b46891 100644
--- a/pkgs/development/compilers/llvm/12/libunwind/default.nix
+++ b/pkgs/development/compilers/llvm/12/libunwind/default.nix
@@ -9,10 +9,8 @@ stdenv.mkDerivation rec {
   src = fetch pname "192ww6n81lj2mb9pj4043z79jp3cf58a9c2qrxjwm5c3a64n1shb";
 
   postUnpack = ''
-    unpackFile ${libcxx.src}
-    mv libcxx-* libcxx
-    unpackFile ${llvm.src}
-    mv llvm-* llvm
+    ln -s ${libcxx.src}/libcxx .
+    ln -s ${libcxx.src}/llvm .
   '';
 
   patches = [
diff --git a/pkgs/development/compilers/llvm/12/llvm/default.nix b/pkgs/development/compilers/llvm/12/llvm/default.nix
index d75ce3b3b052c..4745345a3f712 100644
--- a/pkgs/development/compilers/llvm/12/llvm/default.nix
+++ b/pkgs/development/compilers/llvm/12/llvm/default.nix
@@ -184,6 +184,10 @@ in stdenv.mkDerivation (rec {
         --replace 'Starting llvm::' 'Starting {{.*}}' \
         --replace 'Finished llvm::' 'Finished {{.*}}'
     done
+  '' + ''
+    # gcc-13 fix
+    sed -i '/#include <string>/i#include <cstdint>' \
+      include/llvm/DebugInfo/Symbolize/DIPrinter.h
   '';
 
   preConfigure = ''
diff --git a/pkgs/development/compilers/llvm/13/compiler-rt/default.nix b/pkgs/development/compilers/llvm/13/compiler-rt/default.nix
index b6a9c13ba9436..7853981bb0030 100644
--- a/pkgs/development/compilers/llvm/13/compiler-rt/default.nix
+++ b/pkgs/development/compilers/llvm/13/compiler-rt/default.nix
@@ -1,5 +1,5 @@
 { lib, stdenv, llvm_meta, version, src
-, cmake, python3, xcbuild, libllvm, linuxHeaders, libcxxabi, libxcrypt
+, cmake, python3, xcbuild, libllvm, linuxHeaders, libxcrypt
 , doFakeLibgcc ? stdenv.hostPlatform.isFreeBSD
 }:
 
@@ -22,8 +22,7 @@ stdenv.mkDerivation {
   nativeBuildInputs = [ cmake python3 libllvm.dev ]
     ++ lib.optional stdenv.isDarwin xcbuild.xcrun;
   buildInputs =
-    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders
-    ++ lib.optional stdenv.hostPlatform.isDarwin libcxxabi;
+    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders;
 
   env.NIX_CFLAGS_COMPILE = toString [
     "-DSCUDO_DEFAULT_OPTIONS=DeleteSizeMismatch=0:DeallocationTypeMismatch=0"
diff --git a/pkgs/development/compilers/llvm/13/default.nix b/pkgs/development/compilers/llvm/13/default.nix
index c811b24c48ef4..cd96231e62c35 100644
--- a/pkgs/development/compilers/llvm/13/default.nix
+++ b/pkgs/development/compilers/llvm/13/default.nix
@@ -137,7 +137,6 @@ in let
       cc = tools.clang-unwrapped;
       libcxx = targetLlvmLibraries.libcxx;
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ];
       extraBuildCommands = mkExtraBuildCommands cc;
@@ -203,7 +202,6 @@ in let
       libcxx = targetLlvmLibraries.libcxx;
       bintools = bintools';
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
         targetLlvmLibraries.libunwind
@@ -297,28 +295,8 @@ in let
 
     libcxx = callPackage ./libcxx {
       inherit llvm_meta;
-      stdenv = if stdenv.hostPlatform.useLLVM or false
-               then overrideCC stdenv buildLlvmTools.clangNoLibcxx
-               else (
-                 # libcxx >= 13 does not build on gcc9
-                 if stdenv.cc.isGNU && lib.versionOlder stdenv.cc.version "10"
-                 then pkgs.gcc10Stdenv
-                 else stdenv
-               );
-    };
-
-    libcxxabi = let
-      stdenv_ = if stdenv.hostPlatform.useLLVM or false
-               then overrideCC stdenv buildLlvmTools.clangNoLibcxx
-               else stdenv;
-      cxx-headers = callPackage ./libcxx {
-        inherit llvm_meta;
-        stdenv = stdenv_;
-        headersOnly = true;
-      };
-    in callPackage ./libcxxabi {
-      stdenv = stdenv_;
-      inherit llvm_meta cxx-headers;
+      stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcxx;
+      monorepoSrc = src;
     };
 
     libunwind = callPackage ./libunwind {
diff --git a/pkgs/development/compilers/llvm/13/libcxx/default.nix b/pkgs/development/compilers/llvm/13/libcxx/default.nix
index 2974fc80e191b..c44149904652a 100644
--- a/pkgs/development/compilers/llvm/13/libcxx/default.nix
+++ b/pkgs/development/compilers/llvm/13/libcxx/default.nix
@@ -1,80 +1,123 @@
-{ lib, stdenv, llvm_meta, src, cmake, python3, fixDarwinDylibNames, version
-, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else libcxxabi
-, libcxxabi, libcxxrt
+{ lib, stdenv, llvm_meta
+, monorepoSrc, runCommand, substitute
+, cmake, lndir, ninja, python3, fixDarwinDylibNames, version
+, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else null
+, libcxxrt, libunwind
 , enableShared ? !stdenv.hostPlatform.isStatic
-
-# If headersOnly is true, the resulting package would only include the headers.
-# Use this to break the circular dependency between libcxx and libcxxabi.
-#
-# Some context:
-# https://reviews.llvm.org/rG1687f2bbe2e2aaa092f942d4a97d41fad43eedfb
-, headersOnly ? false
 }:
 
-assert stdenv.isDarwin -> cxxabi.pname == "libcxxabi";
+# external cxxabi is not supported on Darwin as the build will not link libcxx
+# properly and not re-export the cxxabi symbols into libcxx
+# https://github.com/NixOS/nixpkgs/issues/166205
+# https://github.com/NixOS/nixpkgs/issues/269548
+assert cxxabi == null || !stdenv.hostPlatform.isDarwin;
+let
+  basename = "libcxx";
+  cxxabiName = "lib${if cxxabi == null then "cxxabi" else cxxabi.libName}";
+  runtimes = [ "libcxx" ] ++ lib.optional (cxxabi == null) "libcxxabi";
+
+  # Note: useLLVM is likely false for Darwin but true under pkgsLLVM
+  useLLVM = stdenv.hostPlatform.useLLVM or false;
+
+  cxxabiCMakeFlags = lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXXABI_ENABLE_THREADS=OFF"
+    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXXABI_ENABLE_SHARED=OFF"
+  ];
+
+  cxxCMakeFlags = [
+    "-DLIBCXX_CXX_ABI=${cxxabiName}"
+  ] ++ lib.optionals (cxxabi != null) [
+    "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${lib.getDev cxxabi}/include"
+  ] ++ lib.optionals (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) [
+    "-DLIBCXX_HAS_MUSL_LIBC=1"
+  ] ++ lib.optionals useLLVM [
+    "-DLIBCXX_USE_COMPILER_RT=ON"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXX_ENABLE_THREADS=OFF"
+    "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
+    "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXX_ENABLE_SHARED=OFF"
+  ];
+
+  cmakeFlags = [
+    "-DLLVM_ENABLE_RUNTIMES=${lib.concatStringsSep ";" runtimes}"
+  ] ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    # libcxxabi's CMake looks as though it treats -nostdlib++ as implying -nostdlib,
+    # but that does not appear to be the case for example when building
+    # pkgsLLVM.libcxxabi (which uses clangNoCompilerRtWithLibc).
+    "-DCMAKE_EXE_LINKER_FLAGS=-nostdlib"
+    "-DCMAKE_SHARED_LINKER_FLAGS=-nostdlib"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DCMAKE_C_COMPILER_WORKS=ON"
+    "-DCMAKE_CXX_COMPILER_WORKS=ON"
+    "-DUNIX=ON" # Required otherwise libc++ fails to detect the correct linker
+  ] ++ cxxCMakeFlags
+    ++ lib.optionals (cxxabi == null) cxxabiCMakeFlags;
+
+in
 
 stdenv.mkDerivation rec {
-  pname = if headersOnly then "cxx-headers" else "libcxx";
-  inherit version;
+  pname = basename;
+  inherit version cmakeFlags;
 
-  inherit src;
-  sourceRoot = "${src.name}/libcxx";
+  src = runCommand "${pname}-src-${version}" {} (''
+    mkdir -p "$out/llvm"
+    cp -r ${monorepoSrc}/libcxx "$out"
+    cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
+    cp -r ${monorepoSrc}/llvm/utils "$out/llvm"
+    cp -r ${monorepoSrc}/runtimes "$out"
+  '' + lib.optionalString (cxxabi == null) ''
+    cp -r ${monorepoSrc}/libcxxabi "$out"
+  '');
 
-  outputs = [ "out" ] ++ lib.optional (!headersOnly) "dev";
+  outputs = [ "out" "dev" ];
 
   patches = [
-    ./gnu-install-dirs.patch
+    (substitute {
+      src = ../../common/libcxxabi/wasm.patch;
+      replacements = [
+        "--replace-fail" "/cmake/" "/llvm/cmake/"
+      ];
+    })
   ] ++ lib.optionals stdenv.hostPlatform.isMusl [
-    ../../common/libcxx/libcxx-0001-musl-hacks.patch
+    (substitute {
+      src = ../../common/libcxx/libcxx-0001-musl-hacks.patch;
+      replacements = [
+        "--replace-fail" "/include/" "/libcxx/include/"
+      ];
+    })
   ];
 
+  postPatch = ''
+    cd runtimes
+  '';
+
   preConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
     patchShebangs utils/cat_files.py
   '';
 
-  nativeBuildInputs = [ cmake python3 ]
-    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames;
+  nativeBuildInputs = [ cmake ninja python3 ]
+    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames
+    ++ lib.optional (cxxabi != null) lndir;
 
-  buildInputs = lib.optionals (!headersOnly) [ cxxabi ];
+  buildInputs = [ cxxabi ]
+    ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [ libunwind ];
 
-  cmakeFlags = [ "-DLIBCXX_CXX_ABI=${cxxabi.pname}" ]
-    ++ lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) "-DLIBCXX_HAS_MUSL_LIBC=1"
-    ++ lib.optional (stdenv.hostPlatform.useLLVM or false) "-DLIBCXX_USE_COMPILER_RT=ON"
-    ++ lib.optionals stdenv.hostPlatform.isWasm [
-      "-DLIBCXX_ENABLE_THREADS=OFF"
-      "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
-      "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
-    ] ++ lib.optional (!enableShared) "-DLIBCXX_ENABLE_SHARED=OFF";
-
-  buildFlags = lib.optional headersOnly "generate-cxx-headers";
-  installTargets = lib.optional headersOnly "install-cxx-headers";
-
-  preInstall = lib.optionalString (stdenv.isDarwin && !headersOnly) ''
-    for file in lib/*.dylib; do
-      if [ -L "$file" ]; then continue; fi
-
-      baseName=$(basename $(${stdenv.cc.targetPrefix}otool -D $file | tail -n 1))
-      installName="$out/lib/$baseName"
-      abiName=$(echo "$baseName" | sed -e 's/libc++/libc++abi/')
-
-      for other in $(${stdenv.cc.targetPrefix}otool -L $file | awk '$1 ~ "/libc\\+\\+abi" { print $1 }'); do
-        ${stdenv.cc.targetPrefix}install_name_tool -change $other ${cxxabi}/lib/$abiName $file
-      done
-    done
-  '';
-
-  # At this point, cxxabi headers would be installed in the dev output, which
-  # prevents moveToOutput from doing its job later in the build process.
-  postInstall = lib.optionalString (!headersOnly) ''
-    mv "$dev/include/c++/v1/"* "$out/include/c++/v1/"
-    pushd "$dev"
-    rmdir -p include/c++/v1
-    popd
+  # libc++.so is a linker script which expands to multiple libraries,
+  # libc++.so.1 and libc++abi.so or the external cxxabi. ld-wrapper doesn't
+  # support linker scripts so the external cxxabi needs to be symlinked in
+  postInstall = lib.optionalString (cxxabi != null) ''
+    lndir ${lib.getDev cxxabi}/include ''${!outputDev}/include/c++/v1
+    lndir ${lib.getLib cxxabi}/lib ''${!outputLib}/lib
   '';
 
   passthru = {
     isLLVM = true;
-    inherit cxxabi;
   };
 
   meta = llvm_meta // {
@@ -84,7 +127,6 @@ stdenv.mkDerivation rec {
       libc++ is an implementation of the C++ standard library, targeting C++11,
       C++14 and above.
     '';
-
     # "All of the code in libc++ is dual licensed under the MIT license and the
     # UIUC License (a BSD-like license)":
     license = with lib.licenses; [ mit ncsa ];
diff --git a/pkgs/development/compilers/llvm/13/libcxx/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/13/libcxx/gnu-install-dirs.patch
deleted file mode 100644
index 744967a6ee0bd..0000000000000
--- a/pkgs/development/compilers/llvm/13/libcxx/gnu-install-dirs.patch
+++ /dev/null
@@ -1,82 +0,0 @@
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index b1e25358d41a..7fe1f4d85401 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -26,6 +26,8 @@ set(LIBCXX_BINARY_INCLUDE_DIR "${LIBCXX_BINARY_DIR}/include/c++build")
- if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXX_STANDALONE_BUILD)
-   project(libcxx CXX C)
- 
-+  include(GNUInstallDirs)
-+
-   set(PACKAGE_NAME libcxx)
-   set(PACKAGE_VERSION 13.0.0git)
-   set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
-@@ -412,7 +414,7 @@ if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
-   set(LIBCXX_GENERATED_INCLUDE_DIR "${LLVM_BINARY_DIR}/include/c++/v1")
-   set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LLVM_BINARY_DIR}/include/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1")
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-+  set(LIBCXX_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-       "Path where built libc++ libraries should be installed.")
-   set(LIBCXX_INSTALL_INCLUDE_DIR "include/c++/v1" CACHE PATH
-       "Path where target-agnostic libc++ headers should be installed.")
-@@ -426,7 +428,7 @@ elseif(LLVM_LIBRARY_OUTPUT_INTDIR)
-   set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
-   set(LIBCXX_GENERATED_INCLUDE_DIR "${LLVM_BINARY_DIR}/include/c++/v1")
-   set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LIBCXX_GENERATED_INCLUDE_DIR}")
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX} CACHE PATH
-+  set(LIBCXX_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXX_LIBDIR_SUFFIX} CACHE PATH
-       "Path where built libc++ libraries should be installed.")
-   set(LIBCXX_INSTALL_INCLUDE_DIR "include/c++/v1" CACHE PATH
-       "Path where target-agnostic libc++ headers should be installed.")
-@@ -436,7 +438,7 @@ else()
-   set(LIBCXX_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXX_LIBDIR_SUFFIX})
-   set(LIBCXX_GENERATED_INCLUDE_DIR "${CMAKE_BINARY_DIR}/include/c++/v1")
-   set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LIBCXX_GENERATED_INCLUDE_DIR}")
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX} CACHE PATH
-+  set(LIBCXX_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXX_LIBDIR_SUFFIX} CACHE PATH
-       "Path where built libc++ libraries should be installed.")
-   set(LIBCXX_INSTALL_INCLUDE_DIR "include/c++/v1" CACHE PATH
-       "Path where target-agnostic libc++ headers should be installed.")
-diff --git a/cmake/Modules/HandleLibCXXABI.cmake b/cmake/Modules/HandleLibCXXABI.cmake
-index 5a8a4a270a1a..c06bae0001aa 100644
---- a/cmake/Modules/HandleLibCXXABI.cmake
-+++ b/cmake/Modules/HandleLibCXXABI.cmake
-@@ -63,7 +63,7 @@ macro(setup_abi_lib abidefines abishared abistatic abifiles abidirs)
- 
-         if (LIBCXX_INSTALL_HEADERS)
-           install(FILES "${LIBCXX_BINARY_INCLUDE_DIR}/${fpath}"
--            DESTINATION include/c++/v1/${dstdir}
-+            DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/c++/v1/${dstdir}
-             COMPONENT cxx-headers
-             PERMISSIONS OWNER_READ OWNER_WRITE GROUP_READ WORLD_READ
-             )
-diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
-index 496429f3841e..1a0c9c0a3159 100644
---- a/src/CMakeLists.txt
-+++ b/src/CMakeLists.txt
-@@ -376,21 +376,21 @@ if (LIBCXX_INSTALL_SHARED_LIBRARY)
-   install(TARGETS cxx_shared
-     ARCHIVE DESTINATION ${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
-     LIBRARY DESTINATION ${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
--    RUNTIME DESTINATION bin COMPONENT cxx)
-+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT cxx)
- endif()
- 
- if (LIBCXX_INSTALL_STATIC_LIBRARY)
-   install(TARGETS cxx_static
-     ARCHIVE DESTINATION ${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
-     LIBRARY DESTINATION ${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
--    RUNTIME DESTINATION bin COMPONENT cxx)
-+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT cxx)
- endif()
- 
- if(LIBCXX_INSTALL_EXPERIMENTAL_LIBRARY)
-   install(TARGETS cxx_experimental
-     LIBRARY DESTINATION ${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
-     ARCHIVE DESTINATION ${LIBCXX_INSTALL_LIBRARY_DIR} COMPONENT cxx
--    RUNTIME DESTINATION bin COMPONENT cxx)
-+    RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT cxx)
- endif()
- 
- # NOTE: This install command must go after the cxx install command otherwise
diff --git a/pkgs/development/compilers/llvm/13/libcxxabi/default.nix b/pkgs/development/compilers/llvm/13/libcxxabi/default.nix
deleted file mode 100644
index 50f09831e9741..0000000000000
--- a/pkgs/development/compilers/llvm/13/libcxxabi/default.nix
+++ /dev/null
@@ -1,84 +0,0 @@
-{ lib, stdenv, llvm_meta, cmake, python3, src, cxx-headers, libunwind, version
-, enableShared ? !stdenv.hostPlatform.isStatic
-, standalone ? stdenv.hostPlatform.useLLVM or false
-, withLibunwind ? !stdenv.isDarwin && !stdenv.hostPlatform.isWasm
-}:
-
-stdenv.mkDerivation rec {
-  pname = "libcxxabi";
-  inherit version;
-
-  inherit src;
-  sourceRoot = "${src.name}/${pname}";
-
-  outputs = [ "out" "dev" ];
-
-  postUnpack = lib.optionalString stdenv.isDarwin ''
-    export TRIPLE=x86_64-apple-darwin
-  '' + lib.optionalString stdenv.hostPlatform.isWasm ''
-    patch -p1 -d llvm -i ${../../common/libcxxabi/wasm.patch}
-  '';
-
-  patches = [
-    ./gnu-install-dirs.patch
-  ];
-
-  nativeBuildInputs = [ cmake python3 ];
-  buildInputs = lib.optional withLibunwind libunwind;
-
-  cmakeFlags = [
-    "-DLIBCXXABI_LIBCXX_INCLUDES=${cxx-headers}/include/c++/v1"
-  ] ++ lib.optionals standalone [
-    "-DLLVM_ENABLE_LIBCXX=ON"
-  ] ++ lib.optionals (standalone && withLibunwind) [
-    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
-  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
-    "-DLIBCXXABI_ENABLE_THREADS=OFF"
-    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
-  ] ++ lib.optionals (!enableShared) [
-    "-DLIBCXXABI_ENABLE_SHARED=OFF"
-  ];
-
-  preInstall = lib.optionalString stdenv.isDarwin ''
-    for file in lib/*.dylib; do
-      if [ -L "$file" ]; then continue; fi
-
-      # Fix up the install name. Preserve the basename, just replace the path.
-      installName="$out/lib/$(basename $(${stdenv.cc.targetPrefix}otool -D $file | tail -n 1))"
-
-      # this should be done in CMake, but having trouble figuring out
-      # the magic combination of necessary CMake variables
-      # if you fancy a try, take a look at
-      # https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling
-      ${stdenv.cc.targetPrefix}install_name_tool -id $installName $file
-
-      # cc-wrapper passes '-lc++abi' to all c++ link steps, but that causes
-      # libcxxabi to sometimes link against a different version of itself.
-      # Here we simply make that second reference point to ourselves.
-      for other in $(${stdenv.cc.targetPrefix}otool -L $file | awk '$1 ~ "/libc\\+\\+abi" { print $1 }'); do
-        ${stdenv.cc.targetPrefix}install_name_tool -change $other $installName $file
-      done
-    done
-  '';
-
-  postInstall = ''
-    mkdir -p "$dev/include"
-    install -m 644 ../include/${if stdenv.isDarwin then "*" else "cxxabi.h"} "$dev/include"
-  '';
-
-  passthru = {
-    libName = "c++abi";
-  };
-
-  meta = llvm_meta // {
-    homepage = "https://libcxxabi.llvm.org/";
-    description = "Provides C++ standard library support";
-    longDescription = ''
-      libc++abi is a new implementation of low level support for a standard C++ library.
-    '';
-    # "All of the code in libc++abi is dual licensed under the MIT license and
-    # the UIUC License (a BSD-like license)":
-    license = with lib.licenses; [ mit ncsa ];
-    maintainers = llvm_meta.maintainers ++ [ lib.maintainers.vlstill ];
-  };
-}
diff --git a/pkgs/development/compilers/llvm/13/libcxxabi/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/13/libcxxabi/gnu-install-dirs.patch
deleted file mode 100644
index 5d562dd59a992..0000000000000
--- a/pkgs/development/compilers/llvm/13/libcxxabi/gnu-install-dirs.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 9fb35860d483..5739d9e8af62 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -27,6 +27,8 @@ set(LIBCXXABI_LIBCXX_PATH "${CMAKE_CURRENT_LIST_DIR}/../libcxx" CACHE PATH
- if (CMAKE_SOURCE_DIR STREQUAL CMAKE_CURRENT_SOURCE_DIR OR LIBCXXABI_STANDALONE_BUILD)
-   project(libcxxabi CXX C)
- 
-+  include(GNUInstallDirs)
-+
-   set(PACKAGE_NAME libcxxabi)
-   set(PACKAGE_VERSION 11.0.0git)
-   set(PACKAGE_STRING "${PACKAGE_NAME} ${PACKAGE_VERSION}")
-@@ -195,7 +197,7 @@ set(CMAKE_MODULE_PATH
- if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR})
-   set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
-   if(LIBCXX_LIBDIR_SUBDIR)
-     string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
-@@ -204,12 +206,12 @@ if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
- elseif(LLVM_LIBRARY_OUTPUT_INTDIR)
-   set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR})
-   set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR})
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
- else()
-   set(LIBCXXABI_HEADER_DIR ${CMAKE_BINARY_DIR})
-   set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
- endif()
- 
diff --git a/pkgs/development/compilers/llvm/14/compiler-rt/default.nix b/pkgs/development/compilers/llvm/14/compiler-rt/default.nix
index 1652b3a7fac0f..53da1bb125b3d 100644
--- a/pkgs/development/compilers/llvm/14/compiler-rt/default.nix
+++ b/pkgs/development/compilers/llvm/14/compiler-rt/default.nix
@@ -1,6 +1,6 @@
 { lib, stdenv, llvm_meta, version
 , monorepoSrc, runCommand
-, cmake, python3, xcbuild, libllvm, linuxHeaders, libcxxabi, libxcrypt
+, cmake, python3, xcbuild, libllvm, linuxHeaders, libxcrypt
 , doFakeLibgcc ? stdenv.hostPlatform.isFreeBSD
 }:
 
@@ -30,8 +30,7 @@ stdenv.mkDerivation {
   nativeBuildInputs = [ cmake python3 libllvm.dev ]
     ++ lib.optional stdenv.isDarwin xcbuild.xcrun;
   buildInputs =
-    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders
-    ++ lib.optional stdenv.hostPlatform.isDarwin libcxxabi;
+    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders;
 
   env.NIX_CFLAGS_COMPILE = toString [
     "-DSCUDO_DEFAULT_OPTIONS=DeleteSizeMismatch=0:DeallocationTypeMismatch=0"
diff --git a/pkgs/development/compilers/llvm/14/default.nix b/pkgs/development/compilers/llvm/14/default.nix
index 090eec2348869..66f5c7385a150 100644
--- a/pkgs/development/compilers/llvm/14/default.nix
+++ b/pkgs/development/compilers/llvm/14/default.nix
@@ -134,7 +134,6 @@ in let
       cc = tools.clang-unwrapped;
       libcxx = targetLlvmLibraries.libcxx;
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ];
       extraBuildCommands = mkExtraBuildCommands cc;
@@ -200,7 +199,6 @@ in let
       libcxx = targetLlvmLibraries.libcxx;
       bintools = bintools';
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
         targetLlvmLibraries.libunwind
@@ -296,23 +294,7 @@ in let
 
     libcxx = callPackage ./libcxx {
       inherit llvm_meta;
-      stdenv = if stdenv.hostPlatform.useLLVM or false
-               then overrideCC stdenv buildLlvmTools.clangNoLibcxx
-               else stdenv;
-    };
-
-    libcxxabi = let
-      stdenv_ = if stdenv.hostPlatform.useLLVM or false
-               then overrideCC stdenv buildLlvmTools.clangNoLibcxx
-               else stdenv;
-      cxx-headers = callPackage ./libcxx {
-        inherit llvm_meta;
-        stdenv = stdenv_;
-        headersOnly = true;
-      };
-    in callPackage ./libcxxabi {
-      stdenv = stdenv_;
-      inherit llvm_meta cxx-headers;
+      stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcxx;
     };
 
     libunwind = callPackage ./libunwind {
diff --git a/pkgs/development/compilers/llvm/14/libcxx/default.nix b/pkgs/development/compilers/llvm/14/libcxx/default.nix
index ad9e82291cde7..3234b2814379c 100644
--- a/pkgs/development/compilers/llvm/14/libcxx/default.nix
+++ b/pkgs/development/compilers/llvm/14/libcxx/default.nix
@@ -1,87 +1,129 @@
 { lib, stdenv, llvm_meta
-, monorepoSrc, runCommand
-, cmake, python3, fixDarwinDylibNames, version
-, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else libcxxabi
-, libcxxabi, libcxxrt
+, monorepoSrc, runCommand, substitute
+, cmake, lndir, ninja, python3, fixDarwinDylibNames, version
+, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else null
+, libcxxrt, libunwind
 , enableShared ? !stdenv.hostPlatform.isStatic
-
-# If headersOnly is true, the resulting package would only include the headers.
-# Use this to break the circular dependency between libcxx and libcxxabi.
-#
-# Some context:
-# https://reviews.llvm.org/rG1687f2bbe2e2aaa092f942d4a97d41fad43eedfb
-, headersOnly ? false
 }:
 
+# external cxxabi is not supported on Darwin as the build will not link libcxx
+# properly and not re-export the cxxabi symbols into libcxx
+# https://github.com/NixOS/nixpkgs/issues/166205
+# https://github.com/NixOS/nixpkgs/issues/269548
+assert cxxabi == null || !stdenv.hostPlatform.isDarwin;
 let
   basename = "libcxx";
-in
+  cxxabiName = "lib${if cxxabi == null then "cxxabi" else cxxabi.libName}";
+  runtimes = [ "libcxx" ] ++ lib.optional (cxxabi == null) "libcxxabi";
+
+  # Note: useLLVM is likely false for Darwin but true under pkgsLLVM
+  useLLVM = stdenv.hostPlatform.useLLVM or false;
+
+  cxxabiCMakeFlags = lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXXABI_ENABLE_THREADS=OFF"
+    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXXABI_ENABLE_SHARED=OFF"
+  ];
+
+  cxxCMakeFlags = [
+    "-DLIBCXX_CXX_ABI=${cxxabiName}"
+  ] ++ lib.optionals (cxxabi != null) [
+    "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${lib.getDev cxxabi}/include"
+  ] ++ lib.optionals (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) [
+    "-DLIBCXX_HAS_MUSL_LIBC=1"
+  ] ++ lib.optionals useLLVM [
+    "-DLIBCXX_USE_COMPILER_RT=ON"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXX_ENABLE_THREADS=OFF"
+    "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
+    "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXX_ENABLE_SHARED=OFF"
+  ];
 
-assert stdenv.isDarwin -> cxxabi.pname == "libcxxabi";
+  cmakeFlags = [
+    "-DLLVM_ENABLE_RUNTIMES=${lib.concatStringsSep ";" runtimes}"
+  ] ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    # libcxxabi's CMake looks as though it treats -nostdlib++ as implying -nostdlib,
+    # but that does not appear to be the case for example when building
+    # pkgsLLVM.libcxxabi (which uses clangNoCompilerRtWithLibc).
+    "-DCMAKE_EXE_LINKER_FLAGS=-nostdlib"
+    "-DCMAKE_SHARED_LINKER_FLAGS=-nostdlib"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DCMAKE_C_COMPILER_WORKS=ON"
+    "-DCMAKE_CXX_COMPILER_WORKS=ON"
+    "-DUNIX=ON" # Required otherwise libc++ fails to detect the correct linker
+  ] ++ cxxCMakeFlags
+    ++ lib.optionals (cxxabi == null) cxxabiCMakeFlags;
+
+in
 
 stdenv.mkDerivation rec {
-  pname = basename + lib.optionalString headersOnly "-headers";
-  inherit version;
+  pname = basename;
+  inherit version cmakeFlags;
 
-  src = runCommand "${pname}-src-${version}" {} ''
-    mkdir -p "$out"
-    cp -r ${monorepoSrc}/cmake "$out"
-    cp -r ${monorepoSrc}/${basename} "$out"
-    mkdir -p "$out/libcxxabi"
-    cp -r ${monorepoSrc}/libcxxabi/include "$out/libcxxabi"
+  src = runCommand "${pname}-src-${version}" {} (''
     mkdir -p "$out/llvm"
+    cp -r ${monorepoSrc}/cmake "$out"
+    cp -r ${monorepoSrc}/libcxx "$out"
     cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
     cp -r ${monorepoSrc}/llvm/utils "$out/llvm"
-  '';
-
-  sourceRoot = "${src.name}/${basename}";
+    cp -r ${monorepoSrc}/third-party "$out"
+    cp -r ${monorepoSrc}/runtimes "$out"
+  '' + lib.optionalString (cxxabi == null) ''
+    cp -r ${monorepoSrc}/libcxxabi "$out"
+  '');
 
-  outputs = [ "out" ] ++ lib.optional (!headersOnly) "dev";
+  outputs = [ "out" "dev" ];
 
   patches = [
-    ./gnu-install-dirs.patch
+    (substitute {
+      src = ../../common/libcxxabi/wasm.patch;
+      replacements = [
+        "--replace-fail" "/cmake/" "/llvm/cmake/"
+      ];
+    })
   ] ++ lib.optionals stdenv.hostPlatform.isMusl [
-    ../../common/libcxx/libcxx-0001-musl-hacks.patch
+    (substitute {
+      src = ../../common/libcxx/libcxx-0001-musl-hacks.patch;
+      replacements = [
+        "--replace-fail" "/include/" "/libcxx/include/"
+      ];
+    })
   ];
 
+  postPatch = ''
+    # fix CMake error when static and LIBCXXABI_USE_LLVM_UNWINDER=ON. aren't
+    # building unwind so don't need to depend on it
+    substituteInPlace libcxx/src/CMakeLists.txt \
+      --replace-fail "add_dependencies(cxx_static unwind)" "# add_dependencies(cxx_static unwind)"
+    cd runtimes
+  '';
+
   preConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
     patchShebangs utils/cat_files.py
   '';
 
-  nativeBuildInputs = [ cmake python3 ]
-    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames;
-
-  buildInputs = lib.optionals (!headersOnly) [ cxxabi ];
-
-  cmakeFlags = [ "-DLIBCXX_CXX_ABI=${cxxabi.pname}" ]
-    ++ lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) "-DLIBCXX_HAS_MUSL_LIBC=1"
-    ++ lib.optional (stdenv.hostPlatform.useLLVM or false) "-DLIBCXX_USE_COMPILER_RT=ON"
-    ++ lib.optionals stdenv.hostPlatform.isWasm [
-      "-DLIBCXX_ENABLE_THREADS=OFF"
-      "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
-      "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
-    ] ++ lib.optional (!enableShared) "-DLIBCXX_ENABLE_SHARED=OFF";
-
-  buildFlags = lib.optional headersOnly "generate-cxx-headers";
-  installTargets = lib.optional headersOnly "install-cxx-headers";
-
-  preInstall = lib.optionalString (stdenv.isDarwin && !headersOnly) ''
-    for file in lib/*.dylib; do
-      if [ -L "$file" ]; then continue; fi
+  nativeBuildInputs = [ cmake ninja python3 ]
+    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames
+    ++ lib.optional (cxxabi != null) lndir;
 
-      baseName=$(basename $(${stdenv.cc.targetPrefix}otool -D $file | tail -n 1))
-      installName="$out/lib/$baseName"
-      abiName=$(echo "$baseName" | sed -e 's/libc++/libc++abi/')
+  buildInputs = [ cxxabi ]
+    ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [ libunwind ];
 
-      for other in $(${stdenv.cc.targetPrefix}otool -L $file | awk '$1 ~ "/libc\\+\\+abi" { print $1 }'); do
-        ${stdenv.cc.targetPrefix}install_name_tool -change $other ${cxxabi}/lib/$abiName $file
-      done
-    done
+  # libc++.so is a linker script which expands to multiple libraries,
+  # libc++.so.1 and libc++abi.so or the external cxxabi. ld-wrapper doesn't
+  # support linker scripts so the external cxxabi needs to be symlinked in
+  postInstall = lib.optionalString (cxxabi != null) ''
+    lndir ${lib.getDev cxxabi}/include ''${!outputDev}/include/c++/v1
+    lndir ${lib.getLib cxxabi}/lib ''${!outputLib}/lib
   '';
 
   passthru = {
     isLLVM = true;
-    inherit cxxabi;
   };
 
   meta = llvm_meta // {
diff --git a/pkgs/development/compilers/llvm/14/libcxx/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/14/libcxx/gnu-install-dirs.patch
deleted file mode 100644
index bddf55d1e6051..0000000000000
--- a/pkgs/development/compilers/llvm/14/libcxx/gnu-install-dirs.patch
+++ /dev/null
@@ -1,21 +0,0 @@
-diff --git a/CMakeLists.txt b/CMakeLists.txt
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -436,7 +436,7 @@ if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
-   set(LIBCXX_GENERATED_INCLUDE_DIR "${LLVM_BINARY_DIR}/include/c++/v1")
-   set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LLVM_BINARY_DIR}/include/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1")
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-+  set(LIBCXX_INSTALL_LIBRARY_DIR "${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE}" CACHE PATH
-       "Path where built libc++ libraries should be installed.")
-   set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1" CACHE PATH
-       "Path where target-specific libc++ headers should be installed.")
-@@ -453,7 +453,7 @@ else()
-     set(LIBCXX_GENERATED_INCLUDE_DIR "${CMAKE_BINARY_DIR}/include/c++/v1")
-   endif()
-   set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LIBCXX_GENERATED_INCLUDE_DIR}")
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX} CACHE PATH
-+  set(LIBCXX_INSTALL_LIBRARY_DIR "${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}" CACHE PATH
-       "Path where built libc++ libraries should be installed.")
-   set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${LIBCXX_INSTALL_INCLUDE_DIR}" CACHE PATH
-       "Path where target-specific libc++ headers should be installed.")
diff --git a/pkgs/development/compilers/llvm/14/libcxxabi/default.nix b/pkgs/development/compilers/llvm/14/libcxxabi/default.nix
deleted file mode 100644
index 0f7cec3695d6f..0000000000000
--- a/pkgs/development/compilers/llvm/14/libcxxabi/default.nix
+++ /dev/null
@@ -1,103 +0,0 @@
-{ lib, stdenv, llvm_meta, cmake, python3
-, monorepoSrc, runCommand
-, cxx-headers, libunwind, version
-, enableShared ? !stdenv.hostPlatform.isStatic
-}:
-
-stdenv.mkDerivation rec {
-  pname = "libcxxabi";
-  inherit version;
-
-  src = runCommand "${pname}-src-${version}" {} ''
-    mkdir -p "$out"
-    cp -r ${monorepoSrc}/cmake "$out"
-    cp -r ${monorepoSrc}/${pname} "$out"
-    mkdir -p "$out/libcxx/src"
-    cp -r ${monorepoSrc}/libcxx/cmake "$out/libcxx"
-    cp -r ${monorepoSrc}/libcxx/include "$out/libcxx"
-    cp -r ${monorepoSrc}/libcxx/src/include "$out/libcxx/src"
-    mkdir -p "$out/llvm"
-    cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
-  '';
-
-  sourceRoot = "${src.name}/${pname}";
-
-  outputs = [ "out" "dev" ];
-
-  postUnpack = lib.optionalString stdenv.isDarwin ''
-    export TRIPLE=x86_64-apple-darwin
-  '' + lib.optionalString stdenv.hostPlatform.isWasm ''
-    patch -p1 -d llvm -i ${../../common/libcxxabi/wasm.patch}
-  '';
-
-  patches = [
-    ./gnu-install-dirs.patch
-  ];
-
-  nativeBuildInputs = [ cmake python3 ];
-  buildInputs = lib.optional (!stdenv.isDarwin && !stdenv.hostPlatform.isWasm) libunwind;
-
-  cmakeFlags = [
-    "-DLIBCXXABI_LIBCXX_INCLUDES=${cxx-headers}/include/c++/v1"
-  ] ++ lib.optionals (stdenv.hostPlatform.useLLVM or false) [
-    "-DLLVM_ENABLE_LIBCXX=ON"
-    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
-  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
-    "-DLIBCXXABI_ENABLE_THREADS=OFF"
-    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
-  ] ++ lib.optionals (!enableShared) [
-    "-DLIBCXXABI_ENABLE_SHARED=OFF"
-  ];
-
-  installPhase = if stdenv.isDarwin
-    then ''
-      for file in lib/*.dylib; do
-        if [ -L "$file" ]; then continue; fi
-
-        # Fix up the install name. Preserve the basename, just replace the path.
-        installName="$out/lib/$(basename $(${stdenv.cc.targetPrefix}otool -D $file | tail -n 1))"
-
-        # this should be done in CMake, but having trouble figuring out
-        # the magic combination of necessary CMake variables
-        # if you fancy a try, take a look at
-        # https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling
-        ${stdenv.cc.targetPrefix}install_name_tool -id $installName $file
-
-        # cc-wrapper passes '-lc++abi' to all c++ link steps, but that causes
-        # libcxxabi to sometimes link against a different version of itself.
-        # Here we simply make that second reference point to ourselves.
-        for other in $(${stdenv.cc.targetPrefix}otool -L $file | awk '$1 ~ "/libc\\+\\+abi" { print $1 }'); do
-          ${stdenv.cc.targetPrefix}install_name_tool -change $other $installName $file
-        done
-      done
-
-      make install
-      install -d 755 $out/include
-      install -m 644 ../include/*.h $out/include
-    ''
-    else ''
-      install -d -m 755 $out/include $out/lib
-      install -m 644 lib/libc++abi.a $out/lib
-      install -m 644 ../include/cxxabi.h $out/include
-    '' + lib.optionalString enableShared ''
-      install -m 644 lib/libc++abi.so.1.0 $out/lib
-      ln -s libc++abi.so.1.0 $out/lib/libc++abi.so
-      ln -s libc++abi.so.1.0 $out/lib/libc++abi.so.1
-    '';
-
-  passthru = {
-    libName = "c++abi";
-  };
-
-  meta = llvm_meta // {
-    homepage = "https://libcxxabi.llvm.org/";
-    description = "Provides C++ standard library support";
-    longDescription = ''
-      libc++abi is a new implementation of low level support for a standard C++ library.
-    '';
-    # "All of the code in libc++abi is dual licensed under the MIT license and
-    # the UIUC License (a BSD-like license)":
-    license = with lib.licenses; [ mit ncsa ];
-    maintainers = llvm_meta.maintainers ++ [ lib.maintainers.vlstill ];
-  };
-}
diff --git a/pkgs/development/compilers/llvm/14/libcxxabi/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/14/libcxxabi/gnu-install-dirs.patch
deleted file mode 100644
index bd25c903d5bcc..0000000000000
--- a/pkgs/development/compilers/llvm/14/libcxxabi/gnu-install-dirs.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index ecbc7091864e..53ba2dbc3bd1 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -216,7 +216,7 @@ set(LIBCXXABI_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH
- if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR})
-   set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
-   if(LIBCXX_LIBDIR_SUBDIR)
-     string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
-@@ -230,7 +230,7 @@ else()
-     set(LIBCXXABI_HEADER_DIR ${CMAKE_BINARY_DIR})
-     set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
-   endif()
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
- endif()
- 
diff --git a/pkgs/development/compilers/llvm/15/compiler-rt/default.nix b/pkgs/development/compilers/llvm/15/compiler-rt/default.nix
index fbf25786efee6..2d89407c0e639 100644
--- a/pkgs/development/compilers/llvm/15/compiler-rt/default.nix
+++ b/pkgs/development/compilers/llvm/15/compiler-rt/default.nix
@@ -1,6 +1,6 @@
 { lib, stdenv, llvm_meta, version
 , monorepoSrc, runCommand
-, cmake, ninja, python3, xcbuild, libllvm, linuxHeaders, libcxxabi, libxcrypt
+, cmake, ninja, python3, xcbuild, libllvm, linuxHeaders, libxcrypt
 , doFakeLibgcc ? stdenv.hostPlatform.isFreeBSD
 }:
 
@@ -30,8 +30,7 @@ stdenv.mkDerivation {
   nativeBuildInputs = [ cmake ninja python3 libllvm.dev ]
     ++ lib.optional stdenv.isDarwin xcbuild.xcrun;
   buildInputs =
-    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders
-    ++ lib.optional stdenv.hostPlatform.isDarwin libcxxabi;
+    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders;
 
   env.NIX_CFLAGS_COMPILE = toString [
     "-DSCUDO_DEFAULT_OPTIONS=DeleteSizeMismatch=0:DeallocationTypeMismatch=0"
diff --git a/pkgs/development/compilers/llvm/15/default.nix b/pkgs/development/compilers/llvm/15/default.nix
index d9ca0819f2e07..0ccb9c449a8da 100644
--- a/pkgs/development/compilers/llvm/15/default.nix
+++ b/pkgs/development/compilers/llvm/15/default.nix
@@ -139,7 +139,6 @@ in let
       cc = tools.clang-unwrapped;
       libcxx = targetLlvmLibraries.libcxx;
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ];
       extraBuildCommands = mkExtraBuildCommands cc;
@@ -205,7 +204,6 @@ in let
       libcxx = targetLlvmLibraries.libcxx;
       bintools = bintools';
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
         targetLlvmLibraries.libunwind
@@ -309,45 +307,7 @@ in let
 
     libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang;
 
-    libcxxabi = let
-      # CMake will "require" a compiler capable of compiling C++ programs
-      # cxx-header's build does not actually use one so it doesn't really matter
-      # what stdenv we use here, as long as CMake is happy.
-      cxx-headers = callPackage ./libcxx {
-        inherit llvm_meta;
-        # Note that if we use the regular stdenv here we'll get cycle errors
-        # when attempting to use this compiler in the stdenv.
-        #
-        # The final stdenv pulls `cxx-headers` from the package set where
-        # hostPlatform *is* the target platform which means that `stdenv` at
-        # that point attempts to use this toolchain.
-        #
-        # So, we use `stdenv_` (the stdenv containing `clang` from this package
-        # set, defined below) to sidestep this issue.
-        #
-        # Because we only use `cxx-headers` in `libcxxabi` (which depends on the
-        # clang stdenv _anyways_), this is okay.
-        stdenv = stdenv_;
-        headersOnly = true;
-      };
-
-      # `libcxxabi` *doesn't* need a compiler with a working C++ stdlib but it
-      # *does* need a relatively modern C++ compiler (see:
-      # https://releases.llvm.org/15.0.0/projects/libcxx/docs/index.html#platform-and-compiler-support).
-      #
-      # So, we use the clang from this LLVM package set, like libc++
-      # "boostrapping builds" do:
-      # https://releases.llvm.org/15.0.0/projects/libcxx/docs/BuildingLibcxx.html#bootstrapping-build
-      #
-      # We cannot use `clangNoLibcxx` because that contains `compiler-rt` which,
-      # on macOS, depends on `libcxxabi`, thus forming a cycle.
-      stdenv_ = overrideCC stdenv buildLlvmTools.clangNoCompilerRtWithLibc;
-    in callPackage ./libcxxabi {
-      stdenv = stdenv_;
-      inherit llvm_meta cxx-headers;
-    };
-
-    # Like `libcxxabi` above, `libcxx` requires a fairly modern C++ compiler,
+    # `libcxx` requires a fairly modern C++ compiler,
     # so: we use the clang from this LLVM package set instead of the regular
     # stdenv's compiler.
     libcxx = callPackage ./libcxx {
diff --git a/pkgs/development/compilers/llvm/15/libcxx/default.nix b/pkgs/development/compilers/llvm/15/libcxx/default.nix
index 6a055581fffd5..ea9f05704b340 100644
--- a/pkgs/development/compilers/llvm/15/libcxx/default.nix
+++ b/pkgs/development/compilers/llvm/15/libcxx/default.nix
@@ -1,75 +1,110 @@
 { lib, stdenv, llvm_meta
-, monorepoSrc, runCommand, fetchpatch
-, cmake, ninja, python3, fixDarwinDylibNames, version
-, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else libcxxabi
-, libcxxabi, libcxxrt, libunwind
+, monorepoSrc, runCommand, fetchpatch, substitute
+, cmake, lndir, ninja, python3, fixDarwinDylibNames, version
+, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else null
+, libcxxrt, libunwind
 , enableShared ? !stdenv.hostPlatform.isStatic
-
-# If headersOnly is true, the resulting package would only include the headers.
-# Use this to break the circular dependency between libcxx and libcxxabi.
-#
-# Some context:
-# https://reviews.llvm.org/rG1687f2bbe2e2aaa092f942d4a97d41fad43eedfb
-, headersOnly ? false
 }:
 
+# external cxxabi is not supported on Darwin as the build will not link libcxx
+# properly and not re-export the cxxabi symbols into libcxx
+# https://github.com/NixOS/nixpkgs/issues/166205
+# https://github.com/NixOS/nixpkgs/issues/269548
+assert cxxabi == null || !stdenv.hostPlatform.isDarwin;
 let
   basename = "libcxx";
-in
+  cxxabiName = "lib${if cxxabi == null then "cxxabi" else cxxabi.libName}";
+  runtimes = [ "libcxx" ] ++ lib.optional (cxxabi == null) "libcxxabi";
+
+  # Note: useLLVM is likely false for Darwin but true under pkgsLLVM
+  useLLVM = stdenv.hostPlatform.useLLVM or false;
+
+  cxxabiCMakeFlags = lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXXABI_ENABLE_THREADS=OFF"
+    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXXABI_ENABLE_SHARED=OFF"
+  ];
+
+  cxxCMakeFlags = [
+    "-DLIBCXX_CXX_ABI=${cxxabiName}"
+  ] ++ lib.optionals (cxxabi != null) [
+    "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${lib.getDev cxxabi}/include"
+  ] ++ lib.optionals (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) [
+    "-DLIBCXX_HAS_MUSL_LIBC=1"
+  ] ++ lib.optionals useLLVM [
+    "-DLIBCXX_USE_COMPILER_RT=ON"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXX_ENABLE_THREADS=OFF"
+    "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
+    "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXX_ENABLE_SHARED=OFF"
+  ];
+
+  cmakeFlags = [
+    "-DLLVM_ENABLE_RUNTIMES=${lib.concatStringsSep ";" runtimes}"
+  ] ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    # libcxxabi's CMake looks as though it treats -nostdlib++ as implying -nostdlib,
+    # but that does not appear to be the case for example when building
+    # pkgsLLVM.libcxxabi (which uses clangNoCompilerRtWithLibc).
+    "-DCMAKE_EXE_LINKER_FLAGS=-nostdlib"
+    "-DCMAKE_SHARED_LINKER_FLAGS=-nostdlib"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DCMAKE_C_COMPILER_WORKS=ON"
+    "-DCMAKE_CXX_COMPILER_WORKS=ON"
+    "-DUNIX=ON" # Required otherwise libc++ fails to detect the correct linker
+  ] ++ cxxCMakeFlags
+    ++ lib.optionals (cxxabi == null) cxxabiCMakeFlags;
 
-assert stdenv.isDarwin -> cxxabi.libName == "c++abi";
+in
 
 stdenv.mkDerivation rec {
-  pname = basename + lib.optionalString headersOnly "-headers";
-  inherit version;
+  pname = basename;
+  inherit version cmakeFlags;
 
-  src = runCommand "${pname}-src-${version}" {} ''
-    mkdir -p "$out"
-    cp -r ${monorepoSrc}/cmake "$out"
-    cp -r ${monorepoSrc}/${basename} "$out"
-    mkdir -p "$out/libcxxabi"
-    cp -r ${monorepoSrc}/libcxxabi/include "$out/libcxxabi"
+  src = runCommand "${pname}-src-${version}" {} (''
     mkdir -p "$out/llvm"
+    cp -r ${monorepoSrc}/cmake "$out"
+    cp -r ${monorepoSrc}/libcxx "$out"
     cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
     cp -r ${monorepoSrc}/llvm/utils "$out/llvm"
     cp -r ${monorepoSrc}/third-party "$out"
     cp -r ${monorepoSrc}/runtimes "$out"
-  '';
-
-  sourceRoot = "${src.name}/runtimes";
-
-  outputs = [ "out" ] ++ lib.optional (!headersOnly) "dev";
+  '' + lib.optionalString (cxxabi == null) ''
+    cp -r ${monorepoSrc}/libcxxabi "$out"
+  '');
 
-  prePatch = ''
-    cd ../${basename}
-    chmod -R u+w .
-  '';
+  outputs = [ "out" "dev" ];
 
   patches = [
-    ./gnu-install-dirs.patch
     # See:
     #   - https://reviews.llvm.org/D133566
     #   - https://github.com/NixOS/nixpkgs/issues/214524#issuecomment-1429146432
     # !!! Drop in LLVM 16+
     (fetchpatch {
       url = "https://github.com/llvm/llvm-project/commit/57c7bb3ec89565c68f858d316504668f9d214d59.patch";
-      hash = "sha256-AaM9A6tQ4YAw7uDqCIV4VaiUyLZv+unwcOqbakwW9/k=";
-      relative = "libcxx";
+      hash = "sha256-B07vHmSjy5BhhkGSj3e1E0XmMv5/9+mvC/k70Z29VwY=";
     })
-    # fix for https://github.com/NixOS/nixpkgs/issues/269548
-    # https://github.com/llvm/llvm-project/pull/77218
-    (fetchpatch {
-      name = "darwin-system-libcxxabi-link-flags.patch";
-      url = "https://github.com/llvm/llvm-project/commit/c5b89b29ee6e3c444a355fd1cf733ce7ab2e316a.patch";
-      hash = "sha256-LNoPg1KCoP8RWxU/AzHR52f4Dww24I9BGQJedMhFxyQ=";
-      relative = "libcxx";
+    (substitute {
+      src = ../../common/libcxxabi/wasm.patch;
+      replacements = [
+        "--replace-fail" "/cmake/" "/llvm/cmake/"
+      ];
     })
   ] ++ lib.optionals stdenv.hostPlatform.isMusl [
-    ../../common/libcxx/libcxx-0001-musl-hacks.patch
+    (substitute {
+      src = ../../common/libcxx/libcxx-0001-musl-hacks.patch;
+      replacements = [
+        "--replace-fail" "/include/" "/libcxx/include/"
+      ];
+    })
   ];
 
   postPatch = ''
-    cd ../runtimes
+    cd runtimes
   '';
 
   preConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
@@ -77,52 +112,22 @@ stdenv.mkDerivation rec {
   '';
 
   nativeBuildInputs = [ cmake ninja python3 ]
-    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames;
-
-  buildInputs =
-    lib.optionals (!headersOnly) [ cxxabi ]
-    ++ lib.optionals (stdenv.hostPlatform.useLLVM or false) [ libunwind ];
-
-  cmakeFlags = let
-    # See: https://libcxx.llvm.org/BuildingLibcxx.html#cmdoption-arg-libcxx-cxx-abi-string
-    libcxx_cxx_abi_opt = {
-      "c++abi" = "system-libcxxabi";
-      "cxxrt" = "libcxxrt";
-    }.${cxxabi.libName} or (throw "unknown cxxabi: ${cxxabi.libName} (${cxxabi.pname})");
-  in [
-    "-DLLVM_ENABLE_RUNTIMES=libcxx"
-    "-DLIBCXX_CXX_ABI=${if headersOnly then "none" else libcxx_cxx_abi_opt}"
-  ] ++ lib.optional (!headersOnly && cxxabi.libName == "c++abi") "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${cxxabi.dev}/include/c++/v1"
-    ++ lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) "-DLIBCXX_HAS_MUSL_LIBC=1"
-    ++ lib.optionals (stdenv.hostPlatform.useLLVM or false) [
-      "-DLIBCXX_USE_COMPILER_RT=ON"
-      # (Backport fix from 16, which has LIBCXX_ADDITIONAL_LIBRARIES, but 15
-      # does not appear to)
-      # There's precedent for this in llvm-project/libcxx/cmake/caches.
-      # In a monorepo build you might do the following in the libcxxabi build:
-      #   -DLLVM_ENABLE_PROJECTS=libcxxabi;libunwind
-      #   -DLIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY=On
-      # libcxx appears to require unwind and doesn't pull it in via other means.
-      # "-DLIBCXX_ADDITIONAL_LIBRARIES=unwind"
-      "-DCMAKE_SHARED_LINKER_FLAGS=-lunwind"
-    ] ++ lib.optionals stdenv.hostPlatform.isWasm [
-      "-DLIBCXX_ENABLE_THREADS=OFF"
-      "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
-      "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
-    ] ++ lib.optional (!enableShared) "-DLIBCXX_ENABLE_SHARED=OFF"
-    # If we're only building the headers we don't actually *need* a functioning
-    # C/C++ compiler:
-    ++ lib.optionals (headersOnly) [
-      "-DCMAKE_C_COMPILER_WORKS=ON"
-      "-DCMAKE_CXX_COMPILER_WORKS=ON"
-    ];
-
-  ninjaFlags = lib.optional headersOnly "generate-cxx-headers";
-  installTargets = lib.optional headersOnly "install-cxx-headers";
+    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames
+    ++ lib.optional (cxxabi != null) lndir;
+
+  buildInputs = [ cxxabi ]
+    ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [ libunwind ];
+
+  # libc++.so is a linker script which expands to multiple libraries,
+  # libc++.so.1 and libc++abi.so or the external cxxabi. ld-wrapper doesn't
+  # support linker scripts so the external cxxabi needs to be symlinked in
+  postInstall = lib.optionalString (cxxabi != null) ''
+    lndir ${lib.getDev cxxabi}/include ''${!outputDev}/include/c++/v1
+    lndir ${lib.getLib cxxabi}/lib ''${!outputLib}/lib
+  '';
 
   passthru = {
     isLLVM = true;
-    inherit cxxabi;
   };
 
   meta = llvm_meta // {
diff --git a/pkgs/development/compilers/llvm/15/libcxx/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/15/libcxx/gnu-install-dirs.patch
deleted file mode 100644
index daee5bdd0ed33..0000000000000
--- a/pkgs/development/compilers/llvm/15/libcxx/gnu-install-dirs.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 74eff2002fc9..c935d10878bb 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -419,7 +419,7 @@ if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
-   set(LIBCXX_GENERATED_INCLUDE_DIR "${LLVM_BINARY_DIR}/include/c++/v1")
-   set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LLVM_BINARY_DIR}/include/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1")
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-+  set(LIBCXX_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-       "Path where built libc++ libraries should be installed.")
-   set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1" CACHE PATH
-       "Path where target-specific libc++ headers should be installed.")
-@@ -436,7 +436,7 @@ else()
-     set(LIBCXX_GENERATED_INCLUDE_DIR "${CMAKE_BINARY_DIR}/include/c++/v1")
-   endif()
-   set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LIBCXX_GENERATED_INCLUDE_DIR}")
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX} CACHE PATH
-+  set(LIBCXX_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXX_LIBDIR_SUFFIX} CACHE PATH
-       "Path where built libc++ libraries should be installed.")
-   set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${LIBCXX_INSTALL_INCLUDE_DIR}" CACHE PATH
-       "Path where target-specific libc++ headers should be installed.")
diff --git a/pkgs/development/compilers/llvm/15/libcxxabi/default.nix b/pkgs/development/compilers/llvm/15/libcxxabi/default.nix
deleted file mode 100644
index 04bfee14aa186..0000000000000
--- a/pkgs/development/compilers/llvm/15/libcxxabi/default.nix
+++ /dev/null
@@ -1,113 +0,0 @@
-{ lib, stdenv, llvm_meta, cmake, ninja, python3
-, monorepoSrc, runCommand, fetchpatch
-, cxx-headers, libunwind, version
-, enableShared ? !stdenv.hostPlatform.isStatic
-}:
-
-stdenv.mkDerivation rec {
-  pname = "libcxxabi";
-  inherit version;
-
-  src = runCommand "${pname}-src-${version}" {} ''
-    mkdir -p "$out"
-    cp -r ${monorepoSrc}/cmake "$out"
-    cp -r ${monorepoSrc}/${pname} "$out"
-    mkdir -p "$out/libcxx/src"
-    cp -r ${monorepoSrc}/libcxx/cmake "$out/libcxx"
-    cp -r ${monorepoSrc}/libcxx/include "$out/libcxx"
-    cp -r ${monorepoSrc}/libcxx/src/include "$out/libcxx/src"
-    mkdir -p "$out/llvm"
-    cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
-    cp -r ${monorepoSrc}/llvm/utils "$out/llvm"
-    cp -r ${monorepoSrc}/runtimes "$out"
-  '';
-
-  sourceRoot = "${src.name}/runtimes";
-
-  outputs = [ "out" "dev" ];
-
-  postUnpack = lib.optionalString stdenv.isDarwin ''
-    export TRIPLE=x86_64-apple-darwin
-  '' + lib.optionalString stdenv.hostPlatform.isWasm ''
-    patch -p1 -d llvm -i ${../../common/libcxxabi/wasm.patch}
-  '';
-
-  prePatch = ''
-    cd ../${pname}
-    chmod -R u+w .
-  '';
-
-  patches = [
-    ./gnu-install-dirs.patch
-
-    # https://reviews.llvm.org/D132298, Allow building libcxxabi alone
-    (fetchpatch {
-      url = "https://github.com/llvm/llvm-project/commit/e6a0800532bb409f6d1c62f3698bdd6994a877dc.patch";
-      sha256 = "1xyjd56m4pfwq8p3xh6i8lhkk9kq15jaml7qbhxdf87z4jjkk63a";
-      stripLen = 1;
-    })
-  ];
-
-  postPatch = ''
-    cd ../runtimes
-  '';
-
-  nativeBuildInputs = [ cmake ninja python3 ];
-  buildInputs = lib.optional (!stdenv.isDarwin && !stdenv.hostPlatform.isWasm) libunwind;
-
-  cmakeFlags = [
-    "-DLLVM_ENABLE_RUNTIMES=libcxxabi"
-    "-DLIBCXXABI_LIBCXX_INCLUDES=${cxx-headers}/include/c++/v1"
-
-    # `libcxxabi`'s build does not need a toolchain with a c++ stdlib attached
-    # (we specify the headers it should use explicitly above).
-    #
-    # CMake however checks for this anyways; this flag tells it not to. See:
-    # https://github.com/llvm/llvm-project/blob/4bd3f3759259548e159aeba5c76efb9a0864e6fa/llvm/runtimes/CMakeLists.txt#L243
-    "-DCMAKE_CXX_COMPILER_WORKS=ON"
-  ] ++ lib.optionals (stdenv.hostPlatform.useLLVM or false) [
-    "-DLLVM_ENABLE_LIBCXX=ON"
-    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
-    # libcxxabi's CMake looks as though it treats -nostdlib++ as implying -nostdlib,
-    # but that does not appear to be the case for example when building
-    # pkgsLLVM.libcxxabi (which uses clangNoCompilerRtWithLibc).
-    "-DCMAKE_EXE_LINKER_FLAGS=-nostdlib"
-    "-DCMAKE_SHARED_LINKER_FLAGS=-nostdlib"
-  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
-    "-DLIBCXXABI_ENABLE_THREADS=OFF"
-    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
-  ] ++ lib.optionals (!enableShared) [
-    "-DLIBCXXABI_ENABLE_SHARED=OFF"
-  ];
-
-  preInstall = lib.optionalString stdenv.isDarwin ''
-    for file in lib/*.dylib; do
-      # this should be done in CMake, but having trouble figuring out
-      # the magic combination of necessary CMake variables
-      # if you fancy a try, take a look at
-      # https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling
-      install_name_tool -id $out/$file $file
-    done
-  '';
-
-  postInstall = ''
-    mkdir -p "$dev/include"
-    install -m 644 ../../${pname}/include/${if stdenv.isDarwin then "*" else "cxxabi.h"} "$dev/include"
-  '';
-
-  passthru = {
-    libName = "c++abi";
-  };
-
-  meta = llvm_meta // {
-    homepage = "https://libcxxabi.llvm.org/";
-    description = "Provides C++ standard library support";
-    longDescription = ''
-      libc++abi is a new implementation of low level support for a standard C++ library.
-    '';
-    # "All of the code in libc++abi is dual licensed under the MIT license and
-    # the UIUC License (a BSD-like license)":
-    license = with lib.licenses; [ mit ncsa ];
-    maintainers = llvm_meta.maintainers ++ [ lib.maintainers.vlstill ];
-  };
-}
diff --git a/pkgs/development/compilers/llvm/15/libcxxabi/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/15/libcxxabi/gnu-install-dirs.patch
deleted file mode 100644
index fa587612aaf63..0000000000000
--- a/pkgs/development/compilers/llvm/15/libcxxabi/gnu-install-dirs.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index b8326d08d23a..a1e36f713161 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -187,7 +187,7 @@ set(LIBCXXABI_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH
- if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR})
-   set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
-   if(LIBCXX_LIBDIR_SUBDIR)
-     string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
-@@ -201,7 +201,7 @@ else()
-     set(LIBCXXABI_HEADER_DIR ${CMAKE_BINARY_DIR})
-     set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
-   endif()
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
- endif()
- 
diff --git a/pkgs/development/compilers/llvm/16/compiler-rt/default.nix b/pkgs/development/compilers/llvm/16/compiler-rt/default.nix
index 0f15a9e12cde5..3891b4ac78c08 100644
--- a/pkgs/development/compilers/llvm/16/compiler-rt/default.nix
+++ b/pkgs/development/compilers/llvm/16/compiler-rt/default.nix
@@ -1,6 +1,6 @@
 { lib, stdenv, llvm_meta, version
 , monorepoSrc, runCommand
-, cmake, ninja, python3, xcbuild, libllvm, linuxHeaders, libcxxabi, libxcrypt
+, cmake, ninja, python3, xcbuild, libllvm, linuxHeaders, libxcrypt
 , doFakeLibgcc ? stdenv.hostPlatform.isFreeBSD
 }:
 
@@ -31,8 +31,7 @@ stdenv.mkDerivation {
   nativeBuildInputs = [ cmake ninja python3 libllvm.dev ]
     ++ lib.optional stdenv.isDarwin xcbuild.xcrun;
   buildInputs =
-    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders
-    ++ lib.optional stdenv.hostPlatform.isDarwin libcxxabi;
+    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders;
 
   env.NIX_CFLAGS_COMPILE = toString ([
     "-DSCUDO_DEFAULT_OPTIONS=DeleteSizeMismatch=0:DeallocationTypeMismatch=0"
diff --git a/pkgs/development/compilers/llvm/16/default.nix b/pkgs/development/compilers/llvm/16/default.nix
index 143076c3f76ee..66185071f22b7 100644
--- a/pkgs/development/compilers/llvm/16/default.nix
+++ b/pkgs/development/compilers/llvm/16/default.nix
@@ -139,7 +139,6 @@ in let
       cc = tools.clang-unwrapped;
       libcxx = targetLlvmLibraries.libcxx;
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ];
       extraBuildCommands = mkExtraBuildCommands cc;
@@ -214,7 +213,6 @@ in let
       libcxx = targetLlvmLibraries.libcxx;
       bintools = bintools';
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
         targetLlvmLibraries.libunwind
@@ -324,45 +322,7 @@ in let
 
     libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang;
 
-    libcxxabi = let
-      # CMake will "require" a compiler capable of compiling C++ programs
-      # cxx-header's build does not actually use one so it doesn't really matter
-      # what stdenv we use here, as long as CMake is happy.
-      cxx-headers = callPackage ./libcxx {
-        inherit llvm_meta;
-        # Note that if we use the regular stdenv here we'll get cycle errors
-        # when attempting to use this compiler in the stdenv.
-        #
-        # The final stdenv pulls `cxx-headers` from the package set where
-        # hostPlatform *is* the target platform which means that `stdenv` at
-        # that point attempts to use this toolchain.
-        #
-        # So, we use `stdenv_` (the stdenv containing `clang` from this package
-        # set, defined below) to sidestep this issue.
-        #
-        # Because we only use `cxx-headers` in `libcxxabi` (which depends on the
-        # clang stdenv _anyways_), this is okay.
-        stdenv = stdenv_;
-        headersOnly = true;
-      };
-
-      # `libcxxabi` *doesn't* need a compiler with a working C++ stdlib but it
-      # *does* need a relatively modern C++ compiler (see:
-      # https://releases.llvm.org/15.0.0/projects/libcxx/docs/index.html#platform-and-compiler-support).
-      #
-      # So, we use the clang from this LLVM package set, like libc++
-      # "boostrapping builds" do:
-      # https://releases.llvm.org/15.0.0/projects/libcxx/docs/BuildingLibcxx.html#bootstrapping-build
-      #
-      # We cannot use `clangNoLibcxx` because that contains `compiler-rt` which,
-      # on macOS, depends on `libcxxabi`, thus forming a cycle.
-      stdenv_ = overrideCC stdenv buildLlvmTools.clangNoCompilerRtWithLibc;
-    in callPackage ./libcxxabi {
-      stdenv = stdenv_;
-      inherit llvm_meta cxx-headers;
-    };
-
-    # Like `libcxxabi` above, `libcxx` requires a fairly modern C++ compiler,
+    # `libcxx` requires a fairly modern C++ compiler,
     # so: we use the clang from this LLVM package set instead of the regular
     # stdenv's compiler.
     libcxx = callPackage ./libcxx {
diff --git a/pkgs/development/compilers/llvm/16/libcxx/default.nix b/pkgs/development/compilers/llvm/16/libcxx/default.nix
index d6c8c57c17437..796eefec2d7bb 100644
--- a/pkgs/development/compilers/llvm/16/libcxx/default.nix
+++ b/pkgs/development/compilers/llvm/16/libcxx/default.nix
@@ -1,115 +1,113 @@
 { lib, stdenv, llvm_meta
 , monorepoSrc, runCommand, fetchpatch
-, cmake, ninja, python3, fixDarwinDylibNames, version
-, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else libcxxabi
-, libcxxabi, libcxxrt, libunwind
+, cmake, lndir, ninja, python3, fixDarwinDylibNames, version
+, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else null
+, libcxxrt, libunwind
 , enableShared ? !stdenv.hostPlatform.isStatic
-
-# If headersOnly is true, the resulting package would only include the headers.
-# Use this to break the circular dependency between libcxx and libcxxabi.
-#
-# Some context:
-# https://reviews.llvm.org/rG1687f2bbe2e2aaa092f942d4a97d41fad43eedfb
-, headersOnly ? false
 }:
 
+# external cxxabi is not supported on Darwin as the build will not link libcxx
+# properly and not re-export the cxxabi symbols into libcxx
+# https://github.com/NixOS/nixpkgs/issues/166205
+# https://github.com/NixOS/nixpkgs/issues/269548
+assert cxxabi == null || !stdenv.hostPlatform.isDarwin;
 let
   basename = "libcxx";
-in
+  cxxabiName = "lib${if cxxabi == null then "cxxabi" else cxxabi.libName}";
+  runtimes = [ "libcxx" ] ++ lib.optional (cxxabi == null) "libcxxabi";
+
+  # Note: useLLVM is likely false for Darwin but true under pkgsLLVM
+  useLLVM = stdenv.hostPlatform.useLLVM or false;
+
+  cxxabiCMakeFlags = lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXXABI_ENABLE_THREADS=OFF"
+    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXXABI_ENABLE_SHARED=OFF"
+  ];
+
+  cxxCMakeFlags = [
+    "-DLIBCXX_CXX_ABI=${cxxabiName}"
+  ] ++ lib.optionals (cxxabi != null) [
+    "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${lib.getDev cxxabi}/include"
+  ] ++ lib.optionals (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) [
+    "-DLIBCXX_HAS_MUSL_LIBC=1"
+  ] ++ lib.optionals useLLVM [
+    "-DLIBCXX_USE_COMPILER_RT=ON"
+    # There's precedent for this in llvm-project/libcxx/cmake/caches.
+    # In a monorepo build you might do the following in the libcxxabi build:
+    #   -DLLVM_ENABLE_PROJECTS=libcxxabi;libunwinder
+    #   -DLIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY=On
+    # libcxx appears to require unwind and doesn't pull it in via other means.
+    "-DLIBCXX_ADDITIONAL_LIBRARIES=unwind"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXX_ENABLE_THREADS=OFF"
+    "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
+    "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXX_ENABLE_SHARED=OFF"
+  ];
 
-assert stdenv.isDarwin -> cxxabi.libName == "c++abi";
+  cmakeFlags = [
+    "-DLLVM_ENABLE_RUNTIMES=${lib.concatStringsSep ";" runtimes}"
+  ] ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    # libcxxabi's CMake looks as though it treats -nostdlib++ as implying -nostdlib,
+    # but that does not appear to be the case for example when building
+    # pkgsLLVM.libcxxabi (which uses clangNoCompilerRtWithLibc).
+    "-DCMAKE_EXE_LINKER_FLAGS=-nostdlib"
+    "-DCMAKE_SHARED_LINKER_FLAGS=-nostdlib"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DCMAKE_C_COMPILER_WORKS=ON"
+    "-DCMAKE_CXX_COMPILER_WORKS=ON"
+    "-DUNIX=ON" # Required otherwise libc++ fails to detect the correct linker
+  ] ++ cxxCMakeFlags
+    ++ lib.optionals (cxxabi == null) cxxabiCMakeFlags;
+
+in
 
 stdenv.mkDerivation rec {
-  pname = basename + lib.optionalString headersOnly "-headers";
-  inherit version;
+  pname = basename;
+  inherit version cmakeFlags;
 
-  src = runCommand "${pname}-src-${version}" {} ''
-    mkdir -p "$out"
-    cp -r ${monorepoSrc}/cmake "$out"
-    cp -r ${monorepoSrc}/${basename} "$out"
-    mkdir -p "$out/libcxxabi"
-    cp -r ${monorepoSrc}/libcxxabi/include "$out/libcxxabi"
+  src = runCommand "${pname}-src-${version}" {} (''
     mkdir -p "$out/llvm"
+    cp -r ${monorepoSrc}/cmake "$out"
+    cp -r ${monorepoSrc}/libcxx "$out"
     cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
     cp -r ${monorepoSrc}/llvm/utils "$out/llvm"
     cp -r ${monorepoSrc}/third-party "$out"
     cp -r ${monorepoSrc}/runtimes "$out"
-  '';
+  '' + lib.optionalString (cxxabi == null) ''
+    cp -r ${monorepoSrc}/libcxxabi "$out"
+  '');
 
   sourceRoot = "${src.name}/runtimes";
 
-  outputs = [ "out" ] ++ lib.optional (!headersOnly) "dev";
-
-  prePatch = ''
-    cd ../${basename}
-    chmod -R u+w .
-  '';
-
-  patches = [
-    ./gnu-install-dirs.patch
-    # fix for https://github.com/NixOS/nixpkgs/issues/269548
-    # https://github.com/llvm/llvm-project/pull/77218
-    (fetchpatch {
-      name = "darwin-system-libcxxabi-link-flags.patch";
-      url = "https://github.com/llvm/llvm-project/commit/c5b89b29ee6e3c444a355fd1cf733ce7ab2e316a.patch";
-      hash = "sha256-LNoPg1KCoP8RWxU/AzHR52f4Dww24I9BGQJedMhFxyQ=";
-      relative = "libcxx";
-    })
-  ];
-
-  postPatch = ''
-    cd ../runtimes
-  '';
+  outputs = [ "out" "dev" ];
 
   preConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
     patchShebangs utils/cat_files.py
   '';
 
   nativeBuildInputs = [ cmake ninja python3 ]
-    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames;
-
-  buildInputs =
-    lib.optionals (!headersOnly) [ cxxabi ]
-    ++ lib.optionals (stdenv.hostPlatform.useLLVM or false && !stdenv.hostPlatform.isWasm) [ libunwind ];
-
-  cmakeFlags = let
-    # See: https://libcxx.llvm.org/BuildingLibcxx.html#cmdoption-arg-libcxx-cxx-abi-string
-    libcxx_cxx_abi_opt = {
-      "c++abi" = "system-libcxxabi";
-      "cxxrt" = "libcxxrt";
-    }.${cxxabi.libName} or (throw "unknown cxxabi: ${cxxabi.libName} (${cxxabi.pname})");
-  in [
-    "-DLLVM_ENABLE_RUNTIMES=libcxx"
-    "-DLIBCXX_CXX_ABI=${if headersOnly then "none" else libcxx_cxx_abi_opt}"
-  ] ++ lib.optional (!headersOnly && cxxabi.libName == "c++abi") "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${cxxabi.dev}/include/c++/v1"
-    ++ lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) "-DLIBCXX_HAS_MUSL_LIBC=1"
-    ++ lib.optionals (stdenv.hostPlatform.useLLVM or false) [
-      "-DLIBCXX_USE_COMPILER_RT=ON"
-      # There's precedent for this in llvm-project/libcxx/cmake/caches.
-      # In a monorepo build you might do the following in the libcxxabi build:
-      #   -DLLVM_ENABLE_PROJECTS=libcxxabi;libunwinder
-      #   -DLIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY=On
-      # libcxx appears to require unwind and doesn't pull it in via other means.
-      "-DLIBCXX_ADDITIONAL_LIBRARIES=unwind"
-    ] ++ lib.optionals stdenv.hostPlatform.isWasm [
-      "-DLIBCXX_ENABLE_THREADS=OFF"
-      "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
-      "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
-      "-DUNIX=ON" # Required otherwise libc++ fails to detect the correct linker
-    ] ++ lib.optional (!enableShared) "-DLIBCXX_ENABLE_SHARED=OFF"
-    # If we're only building the headers we don't actually *need* a functioning
-    # C/C++ compiler:
-    ++ lib.optionals (headersOnly) [
-      "-DCMAKE_C_COMPILER_WORKS=ON"
-      "-DCMAKE_CXX_COMPILER_WORKS=ON"
-    ];
-
-  ninjaFlags = lib.optional headersOnly "generate-cxx-headers";
-  installTargets = lib.optional headersOnly "install-cxx-headers";
+    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames
+    ++ lib.optional (cxxabi != null) lndir;
+
+  buildInputs = [ cxxabi ]
+    ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [ libunwind ];
+
+  # libc++.so is a linker script which expands to multiple libraries,
+  # libc++.so.1 and libc++abi.so or the external cxxabi. ld-wrapper doesn't
+  # support linker scripts so the external cxxabi needs to be symlinked in
+  postInstall = lib.optionalString (cxxabi != null) ''
+    lndir ${lib.getDev cxxabi}/include ''${!outputDev}/include/c++/v1
+    lndir ${lib.getLib cxxabi}/lib ''${!outputLib}/lib
+  '';
 
   passthru = {
     isLLVM = true;
-    inherit cxxabi;
   };
 
   meta = llvm_meta // {
diff --git a/pkgs/development/compilers/llvm/16/libcxx/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/16/libcxx/gnu-install-dirs.patch
deleted file mode 100644
index daee5bdd0ed33..0000000000000
--- a/pkgs/development/compilers/llvm/16/libcxx/gnu-install-dirs.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 74eff2002fc9..c935d10878bb 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -419,7 +419,7 @@ if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXX_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
-   set(LIBCXX_GENERATED_INCLUDE_DIR "${LLVM_BINARY_DIR}/include/c++/v1")
-   set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LLVM_BINARY_DIR}/include/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1")
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-+  set(LIBCXX_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-       "Path where built libc++ libraries should be installed.")
-   set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${LLVM_DEFAULT_TARGET_TRIPLE}/c++/v1" CACHE PATH
-       "Path where target-specific libc++ headers should be installed.")
-@@ -436,7 +436,7 @@ else()
-     set(LIBCXX_GENERATED_INCLUDE_DIR "${CMAKE_BINARY_DIR}/include/c++/v1")
-   endif()
-   set(LIBCXX_GENERATED_INCLUDE_TARGET_DIR "${LIBCXX_GENERATED_INCLUDE_DIR}")
--  set(LIBCXX_INSTALL_LIBRARY_DIR lib${LIBCXX_LIBDIR_SUFFIX} CACHE PATH
-+  set(LIBCXX_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXX_LIBDIR_SUFFIX} CACHE PATH
-       "Path where built libc++ libraries should be installed.")
-   set(LIBCXX_INSTALL_INCLUDE_TARGET_DIR "${LIBCXX_INSTALL_INCLUDE_DIR}" CACHE PATH
-       "Path where target-specific libc++ headers should be installed.")
diff --git a/pkgs/development/compilers/llvm/16/libcxxabi/default.nix b/pkgs/development/compilers/llvm/16/libcxxabi/default.nix
deleted file mode 100644
index 90c57dc52a2d5..0000000000000
--- a/pkgs/development/compilers/llvm/16/libcxxabi/default.nix
+++ /dev/null
@@ -1,114 +0,0 @@
-{ lib, stdenv, llvm_meta, cmake, ninja, python3
-, monorepoSrc, runCommand, fetchpatch
-, cxx-headers, libunwind, version
-, enableShared ? !stdenv.hostPlatform.isStatic
-}:
-
-stdenv.mkDerivation rec {
-  pname = "libcxxabi";
-  inherit version;
-
-  src = runCommand "${pname}-src-${version}" {} ''
-    mkdir -p "$out"
-    cp -r ${monorepoSrc}/cmake "$out"
-    cp -r ${monorepoSrc}/${pname} "$out"
-    mkdir -p "$out/libcxx/src"
-    cp -r ${monorepoSrc}/libcxx/cmake "$out/libcxx"
-    cp -r ${monorepoSrc}/libcxx/include "$out/libcxx"
-    cp -r ${monorepoSrc}/libcxx/src/include "$out/libcxx/src"
-    mkdir -p "$out/llvm"
-    cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
-    cp -r ${monorepoSrc}/llvm/utils "$out/llvm"
-    cp -r ${monorepoSrc}/runtimes "$out"
-  '';
-
-  sourceRoot = "${src.name}/runtimes";
-
-  outputs = [ "out" "dev" ];
-
-  postUnpack = lib.optionalString stdenv.isDarwin ''
-    export TRIPLE=x86_64-apple-darwin
-  '';
-
-  prePatch = ''
-    cd ../${pname}
-    chmod -R u+w .
-  '';
-
-  patches = [
-    ./gnu-install-dirs.patch
-
-    # https://reviews.llvm.org/D132298, Allow building libcxxabi alone
-    (fetchpatch {
-      url = "https://github.com/llvm/llvm-project/commit/e6a0800532bb409f6d1c62f3698bdd6994a877dc.patch";
-      sha256 = "1xyjd56m4pfwq8p3xh6i8lhkk9kq15jaml7qbhxdf87z4jjkk63a";
-      stripLen = 1;
-    })
-  ];
-
-  postPatch = ''
-    cd ../runtimes
-  '';
-
-  nativeBuildInputs = [ cmake ninja python3 ];
-  buildInputs = lib.optional (!stdenv.isDarwin && !stdenv.hostPlatform.isWasm) libunwind;
-
-  cmakeFlags = [
-    "-DLLVM_ENABLE_RUNTIMES=libcxxabi"
-    "-DLIBCXXABI_LIBCXX_INCLUDES=${cxx-headers}/include/c++/v1"
-
-    # `libcxxabi`'s build does not need a toolchain with a c++ stdlib attached
-    # (we specify the headers it should use explicitly above).
-    #
-    # CMake however checks for this anyways; this flag tells it not to. See:
-    # https://github.com/llvm/llvm-project/blob/4bd3f3759259548e159aeba5c76efb9a0864e6fa/llvm/runtimes/CMakeLists.txt#L243
-    "-DCMAKE_CXX_COMPILER_WORKS=ON"
-  ] ++ lib.optionals (stdenv.hostPlatform.useLLVM or false && !stdenv.hostPlatform.isWasm) [
-    "-DLLVM_ENABLE_LIBCXX=ON"
-    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
-    # libcxxabi's CMake looks as though it treats -nostdlib++ as implying -nostdlib,
-    # but that does not appear to be the case for example when building
-    # pkgsLLVM.libcxxabi (which uses clangNoCompilerRtWithLibc).
-    "-DCMAKE_EXE_LINKER_FLAGS=-nostdlib"
-    "-DCMAKE_SHARED_LINKER_FLAGS=-nostdlib"
-  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
-    "-DCMAKE_C_COMPILER_WORKS=ON"
-    "-DCMAKE_CXX_COMPILER_WORKS=ON"
-    "-DLIBCXXABI_ENABLE_THREADS=OFF"
-    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
-    "-DUNIX=ON" # Required otherwise libc++ fails to detect the correct linker
-  ] ++ lib.optionals (!enableShared) [
-    "-DLIBCXXABI_ENABLE_SHARED=OFF"
-  ];
-
-  preInstall = lib.optionalString stdenv.isDarwin ''
-    for file in lib/*.dylib; do
-      # this should be done in CMake, but having trouble figuring out
-      # the magic combination of necessary CMake variables
-      # if you fancy a try, take a look at
-      # https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling
-      install_name_tool -id $out/$file $file
-    done
-  '';
-
-  postInstall = ''
-    mkdir -p "$dev/include"
-    install -m 644 ../../${pname}/include/${if stdenv.isDarwin then "*" else "cxxabi.h"} "$dev/include"
-  '';
-
-  passthru = {
-    libName = "c++abi";
-  };
-
-  meta = llvm_meta // {
-    homepage = "https://libcxxabi.llvm.org/";
-    description = "Provides C++ standard library support";
-    longDescription = ''
-      libc++abi is a new implementation of low level support for a standard C++ library.
-    '';
-    # "All of the code in libc++abi is dual licensed under the MIT license and
-    # the UIUC License (a BSD-like license)":
-    license = with lib.licenses; [ mit ncsa ];
-    maintainers = llvm_meta.maintainers ++ [ lib.maintainers.vlstill ];
-  };
-}
diff --git a/pkgs/development/compilers/llvm/16/libcxxabi/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/16/libcxxabi/gnu-install-dirs.patch
deleted file mode 100644
index fa587612aaf63..0000000000000
--- a/pkgs/development/compilers/llvm/16/libcxxabi/gnu-install-dirs.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/CMakeLists.txt b/CMakeLists.txt
-index b8326d08d23a..a1e36f713161 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -187,7 +187,7 @@ set(LIBCXXABI_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE PATH
- if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR})
-   set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
-   if(LIBCXX_LIBDIR_SUBDIR)
-     string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
-@@ -201,7 +201,7 @@ else()
-     set(LIBCXXABI_HEADER_DIR ${CMAKE_BINARY_DIR})
-     set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
-   endif()
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
- endif()
- 
diff --git a/pkgs/development/compilers/llvm/17/compiler-rt/default.nix b/pkgs/development/compilers/llvm/17/compiler-rt/default.nix
index 0f15a9e12cde5..3891b4ac78c08 100644
--- a/pkgs/development/compilers/llvm/17/compiler-rt/default.nix
+++ b/pkgs/development/compilers/llvm/17/compiler-rt/default.nix
@@ -1,6 +1,6 @@
 { lib, stdenv, llvm_meta, version
 , monorepoSrc, runCommand
-, cmake, ninja, python3, xcbuild, libllvm, linuxHeaders, libcxxabi, libxcrypt
+, cmake, ninja, python3, xcbuild, libllvm, linuxHeaders, libxcrypt
 , doFakeLibgcc ? stdenv.hostPlatform.isFreeBSD
 }:
 
@@ -31,8 +31,7 @@ stdenv.mkDerivation {
   nativeBuildInputs = [ cmake ninja python3 libllvm.dev ]
     ++ lib.optional stdenv.isDarwin xcbuild.xcrun;
   buildInputs =
-    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders
-    ++ lib.optional stdenv.hostPlatform.isDarwin libcxxabi;
+    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders;
 
   env.NIX_CFLAGS_COMPILE = toString ([
     "-DSCUDO_DEFAULT_OPTIONS=DeleteSizeMismatch=0:DeallocationTypeMismatch=0"
diff --git a/pkgs/development/compilers/llvm/17/default.nix b/pkgs/development/compilers/llvm/17/default.nix
index 60cae920945b7..a9138e3c79b67 100644
--- a/pkgs/development/compilers/llvm/17/default.nix
+++ b/pkgs/development/compilers/llvm/17/default.nix
@@ -134,7 +134,6 @@ in let
       cc = tools.clang-unwrapped;
       libcxx = targetLlvmLibraries.libcxx;
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ];
       extraBuildCommands = mkExtraBuildCommands cc;
@@ -199,7 +198,6 @@ in let
       libcxx = targetLlvmLibraries.libcxx;
       bintools = bintools';
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
         targetLlvmLibraries.libunwind
@@ -308,45 +306,7 @@ in let
 
     libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang;
 
-    libcxxabi = let
-      # CMake will "require" a compiler capable of compiling C++ programs
-      # cxx-header's build does not actually use one so it doesn't really matter
-      # what stdenv we use here, as long as CMake is happy.
-      cxx-headers = callPackage ./libcxx {
-        inherit llvm_meta;
-        # Note that if we use the regular stdenv here we'll get cycle errors
-        # when attempting to use this compiler in the stdenv.
-        #
-        # The final stdenv pulls `cxx-headers` from the package set where
-        # hostPlatform *is* the target platform which means that `stdenv` at
-        # that point attempts to use this toolchain.
-        #
-        # So, we use `stdenv_` (the stdenv containing `clang` from this package
-        # set, defined below) to sidestep this issue.
-        #
-        # Because we only use `cxx-headers` in `libcxxabi` (which depends on the
-        # clang stdenv _anyways_), this is okay.
-        stdenv = stdenv_;
-        headersOnly = true;
-      };
-
-      # `libcxxabi` *doesn't* need a compiler with a working C++ stdlib but it
-      # *does* need a relatively modern C++ compiler (see:
-      # https://releases.llvm.org/15.0.0/projects/libcxx/docs/index.html#platform-and-compiler-support).
-      #
-      # So, we use the clang from this LLVM package set, like libc++
-      # "boostrapping builds" do:
-      # https://releases.llvm.org/15.0.0/projects/libcxx/docs/BuildingLibcxx.html#bootstrapping-build
-      #
-      # We cannot use `clangNoLibcxx` because that contains `compiler-rt` which,
-      # on macOS, depends on `libcxxabi`, thus forming a cycle.
-      stdenv_ = overrideCC stdenv buildLlvmTools.clangNoCompilerRtWithLibc;
-    in callPackage ./libcxxabi {
-      stdenv = stdenv_;
-      inherit llvm_meta cxx-headers;
-    };
-
-    # Like `libcxxabi` above, `libcxx` requires a fairly modern C++ compiler,
+    # `libcxx` requires a fairly modern C++ compiler,
     # so: we use the clang from this LLVM package set instead of the regular
     # stdenv's compiler.
     libcxx = callPackage ./libcxx {
diff --git a/pkgs/development/compilers/llvm/17/libcxx/default.nix b/pkgs/development/compilers/llvm/17/libcxx/default.nix
index 8f4b0cec8d400..29c5dc696bf49 100644
--- a/pkgs/development/compilers/llvm/17/libcxx/default.nix
+++ b/pkgs/development/compilers/llvm/17/libcxx/default.nix
@@ -1,71 +1,101 @@
 { lib, stdenv, llvm_meta
 , monorepoSrc, runCommand, fetchpatch
-, cmake, ninja, python3, fixDarwinDylibNames, version
-, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else libcxxabi
-, libcxxabi, libcxxrt, libunwind
+, cmake, lndir, ninja, python3, fixDarwinDylibNames, version
+, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else null
+, libcxxrt, libunwind
 , enableShared ? !stdenv.hostPlatform.isStatic
-
-# If headersOnly is true, the resulting package would only include the headers.
-# Use this to break the circular dependency between libcxx and libcxxabi.
-#
-# Some context:
-# https://reviews.llvm.org/rG1687f2bbe2e2aaa092f942d4a97d41fad43eedfb
-, headersOnly ? false
 }:
 
+# external cxxabi is not supported on Darwin as the build will not link libcxx
+# properly and not re-export the cxxabi symbols into libcxx
+# https://github.com/NixOS/nixpkgs/issues/166205
+# https://github.com/NixOS/nixpkgs/issues/269548
+assert cxxabi == null || !stdenv.hostPlatform.isDarwin;
 let
   basename = "libcxx";
-in
+  cxxabiName = "lib${if cxxabi == null then "cxxabi" else cxxabi.libName}";
+  runtimes = [ "libcxx" ] ++ lib.optional (cxxabi == null) "libcxxabi";
+
+  # Note: useLLVM is likely false for Darwin but true under pkgsLLVM
+  useLLVM = stdenv.hostPlatform.useLLVM or false;
+
+  cxxabiCMakeFlags = lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXXABI_ENABLE_THREADS=OFF"
+    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXXABI_ENABLE_SHARED=OFF"
+  ];
+
+  cxxCMakeFlags = [
+    "-DLIBCXX_CXX_ABI=${cxxabiName}"
+  ] ++ lib.optionals (cxxabi != null) [
+    "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${lib.getDev cxxabi}/include"
+  ] ++ lib.optionals (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) [
+    "-DLIBCXX_HAS_MUSL_LIBC=1"
+  ] ++ lib.optionals useLLVM [
+    "-DLIBCXX_USE_COMPILER_RT=ON"
+    # There's precedent for this in llvm-project/libcxx/cmake/caches.
+    # In a monorepo build you might do the following in the libcxxabi build:
+    #   -DLLVM_ENABLE_PROJECTS=libcxxabi;libunwinder
+    #   -DLIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY=On
+    # libcxx appears to require unwind and doesn't pull it in via other means.
+    "-DLIBCXX_ADDITIONAL_LIBRARIES=unwind"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXX_ENABLE_THREADS=OFF"
+    "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
+    "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXX_ENABLE_SHARED=OFF"
+  ];
+
+  cmakeFlags = [
+    "-DLLVM_ENABLE_RUNTIMES=${lib.concatStringsSep ";" runtimes}"
+  ] ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    # libcxxabi's CMake looks as though it treats -nostdlib++ as implying -nostdlib,
+    # but that does not appear to be the case for example when building
+    # pkgsLLVM.libcxxabi (which uses clangNoCompilerRtWithLibc).
+    "-DCMAKE_EXE_LINKER_FLAGS=-nostdlib"
+    "-DCMAKE_SHARED_LINKER_FLAGS=-nostdlib"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DCMAKE_C_COMPILER_WORKS=ON"
+    "-DCMAKE_CXX_COMPILER_WORKS=ON"
+    "-DUNIX=ON" # Required otherwise libc++ fails to detect the correct linker
+  ] ++ cxxCMakeFlags
+    ++ lib.optionals (cxxabi == null) cxxabiCMakeFlags;
 
-assert stdenv.isDarwin -> cxxabi.libName == "c++abi";
+in
 
 stdenv.mkDerivation rec {
-  pname = basename + lib.optionalString headersOnly "-headers";
-  inherit version;
+  pname = basename;
+  inherit version cmakeFlags;
 
-  src = runCommand "${pname}-src-${version}" {} ''
-    mkdir -p "$out"
-    cp -r ${monorepoSrc}/cmake "$out"
-    cp -r ${monorepoSrc}/${basename} "$out"
-    mkdir -p "$out/libcxxabi"
-    cp -r ${monorepoSrc}/libcxxabi/include "$out/libcxxabi"
+  src = runCommand "${pname}-src-${version}" {} (''
     mkdir -p "$out/llvm"
+    cp -r ${monorepoSrc}/cmake "$out"
+    cp -r ${monorepoSrc}/libcxx "$out"
     cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
     cp -r ${monorepoSrc}/llvm/utils "$out/llvm"
     cp -r ${monorepoSrc}/third-party "$out"
     cp -r ${monorepoSrc}/runtimes "$out"
-  '';
-
-  sourceRoot = "${src.name}/runtimes";
-
-  outputs = [ "out" ] ++ lib.optional (!headersOnly) "dev";
+  '' + lib.optionalString (cxxabi == null) ''
+    cp -r ${monorepoSrc}/libcxxabi "$out"
+  '');
 
-  prePatch = ''
-    cd ../${basename}
-    chmod -R u+w .
-  '';
+  outputs = [ "out" "dev" ];
 
-  patches = [
-    # fix for https://github.com/NixOS/nixpkgs/issues/269548
-    # https://github.com/llvm/llvm-project/pull/77218
-    (fetchpatch {
-      name = "darwin-system-libcxxabi-link-flags.patch";
-      url = "https://github.com/llvm/llvm-project/commit/c5b89b29ee6e3c444a355fd1cf733ce7ab2e316a.patch";
-      hash = "sha256-LNoPg1KCoP8RWxU/AzHR52f4Dww24I9BGQJedMhFxyQ=";
-      relative = "libcxx";
-    })
-  ] ++ lib.optionals (stdenv.isDarwin && lib.versionOlder stdenv.hostPlatform.darwinMinVersion "10.13") [
+  patches = lib.optionals (stdenv.isDarwin && lib.versionOlder stdenv.hostPlatform.darwinMinVersion "10.13") [
     # https://github.com/llvm/llvm-project/issues/64226
     (fetchpatch {
       name = "0042-mbstate_t-not-defined.patch";
       url = "https://github.com/macports/macports-ports/raw/acd8acb171f1658596ed1cf25da48d5b932e2d19/lang/llvm-17/files/0042-mbstate_t-not-defined.patch";
-      relative = "libcxx";
-      hash = "sha256-fVbX99W1gQrSaMFeBkzsJmNWNy0xVSw+oFvDe4AYXL0=";
+      hash = "sha256-jo+DYA6zuSv9OH3A0bYwY5TlkWprup4OKQ7rfK1WHBI=";
     })
   ];
 
   postPatch = ''
-    cd ../runtimes
+    cd runtimes
   '';
 
   preConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
@@ -73,50 +103,22 @@ stdenv.mkDerivation rec {
   '';
 
   nativeBuildInputs = [ cmake ninja python3 ]
-    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames;
-
-  buildInputs =
-    lib.optionals (!headersOnly) [ cxxabi ]
-    ++ lib.optionals (stdenv.hostPlatform.useLLVM or false && !stdenv.hostPlatform.isWasm) [ libunwind ];
-
-  cmakeFlags = let
-    # See: https://libcxx.llvm.org/BuildingLibcxx.html#cmdoption-arg-libcxx-cxx-abi-string
-    libcxx_cxx_abi_opt = {
-      "c++abi" = "system-libcxxabi";
-      "cxxrt" = "libcxxrt";
-    }.${cxxabi.libName} or (throw "unknown cxxabi: ${cxxabi.libName} (${cxxabi.pname})");
-  in [
-    "-DLLVM_ENABLE_RUNTIMES=libcxx"
-    "-DLIBCXX_CXX_ABI=${if headersOnly then "none" else libcxx_cxx_abi_opt}"
-  ] ++ lib.optional (!headersOnly && cxxabi.libName == "c++abi") "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${cxxabi.dev}/include/c++/v1"
-    ++ lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) "-DLIBCXX_HAS_MUSL_LIBC=1"
-    ++ lib.optionals (stdenv.hostPlatform.useLLVM or false) [
-      "-DLIBCXX_USE_COMPILER_RT=ON"
-      # There's precedent for this in llvm-project/libcxx/cmake/caches.
-      # In a monorepo build you might do the following in the libcxxabi build:
-      #   -DLLVM_ENABLE_PROJECTS=libcxxabi;libunwinder
-      #   -DLIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY=On
-      # libcxx appears to require unwind and doesn't pull it in via other means.
-      "-DLIBCXX_ADDITIONAL_LIBRARIES=unwind"
-    ] ++ lib.optionals stdenv.hostPlatform.isWasm [
-      "-DLIBCXX_ENABLE_THREADS=OFF"
-      "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
-      "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
-      "-DUNIX=ON" # Required otherwise libc++ fails to detect the correct linker
-    ] ++ lib.optional (!enableShared) "-DLIBCXX_ENABLE_SHARED=OFF"
-    # If we're only building the headers we don't actually *need* a functioning
-    # C/C++ compiler:
-    ++ lib.optionals (headersOnly) [
-      "-DCMAKE_C_COMPILER_WORKS=ON"
-      "-DCMAKE_CXX_COMPILER_WORKS=ON"
-    ];
-
-  ninjaFlags = lib.optional headersOnly "generate-cxx-headers";
-  installTargets = lib.optional headersOnly "install-cxx-headers";
+    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames
+    ++ lib.optional (cxxabi != null) lndir;
+
+  buildInputs = [ cxxabi ]
+    ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [ libunwind ];
+
+  # libc++.so is a linker script which expands to multiple libraries,
+  # libc++.so.1 and libc++abi.so or the external cxxabi. ld-wrapper doesn't
+  # support linker scripts so the external cxxabi needs to be symlinked in
+  postInstall = lib.optionalString (cxxabi != null) ''
+    lndir ${lib.getDev cxxabi}/include ''${!outputDev}/include/c++/v1
+    lndir ${lib.getLib cxxabi}/lib ''${!outputLib}/lib
+  '';
 
   passthru = {
     isLLVM = true;
-    inherit cxxabi;
   };
 
   meta = llvm_meta // {
diff --git a/pkgs/development/compilers/llvm/17/libcxxabi/default.nix b/pkgs/development/compilers/llvm/17/libcxxabi/default.nix
deleted file mode 100644
index 30ca99b20fd7a..0000000000000
--- a/pkgs/development/compilers/llvm/17/libcxxabi/default.nix
+++ /dev/null
@@ -1,114 +0,0 @@
-{ lib, stdenv, llvm_meta, cmake, ninja, python3
-, monorepoSrc, runCommand, fetchpatch
-, cxx-headers, libunwind, version
-, enableShared ? !stdenv.hostPlatform.isStatic
-}:
-
-stdenv.mkDerivation rec {
-  pname = "libcxxabi";
-  inherit version;
-
-  src = runCommand "${pname}-src-${version}" {} ''
-    mkdir -p "$out"
-    cp -r ${monorepoSrc}/cmake "$out"
-    cp -r ${monorepoSrc}/${pname} "$out"
-    mkdir -p "$out/libcxx/src"
-    cp -r ${monorepoSrc}/libcxx/cmake "$out/libcxx"
-    cp -r ${monorepoSrc}/libcxx/include "$out/libcxx"
-    cp -r ${monorepoSrc}/libcxx/src/include "$out/libcxx/src"
-    mkdir -p "$out/llvm"
-    cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
-    cp -r ${monorepoSrc}/llvm/utils "$out/llvm"
-    cp -r ${monorepoSrc}/runtimes "$out"
-  '';
-
-  sourceRoot = "${src.name}/runtimes";
-
-  outputs = [ "out" "dev" ];
-
-  postUnpack = lib.optionalString stdenv.isDarwin ''
-    export TRIPLE=x86_64-apple-darwin
-  '';
-
-  prePatch = ''
-    cd ../${pname}
-    chmod -R u+w .
-  '';
-
-  patches = [
-    ./gnu-install-dirs.patch
-
-    # https://reviews.llvm.org/D132298, Allow building libcxxabi alone
-    (fetchpatch {
-      url = "https://github.com/llvm/llvm-project/commit/e6a0800532bb409f6d1c62f3698bdd6994a877dc.patch";
-      sha256 = "1xyjd56m4pfwq8p3xh6i8lhkk9kq15jaml7qbhxdf87z4jjkk63a";
-      stripLen = 1;
-    })
-  ];
-
-  postPatch = ''
-    cd ../runtimes
-  '';
-
-  nativeBuildInputs = [ cmake ninja python3 ];
-  buildInputs = lib.optional (!stdenv.isDarwin && !stdenv.hostPlatform.isWasm) libunwind;
-
-  cmakeFlags = [
-    "-DLLVM_ENABLE_RUNTIMES=libcxxabi"
-    "-DLIBCXXABI_LIBCXX_INCLUDES=${cxx-headers}/include/c++/v1"
-
-    # `libcxxabi`'s build does not need a toolchain with a c++ stdlib attached
-    # (we specify the headers it should use explicitly above).
-    #
-    # CMake however checks for this anyways; this flag tells it not to. See:
-    # https://github.com/llvm/llvm-project/blob/4bd3f3759259548e159aeba5c76efb9a0864e6fa/llvm/runtimes/CMakeLists.txt#L243
-    "-DCMAKE_CXX_COMPILER_WORKS=ON"
-  ] ++ lib.optionals (stdenv.hostPlatform.useLLVM or false && !stdenv.hostPlatform.isWasm) [
-    "-DLLVM_ENABLE_LIBCXX=ON"
-    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
-    # libcxxabi's CMake looks as though it treats -nostdlib++ as implying -nostdlib,
-    # but that does not appear to be the case for example when building
-    # pkgsLLVM.libcxxabi (which uses clangNoCompilerRtWithLibc).
-    "-DCMAKE_EXE_LINKER_FLAGS=-nostdlib"
-    "-DCMAKE_SHARED_LINKER_FLAGS=-nostdlib"
-  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
-    "-DCMAKE_C_COMPILER_WORKS=ON"
-    "-DCMAKE_CXX_COMPILER_WORKS=ON"
-    "-DLIBCXXABI_ENABLE_THREADS=OFF"
-    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
-    "-DUNIX=ON"
-  ] ++ lib.optionals (!enableShared) [
-    "-DLIBCXXABI_ENABLE_SHARED=OFF"
-  ];
-
-  preInstall = lib.optionalString stdenv.isDarwin ''
-    for file in lib/*.dylib; do
-      # this should be done in CMake, but having trouble figuring out
-      # the magic combination of necessary CMake variables
-      # if you fancy a try, take a look at
-      # https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling
-      install_name_tool -id $out/$file $file
-    done
-  '';
-
-  postInstall = ''
-    mkdir -p "$dev/include"
-    install -m 644 ../../${pname}/include/${if stdenv.isDarwin then "*" else "cxxabi.h"} "$dev/include"
-  '';
-
-  passthru = {
-    libName = "c++abi";
-  };
-
-  meta = llvm_meta // {
-    homepage = "https://libcxxabi.llvm.org/";
-    description = "Provides C++ standard library support";
-    longDescription = ''
-      libc++abi is a new implementation of low level support for a standard C++ library.
-    '';
-    # "All of the code in libc++abi is dual licensed under the MIT license and
-    # the UIUC License (a BSD-like license)":
-    license = with lib.licenses; [ mit ncsa ];
-    maintainers = llvm_meta.maintainers ++ [ lib.maintainers.vlstill ];
-  };
-}
diff --git a/pkgs/development/compilers/llvm/17/libcxxabi/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/17/libcxxabi/gnu-install-dirs.patch
deleted file mode 100644
index 51382fcefed27..0000000000000
--- a/pkgs/development/compilers/llvm/17/libcxxabi/gnu-install-dirs.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt
-index f380fe6b6b92..a9656258c38e 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -188,7 +188,7 @@ set(LIBCXXABI_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE STRING
- if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR})
-   set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE STRING
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
-   if(LIBCXX_LIBDIR_SUBDIR)
-     string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
-@@ -202,7 +202,7 @@ else()
-     set(LIBCXXABI_HEADER_DIR ${CMAKE_BINARY_DIR})
-     set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
-   endif()
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE STRING
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
- endif()
- 
diff --git a/pkgs/development/compilers/llvm/git/compiler-rt/default.nix b/pkgs/development/compilers/llvm/git/compiler-rt/default.nix
index 7b44a872adc4a..51f4e95ef2b5a 100644
--- a/pkgs/development/compilers/llvm/git/compiler-rt/default.nix
+++ b/pkgs/development/compilers/llvm/git/compiler-rt/default.nix
@@ -1,6 +1,6 @@
 { lib, stdenv, llvm_meta, version
 , monorepoSrc, runCommand
-, cmake, ninja, python3, xcbuild, libllvm, linuxHeaders, libcxxabi, libxcrypt
+, cmake, ninja, python3, xcbuild, libllvm, linuxHeaders, libxcrypt
 , doFakeLibgcc ? stdenv.hostPlatform.isFreeBSD
 }:
 
@@ -31,8 +31,7 @@ stdenv.mkDerivation {
   nativeBuildInputs = [ cmake ninja python3 libllvm.dev ]
     ++ lib.optional stdenv.isDarwin xcbuild.xcrun;
   buildInputs =
-    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders
-    ++ lib.optional stdenv.hostPlatform.isDarwin libcxxabi;
+    lib.optional (stdenv.hostPlatform.isLinux && stdenv.hostPlatform.isRiscV) linuxHeaders;
 
   env.NIX_CFLAGS_COMPILE = toString ([
     "-DSCUDO_DEFAULT_OPTIONS=DeleteSizeMismatch=0:DeallocationTypeMismatch=0"
diff --git a/pkgs/development/compilers/llvm/git/default.nix b/pkgs/development/compilers/llvm/git/default.nix
index 1efaa0402fc71..7610dd8602830 100644
--- a/pkgs/development/compilers/llvm/git/default.nix
+++ b/pkgs/development/compilers/llvm/git/default.nix
@@ -134,7 +134,6 @@ in let
       cc = tools.clang-unwrapped;
       libcxx = targetLlvmLibraries.libcxx;
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ];
       extraBuildCommands = mkExtraBuildCommands cc;
@@ -199,7 +198,6 @@ in let
       libcxx = targetLlvmLibraries.libcxx;
       bintools = bintools';
       extraPackages = [
-        libcxx.cxxabi
         targetLlvmLibraries.compiler-rt
       ] ++ lib.optionals (!stdenv.targetPlatform.isWasm) [
         targetLlvmLibraries.libunwind
@@ -303,45 +301,7 @@ in let
 
     libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang;
 
-    libcxxabi = let
-      # CMake will "require" a compiler capable of compiling C++ programs
-      # cxx-header's build does not actually use one so it doesn't really matter
-      # what stdenv we use here, as long as CMake is happy.
-      cxx-headers = callPackage ./libcxx {
-        inherit llvm_meta;
-        # Note that if we use the regular stdenv here we'll get cycle errors
-        # when attempting to use this compiler in the stdenv.
-        #
-        # The final stdenv pulls `cxx-headers` from the package set where
-        # hostPlatform *is* the target platform which means that `stdenv` at
-        # that point attempts to use this toolchain.
-        #
-        # So, we use `stdenv_` (the stdenv containing `clang` from this package
-        # set, defined below) to sidestep this issue.
-        #
-        # Because we only use `cxx-headers` in `libcxxabi` (which depends on the
-        # clang stdenv _anyways_), this is okay.
-        stdenv = stdenv_;
-        headersOnly = true;
-      };
-
-      # `libcxxabi` *doesn't* need a compiler with a working C++ stdlib but it
-      # *does* need a relatively modern C++ compiler (see:
-      # https://releases.llvm.org/15.0.0/projects/libcxx/docs/index.html#platform-and-compiler-support).
-      #
-      # So, we use the clang from this LLVM package set, like libc++
-      # "boostrapping builds" do:
-      # https://releases.llvm.org/15.0.0/projects/libcxx/docs/BuildingLibcxx.html#bootstrapping-build
-      #
-      # We cannot use `clangNoLibcxx` because that contains `compiler-rt` which,
-      # on macOS, depends on `libcxxabi`, thus forming a cycle.
-      stdenv_ = overrideCC stdenv buildLlvmTools.clangNoCompilerRtWithLibc;
-    in callPackage ./libcxxabi {
-      stdenv = stdenv_;
-      inherit llvm_meta cxx-headers;
-    };
-
-    # Like `libcxxabi` above, `libcxx` requires a fairly modern C++ compiler,
+    # `libcxx` requires a fairly modern C++ compiler,
     # so: we use the clang from this LLVM package set instead of the regular
     # stdenv's compiler.
     libcxx = callPackage ./libcxx {
diff --git a/pkgs/development/compilers/llvm/git/libcxx/0001-darwin-10.12-mbstate_t-fix.patch b/pkgs/development/compilers/llvm/git/libcxx/0001-darwin-10.12-mbstate_t-fix.patch
index 0a2e8db07391c..29942f8ed03d6 100644
--- a/pkgs/development/compilers/llvm/git/libcxx/0001-darwin-10.12-mbstate_t-fix.patch
+++ b/pkgs/development/compilers/llvm/git/libcxx/0001-darwin-10.12-mbstate_t-fix.patch
@@ -9,13 +9,13 @@ removes space from
 https://github.com/macports/macports-ports/raw/acd8acb171f1658596ed1cf25da48d5b932e2d19/lang/llvm-17/files/0042-mbstate_t-not-defined.patch
 so it applies cleanly
 ---
- include/__mbstate_t.h | 3 +++
+ libcxx/include/__mbstate_t.h | 3 +++
  1 file changed, 3 insertions(+)
 
-diff --git a/include/__mbstate_t.h b/include/__mbstate_t.h
+diff --git a/libcxx/include/__mbstate_t.h b/libcxx/include/__mbstate_t.h
 index bfa6d61..5f51112 100644
---- a/include/__mbstate_t.h
-+++ b/include/__mbstate_t.h
+--- a/libcxx/include/__mbstate_t.h
++++ b/libcxx/include/__mbstate_t.h
 @@ -42,6 +42,9 @@
  #elif __has_include(<bits/types/mbstate_t.h>)
  #  include <bits/types/mbstate_t.h> // works on most Unixes
diff --git a/pkgs/development/compilers/llvm/git/libcxx/default.nix b/pkgs/development/compilers/llvm/git/libcxx/default.nix
index 11f4c6fe5fd10..a865c27f4845c 100644
--- a/pkgs/development/compilers/llvm/git/libcxx/default.nix
+++ b/pkgs/development/compilers/llvm/git/libcxx/default.nix
@@ -1,57 +1,107 @@
 { lib, stdenv, llvm_meta
 , monorepoSrc, runCommand, fetchpatch
-, cmake, ninja, python3, fixDarwinDylibNames, version
-, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else libcxxabi
-, libcxxabi, libcxxrt, libunwind
+, cmake, lndir, ninja, python3, fixDarwinDylibNames, version
+, cxxabi ? if stdenv.hostPlatform.isFreeBSD then libcxxrt else null
+, libcxxrt, libunwind
 , enableShared ? !stdenv.hostPlatform.isStatic
-
-# If headersOnly is true, the resulting package would only include the headers.
-# Use this to break the circular dependency between libcxx and libcxxabi.
-#
-# Some context:
-# https://reviews.llvm.org/rG1687f2bbe2e2aaa092f942d4a97d41fad43eedfb
-, headersOnly ? false
 }:
 
+# external cxxabi is not supported on Darwin as the build will not link libcxx
+# properly and not re-export the cxxabi symbols into libcxx
+# https://github.com/NixOS/nixpkgs/issues/166205
+# https://github.com/NixOS/nixpkgs/issues/269548
+assert cxxabi == null || !stdenv.hostPlatform.isDarwin;
 let
   basename = "libcxx";
-in
+  cxxabiName = "lib${if cxxabi == null then "cxxabi" else cxxabi.libName}";
+  runtimes = [ "libcxx" ] ++ lib.optional (cxxabi == null) "libcxxabi";
+
+  # Note: useLLVM is likely false for Darwin but true under pkgsLLVM
+  useLLVM = stdenv.hostPlatform.useLLVM or false;
+
+  cxxabiCMakeFlags = lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [
+    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
+  ] ++ lib.optionals (lib.versionAtLeast version "18" && !(useLLVM && !stdenv.hostPlatform.isWasm)) [
+    "-DLIBCXXABI_USE_LLVM_UNWINDER=OFF"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXXABI_ENABLE_THREADS=OFF"
+    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXXABI_ENABLE_SHARED=OFF"
+  ];
+
+  cxxCMakeFlags = [
+    "-DLIBCXX_CXX_ABI=${cxxabiName}"
+  ] ++ lib.optionals (cxxabi != null) [
+    "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${lib.getDev cxxabi}/include"
+  ] ++ lib.optionals (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) [
+    "-DLIBCXX_HAS_MUSL_LIBC=1"
+  ] ++ lib.optionals (lib.versionAtLeast version "18" && !useLLVM && stdenv.hostPlatform.libc == "glibc" && !stdenv.hostPlatform.isStatic) [
+    "-DLIBCXX_ADDITIONAL_LIBRARIES=gcc_s"
+  ] ++ lib.optionals useLLVM [
+    "-DLIBCXX_USE_COMPILER_RT=ON"
+    # There's precedent for this in llvm-project/libcxx/cmake/caches.
+    # In a monorepo build you might do the following in the libcxxabi build:
+    #   -DLLVM_ENABLE_PROJECTS=libcxxabi;libunwinder
+    #   -DLIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY=On
+    # libcxx appears to require unwind and doesn't pull it in via other means.
+    "-DLIBCXX_ADDITIONAL_LIBRARIES=unwind"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DLIBCXX_ENABLE_THREADS=OFF"
+    "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
+    "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
+  ] ++ lib.optionals (!enableShared) [
+    "-DLIBCXX_ENABLE_SHARED=OFF"
+  ];
 
-assert stdenv.isDarwin -> cxxabi.libName == "c++abi";
+  cmakeFlags = [
+    "-DLLVM_ENABLE_RUNTIMES=${lib.concatStringsSep ";" runtimes}"
+  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
+    "-DCMAKE_C_COMPILER_WORKS=ON"
+    "-DCMAKE_CXX_COMPILER_WORKS=ON"
+    "-DUNIX=ON" # Required otherwise libc++ fails to detect the correct linker
+  ] ++ cxxCMakeFlags
+    ++ lib.optionals (cxxabi == null) cxxabiCMakeFlags;
+
+in
 
 stdenv.mkDerivation rec {
-  pname = basename + lib.optionalString headersOnly "-headers";
-  inherit version;
+  pname = basename;
+  inherit version cmakeFlags;
 
-  src = runCommand "${pname}-src-${version}" {} ''
-    mkdir -p "$out"
-    cp -r ${monorepoSrc}/cmake "$out"
-    cp -r ${monorepoSrc}/${basename} "$out"
-    mkdir -p "$out/libcxxabi"
-    cp -r ${monorepoSrc}/libcxxabi/include "$out/libcxxabi"
+  src = runCommand "${pname}-src-${version}" {} (''
     mkdir -p "$out/llvm"
+    cp -r ${monorepoSrc}/cmake "$out"
+    cp -r ${monorepoSrc}/libcxx "$out"
     cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
     cp -r ${monorepoSrc}/llvm/utils "$out/llvm"
     cp -r ${monorepoSrc}/third-party "$out"
     cp -r ${monorepoSrc}/runtimes "$out"
-  '';
-
-  sourceRoot = "${src.name}/runtimes";
+  '' + lib.optionalString (cxxabi == null) ''
+    cp -r ${monorepoSrc}/libcxxabi "$out"
+  '');
 
-  outputs = [ "out" ] ++ lib.optional (!headersOnly) "dev";
-
-  prePatch = ''
-    cd ../${basename}
-    chmod -R u+w .
-  '';
+  outputs = [ "out" "dev" ];
 
   patches = lib.optionals (stdenv.isDarwin && lib.versionOlder stdenv.hostPlatform.darwinMinVersion "10.13") [
     # https://github.com/llvm/llvm-project/issues/64226
     ./0001-darwin-10.12-mbstate_t-fix.patch
+  ] ++ lib.optionals (cxxabi == null && lib.versionAtLeast version "18") [
+    # Allow building libcxxabi alone when using LLVM unwinder
+    (fetchpatch {
+      url = "https://github.com/llvm/llvm-project/commit/77610dd10454e87bb387040d2b51100a17ac5755.patch";
+      revert = true;
+      hash = "sha256-jFbC3vBY3nKfjknJ7UzaPyoy0iSYdD3+jUmOFeOaVcA=";
+    })
+    (fetchpatch {
+      url = "https://github.com/llvm/llvm-project/commit/48e5b5ea92674ded69b998cf35724d9012c0f57d.patch";
+      revert = true;
+      hash = "sha256-WN63L4T3GxVozPZb6kx21AgNe4rwwSUOeeryIGsvQYY=";
+    })
   ];
 
   postPatch = ''
-    cd ../runtimes
+    cd runtimes
   '';
 
   preConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
@@ -59,52 +109,22 @@ stdenv.mkDerivation rec {
   '';
 
   nativeBuildInputs = [ cmake ninja python3 ]
-    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames;
-
-  buildInputs =
-    lib.optionals (!headersOnly) [ cxxabi ]
-    ++ lib.optionals (stdenv.hostPlatform.useLLVM or false && !stdenv.hostPlatform.isWasm) [ libunwind ];
-
-  cmakeFlags = let
-    # See: https://libcxx.llvm.org/BuildingLibcxx.html#cmdoption-arg-libcxx-cxx-abi-string
-    libcxx_cxx_abi_opt = {
-      "c++abi" = "system-libcxxabi";
-      "cxxrt" = "libcxxrt";
-    }.${cxxabi.libName} or (throw "unknown cxxabi: ${cxxabi.libName} (${cxxabi.pname})");
-  in [
-    "-DLLVM_ENABLE_RUNTIMES=libcxx"
-    "-DLIBCXX_CXX_ABI=${if headersOnly then "none" else libcxx_cxx_abi_opt}"
-  ] ++ lib.optional (!headersOnly && cxxabi.libName == "c++abi") "-DLIBCXX_CXX_ABI_INCLUDE_PATHS=${cxxabi.dev}/include/c++/v1"
-    ++ lib.optional (stdenv.hostPlatform.isMusl || stdenv.hostPlatform.isWasi) "-DLIBCXX_HAS_MUSL_LIBC=1"
-    ++ lib.optionals (lib.versionAtLeast version "18" && !(stdenv.hostPlatform.useLLVM or false) && stdenv.hostPlatform.libc == "glibc" && !stdenv.hostPlatform.isStatic) [
-    "-DLIBCXX_ADDITIONAL_LIBRARIES=gcc_s"
-  ] ++ lib.optionals (stdenv.hostPlatform.useLLVM or false) [
-      "-DLIBCXX_USE_COMPILER_RT=ON"
-      # There's precedent for this in llvm-project/libcxx/cmake/caches.
-      # In a monorepo build you might do the following in the libcxxabi build:
-      #   -DLLVM_ENABLE_PROJECTS=libcxxabi;libunwinder
-      #   -DLIBCXXABI_STATICALLY_LINK_UNWINDER_IN_STATIC_LIBRARY=On
-      # libcxx appears to require unwind and doesn't pull it in via other means.
-      "-DLIBCXX_ADDITIONAL_LIBRARIES=unwind"
-    ] ++ lib.optionals stdenv.hostPlatform.isWasm [
-      "-DLIBCXX_ENABLE_THREADS=OFF"
-      "-DLIBCXX_ENABLE_FILESYSTEM=OFF"
-      "-DLIBCXX_ENABLE_EXCEPTIONS=OFF"
-      "-DUNIX=ON" # Required otherwise libc++ fails to detect the correct linker
-    ] ++ lib.optional (!enableShared) "-DLIBCXX_ENABLE_SHARED=OFF"
-    # If we're only building the headers we don't actually *need* a functioning
-    # C/C++ compiler:
-    ++ lib.optionals (headersOnly) [
-      "-DCMAKE_C_COMPILER_WORKS=ON"
-      "-DCMAKE_CXX_COMPILER_WORKS=ON"
-    ];
-
-  ninjaFlags = lib.optional headersOnly "generate-cxx-headers";
-  installTargets = lib.optional headersOnly "install-cxx-headers";
+    ++ lib.optional stdenv.isDarwin fixDarwinDylibNames
+    ++ lib.optional (cxxabi != null) lndir;
+
+  buildInputs = [ cxxabi ]
+    ++ lib.optionals (useLLVM && !stdenv.hostPlatform.isWasm) [ libunwind ];
+
+  # libc++.so is a linker script which expands to multiple libraries,
+  # libc++.so.1 and libc++abi.so or the external cxxabi. ld-wrapper doesn't
+  # support linker scripts so the external cxxabi needs to be symlinked in
+  postInstall = lib.optionalString (cxxabi != null) ''
+    lndir ${lib.getDev cxxabi}/include ''${!outputDev}/include/c++/v1
+    lndir ${lib.getLib cxxabi}/lib ''${!outputLib}/lib
+  '';
 
   passthru = {
     isLLVM = true;
-    inherit cxxabi;
   };
 
   meta = llvm_meta // {
diff --git a/pkgs/development/compilers/llvm/git/libcxxabi/default.nix b/pkgs/development/compilers/llvm/git/libcxxabi/default.nix
deleted file mode 100644
index 8e19796543250..0000000000000
--- a/pkgs/development/compilers/llvm/git/libcxxabi/default.nix
+++ /dev/null
@@ -1,130 +0,0 @@
-{ lib, stdenv, llvm_meta, cmake, ninja, python3
-, monorepoSrc, runCommand, fetchpatch
-, cxx-headers, libunwind, version
-, enableShared ? !stdenv.hostPlatform.isStatic
-}:
-
-stdenv.mkDerivation rec {
-  pname = "libcxxabi";
-  inherit version;
-
-  src = runCommand "${pname}-src-${version}" {} ''
-    mkdir -p "$out"
-    cp -r ${monorepoSrc}/cmake "$out"
-    cp -r ${monorepoSrc}/${pname} "$out"
-    mkdir -p "$out/libcxx/src"
-    cp -r ${monorepoSrc}/libcxx/cmake "$out/libcxx"
-    cp -r ${monorepoSrc}/libcxx/include "$out/libcxx"
-    cp -r ${monorepoSrc}/libcxx/src/include "$out/libcxx/src"
-    mkdir -p "$out/llvm"
-    cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
-    cp -r ${monorepoSrc}/llvm/utils "$out/llvm"
-    cp -r ${monorepoSrc}/runtimes "$out"
-  '';
-
-  sourceRoot = "${src.name}/runtimes";
-
-  outputs = [ "out" "dev" ];
-
-  postUnpack = lib.optionalString stdenv.isDarwin ''
-    export TRIPLE=x86_64-apple-darwin
-  '';
-
-  prePatch = ''
-    cd ../${pname}
-    chmod -R u+w .
-  '';
-
-  patches = [
-    ./gnu-install-dirs.patch
-
-    # https://reviews.llvm.org/D132298, Allow building libcxxabi alone
-    (fetchpatch {
-      url = "https://github.com/llvm/llvm-project/commit/e6a0800532bb409f6d1c62f3698bdd6994a877dc.patch";
-      sha256 = "1xyjd56m4pfwq8p3xh6i8lhkk9kq15jaml7qbhxdf87z4jjkk63a";
-      stripLen = 1;
-    })
-  ] ++ lib.optionals (lib.versionAtLeast version "18") [
-    # Allow building libcxxabi alone when using LLVM unwinder
-    (fetchpatch {
-      url = "https://github.com/llvm/llvm-project/commit/77610dd10454e87bb387040d2b51100a17ac5755.patch";
-      stripLen = 1;
-      revert = true;
-      hash = "sha256-Jogx/cvTJ6fdyprTD1QzMIeRWcBlZZMWE/y9joOtVH0=";
-    })
-    (fetchpatch {
-      url = "https://github.com/llvm/llvm-project/commit/48e5b5ea92674ded69b998cf35724d9012c0f57d.patch";
-      stripLen = 1;
-      revert = true;
-      hash = "sha256-7VeBFjG7CnEMWn0hpBvyNOyhRfz50PnD3zyQNDhNChk=";
-    })
-  ];
-
-  postPatch = ''
-    cd ../runtimes
-  '';
-
-  nativeBuildInputs = [ cmake ninja python3 ];
-  buildInputs = lib.optional (!stdenv.isDarwin && !stdenv.hostPlatform.isWasm) libunwind;
-
-  cmakeFlags = [
-    "-DLLVM_ENABLE_RUNTIMES=libcxxabi"
-    "-DLIBCXXABI_LIBCXX_INCLUDES=${cxx-headers}/include/c++/v1"
-
-    # `libcxxabi`'s build does not need a toolchain with a c++ stdlib attached
-    # (we specify the headers it should use explicitly above).
-    #
-    # CMake however checks for this anyways; this flag tells it not to. See:
-    # https://github.com/llvm/llvm-project/blob/4bd3f3759259548e159aeba5c76efb9a0864e6fa/llvm/runtimes/CMakeLists.txt#L243
-    "-DCMAKE_CXX_COMPILER_WORKS=ON"
-  ] ++ lib.optionals (lib.versionAtLeast version "18" && !(stdenv.hostPlatform.useLLVM or false && !stdenv.hostPlatform.isWasm)) [
-    "-DLIBCXXABI_USE_LLVM_UNWINDER=OFF"
-  ] ++ lib.optionals (stdenv.hostPlatform.useLLVM or false && !stdenv.hostPlatform.isWasm) [
-    "-DLLVM_ENABLE_LIBCXX=ON"
-    "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"
-    # libcxxabi's CMake looks as though it treats -nostdlib++ as implying -nostdlib,
-    # but that does not appear to be the case for example when building
-    # pkgsLLVM.libcxxabi (which uses clangNoCompilerRtWithLibc).
-    "-DCMAKE_EXE_LINKER_FLAGS=-nostdlib"
-    "-DCMAKE_SHARED_LINKER_FLAGS=-nostdlib"
-  ] ++ lib.optionals stdenv.hostPlatform.isWasm [
-    "-DCMAKE_C_COMPILER_WORKS=ON"
-    "-DCMAKE_CXX_COMPILER_WORKS=ON"
-    "-DLIBCXXABI_ENABLE_THREADS=OFF"
-    "-DLIBCXXABI_ENABLE_EXCEPTIONS=OFF"
-    "-DUNIX=ON"
-  ] ++ lib.optionals (!enableShared) [
-    "-DLIBCXXABI_ENABLE_SHARED=OFF"
-  ];
-
-  preInstall = lib.optionalString stdenv.isDarwin ''
-    for file in lib/*.dylib; do
-      # this should be done in CMake, but having trouble figuring out
-      # the magic combination of necessary CMake variables
-      # if you fancy a try, take a look at
-      # https://gitlab.kitware.com/cmake/community/-/wikis/doc/cmake/RPATH-handling
-      install_name_tool -id $out/$file $file
-    done
-  '';
-
-  postInstall = ''
-    mkdir -p "$dev/include"
-    install -m 644 ../../${pname}/include/${if stdenv.isDarwin then "*" else "cxxabi.h"} "$dev/include"
-  '';
-
-  passthru = {
-    libName = "c++abi";
-  };
-
-  meta = llvm_meta // {
-    homepage = "https://libcxxabi.llvm.org/";
-    description = "Provides C++ standard library support";
-    longDescription = ''
-      libc++abi is a new implementation of low level support for a standard C++ library.
-    '';
-    # "All of the code in libc++abi is dual licensed under the MIT license and
-    # the UIUC License (a BSD-like license)":
-    license = with lib.licenses; [ mit ncsa ];
-    maintainers = llvm_meta.maintainers ++ [ lib.maintainers.vlstill ];
-  };
-}
diff --git a/pkgs/development/compilers/llvm/git/libcxxabi/gnu-install-dirs.patch b/pkgs/development/compilers/llvm/git/libcxxabi/gnu-install-dirs.patch
deleted file mode 100644
index 51382fcefed27..0000000000000
--- a/pkgs/development/compilers/llvm/git/libcxxabi/gnu-install-dirs.patch
+++ /dev/null
@@ -1,22 +0,0 @@
-diff --git a/libcxxabi/CMakeLists.txt b/libcxxabi/CMakeLists.txt
-index f380fe6b6b92..a9656258c38e 100644
---- a/CMakeLists.txt
-+++ b/CMakeLists.txt
-@@ -188,7 +188,7 @@ set(LIBCXXABI_INSTALL_RUNTIME_DIR "${CMAKE_INSTALL_BINDIR}" CACHE STRING
- if(LLVM_ENABLE_PER_TARGET_RUNTIME_DIR AND NOT APPLE)
-   set(LIBCXXABI_HEADER_DIR ${LLVM_BINARY_DIR})
-   set(LIBCXXABI_LIBRARY_DIR ${LLVM_LIBRARY_OUTPUT_INTDIR}/${LLVM_DEFAULT_TARGET_TRIPLE})
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE STRING
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LLVM_LIBDIR_SUFFIX}/${LLVM_DEFAULT_TARGET_TRIPLE} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
-   if(LIBCXX_LIBDIR_SUBDIR)
-     string(APPEND LIBCXXABI_LIBRARY_DIR /${LIBCXXABI_LIBDIR_SUBDIR})
-@@ -202,7 +202,7 @@ else()
-     set(LIBCXXABI_HEADER_DIR ${CMAKE_BINARY_DIR})
-     set(LIBCXXABI_LIBRARY_DIR ${CMAKE_BINARY_DIR}/lib${LIBCXXABI_LIBDIR_SUFFIX})
-   endif()
--  set(LIBCXXABI_INSTALL_LIBRARY_DIR lib${LIBCXXABI_LIBDIR_SUFFIX} CACHE STRING
-+  set(LIBCXXABI_INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}${LIBCXXABI_LIBDIR_SUFFIX} CACHE PATH
-       "Path where built libc++abi libraries should be installed.")
- endif()
- 
diff --git a/pkgs/development/compilers/open-watcom/v2.nix b/pkgs/development/compilers/open-watcom/v2.nix
index 80ee2ee5e45d8..37503496c9176 100644
--- a/pkgs/development/compilers/open-watcom/v2.nix
+++ b/pkgs/development/compilers/open-watcom/v2.nix
@@ -47,9 +47,6 @@ stdenv.mkDerivation rec {
     ghostscript
   ];
 
-  # Work around https://github.com/NixOS/nixpkgs/issues/166205
-  env.NIX_LDFLAGS = lib.optionalString (stdenv.cc.isClang && stdenv.cc.libcxx != null) "-l${stdenv.cc.libcxx.cxxabi.libName}";
-
   configurePhase = ''
     runHook preConfigure
 
diff --git a/pkgs/development/compilers/swift/compiler/default.nix b/pkgs/development/compilers/swift/compiler/default.nix
index 76c2da0a656af..cef1358aed735 100644
--- a/pkgs/development/compilers/swift/compiler/default.nix
+++ b/pkgs/development/compilers/swift/compiler/default.nix
@@ -284,7 +284,6 @@ in stdenv.mkDerivation {
     patch -p1 -d swift -i ${./patches/swift-linux-fix-libc-paths.patch}
     patch -p1 -d swift -i ${./patches/swift-linux-fix-linking.patch}
     patch -p1 -d swift -i ${./patches/swift-darwin-libcxx-flags.patch}
-    patch -p1 -d swift -i ${./patches/swift-darwin-link-cxxabi.patch}
     patch -p1 -d swift -i ${substituteAll {
       src = ./patches/swift-darwin-plistbuddy-workaround.patch;
       inherit swiftArch;
diff --git a/pkgs/development/compilers/swift/compiler/patches/swift-darwin-link-cxxabi.patch b/pkgs/development/compilers/swift/compiler/patches/swift-darwin-link-cxxabi.patch
deleted file mode 100644
index dad9b3285dc12..0000000000000
--- a/pkgs/development/compilers/swift/compiler/patches/swift-darwin-link-cxxabi.patch
+++ /dev/null
@@ -1,14 +0,0 @@
-This patches the stdlib backdeploy static lib to have its users link c++abi.
-Without this, later steps that try to link this fail looking for global
-new/delete operators (__Znwm/__ZdlPv).
-
---- a/stdlib/toolchain/Compatibility56/Overrides.cpp
-+++ b/stdlib/toolchain/Compatibility56/Overrides.cpp
-@@ -23,6 +23,7 @@
- using namespace swift;
- 
- __asm__ (".linker_option \"-lc++\"");
-+__asm__ (".linker_option \"-lc++abi\"");
- 
- #define OVERRIDE(name, ret, attrs, ccAttrs, namespace, typedArgs, namedArgs) \
-   Override_ ## name name;
diff --git a/pkgs/development/compilers/swift/default.nix b/pkgs/development/compilers/swift/default.nix
index afb8ce39dcced..2a56a03766b95 100644
--- a/pkgs/development/compilers/swift/default.nix
+++ b/pkgs/development/compilers/swift/default.nix
@@ -35,14 +35,6 @@ let
           # that can happen when a Swift application dynamically links different versions
           # of libc++ and libc++abi than libraries it links are using.
           inherit (llvmPackages) libcxx;
-          extraPackages = [
-            llvmPackages.libcxxabi
-            # Use the compiler-rt associated with clang, but use the libc++abi from the stdenv
-            # to avoid linking against two different versions (for the same reasons as above).
-            (swiftLlvmPackages.compiler-rt.override {
-              inherit (llvmPackages) libcxxabi;
-            })
-          ];
         }
       else
         swiftLlvmPackages.clang;