about summary refs log tree commit diff
path: root/pkgs/development/compilers/llvm
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/development/compilers/llvm')
-rw-r--r--pkgs/development/compilers/llvm/10/clang/default.nix1
-rw-r--r--pkgs/development/compilers/llvm/10/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/10/llvm/default.nix78
-rw-r--r--pkgs/development/compilers/llvm/10/llvm/outputs.patch26
-rw-r--r--pkgs/development/compilers/llvm/11/clang/default.nix2
-rw-r--r--pkgs/development/compilers/llvm/11/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/11/llvm/default.nix88
-rw-r--r--pkgs/development/compilers/llvm/11/llvm/outputs.patch26
-rw-r--r--pkgs/development/compilers/llvm/12/clang/default.nix2
-rw-r--r--pkgs/development/compilers/llvm/12/compiler-rt/default.nix1
-rw-r--r--pkgs/development/compilers/llvm/12/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/12/libcxx/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/12/llvm/default.nix90
-rw-r--r--pkgs/development/compilers/llvm/12/llvm/fix-llvm-issue-49955.patch13
-rw-r--r--pkgs/development/compilers/llvm/12/llvm/outputs.patch26
-rw-r--r--pkgs/development/compilers/llvm/13/clang/default.nix2
-rw-r--r--pkgs/development/compilers/llvm/13/compiler-rt/default.nix2
-rw-r--r--pkgs/development/compilers/llvm/13/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/13/libcxx/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/13/llvm/default.nix60
-rw-r--r--pkgs/development/compilers/llvm/13/llvm/outputs.patch26
-rw-r--r--pkgs/development/compilers/llvm/5/compiler-rt/compiler-rt-5-cstddef.patch10
-rw-r--r--pkgs/development/compilers/llvm/5/compiler-rt/default.nix1
-rw-r--r--pkgs/development/compilers/llvm/5/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/5/llvm/default.nix76
-rw-r--r--pkgs/development/compilers/llvm/5/llvm/outputs.patch26
-rw-r--r--pkgs/development/compilers/llvm/6/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/6/llvm/default.nix78
-rw-r--r--pkgs/development/compilers/llvm/6/llvm/outputs.patch26
-rw-r--r--pkgs/development/compilers/llvm/7/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/7/llvm/default.nix80
-rw-r--r--pkgs/development/compilers/llvm/7/llvm/outputs.patch26
-rw-r--r--pkgs/development/compilers/llvm/8/clang/default.nix1
-rw-r--r--pkgs/development/compilers/llvm/8/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/8/llvm/default.nix80
-rw-r--r--pkgs/development/compilers/llvm/8/llvm/outputs.patch26
-rw-r--r--pkgs/development/compilers/llvm/9/clang/default.nix1
-rw-r--r--pkgs/development/compilers/llvm/9/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/9/llvm/default.nix78
-rw-r--r--pkgs/development/compilers/llvm/9/llvm/outputs.patch26
-rw-r--r--pkgs/development/compilers/llvm/git/clang/default.nix2
-rw-r--r--pkgs/development/compilers/llvm/git/compiler-rt/default.nix2
-rw-r--r--pkgs/development/compilers/llvm/git/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/git/libcxx/default.nix6
-rw-r--r--pkgs/development/compilers/llvm/git/llvm/default.nix60
-rw-r--r--pkgs/development/compilers/llvm/git/llvm/outputs.patch26
-rw-r--r--pkgs/development/compilers/llvm/llvm-config-link-static.patch12
-rw-r--r--pkgs/development/compilers/llvm/rocm/llvm/outputs.patch16
48 files changed, 732 insertions, 442 deletions
diff --git a/pkgs/development/compilers/llvm/10/clang/default.nix b/pkgs/development/compilers/llvm/10/clang/default.nix
index b42f40b969439..5336e4ea35a3d 100644
--- a/pkgs/development/compilers/llvm/10/clang/default.nix
+++ b/pkgs/development/compilers/llvm/10/clang/default.nix
@@ -29,7 +29,6 @@ let
       "-DCMAKE_CXX_FLAGS=-std=c++14"
       "-DCLANGD_BUILD_XPC=OFF"
       "-DLLVM_ENABLE_RTTI=ON"
-      "-DLLVM_CONFIG_PATH=${libllvm.dev}/bin/llvm-config${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "-native"}"
     ] ++ lib.optionals enableManpages [
       "-DCLANG_INCLUDE_DOCS=ON"
       "-DLLVM_ENABLE_SPHINX=ON"
diff --git a/pkgs/development/compilers/llvm/10/default.nix b/pkgs/development/compilers/llvm/10/default.nix
index 8bd7e937e7d72..5cb6c278659d8 100644
--- a/pkgs/development/compilers/llvm/10/default.nix
+++ b/pkgs/development/compilers/llvm/10/default.nix
@@ -89,7 +89,11 @@ let
     #   python3 = pkgs.python3;  # don't use python-boot
     # });
 
-    clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang;
+    # pick clang appropriate for package set we are targeting
+    clang =
+      /**/ if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
+      else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
+      else tools.libcxxClang;
 
     libstdcxxClang = wrapCCWith rec {
       cc = tools.clang-unwrapped;
diff --git a/pkgs/development/compilers/llvm/10/llvm/default.nix b/pkgs/development/compilers/llvm/10/llvm/default.nix
index 30a2d016d67c7..bb1b90b36a922 100644
--- a/pkgs/development/compilers/llvm/10/llvm/default.nix
+++ b/pkgs/development/compilers/llvm/10/llvm/default.nix
@@ -57,6 +57,12 @@ in stdenv.mkDerivation (rec {
   propagatedBuildInputs = [ ncurses zlib ];
 
   patches = [
+    # When cross-compiling we configure llvm-config-native with an approximation
+    # of the flags used for the normal LLVM build. To avoid the need for building
+    # a native libLLVM.so (which would fail) we force llvm-config to be linked
+    # statically against the necessary LLVM components always.
+    ../../llvm-config-link-static.patch
+
     ./gnu-install-dirs.patch
     # On older CPUs (e.g. Hydra/wendy) we'd be getting an error in this test.
     (fetchpatch {
@@ -93,11 +99,6 @@ in stdenv.mkDerivation (rec {
     substituteInPlace cmake/modules/AddLLVM.cmake \
       --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \
       --replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}''${LLVM_LIBDIR_SUFFIX}" ''${extra_libdir})' ""
-  ''
-  # Patch llvm-config to return correct library path based on --link-{shared,static}.
-  + optionalString (enableSharedLibraries) ''
-    substitute '${./outputs.patch}' ./outputs.patch --subst-var lib
-    patch -p1 < ./outputs.patch
   '' + ''
     # FileSystem permissions tests fail with various special bits
     substituteInPlace unittests/Support/CMakeLists.txt \
@@ -122,6 +123,32 @@ in stdenv.mkDerivation (rec {
     rm test/ExecutionEngine/frem.ll
   '' + ''
     patchShebangs test/BugPoint/compile-custom.ll.py
+  '' + ''
+    # Tweak tests to ignore namespace part of type to support
+    # gcc-12: https://gcc.gnu.org/PR103598.
+    # The change below mangles strings like:
+    #    CHECK-NEXT: Starting llvm::Function pass manager run.
+    # to:
+    #    CHECK-NEXT: Starting {{.*}}Function pass manager run.
+    for f in \
+      test/Other/new-pass-manager.ll \
+      test/Other/new-pm-defaults.ll \
+      test/Other/new-pm-lto-defaults.ll \
+      test/Other/new-pm-thinlto-defaults.ll \
+      test/Other/pass-pipeline-parsing.ll \
+      test/Transforms/Inline/cgscc-incremental-invalidate.ll \
+      test/Transforms/Inline/clear-analyses.ll \
+      test/Transforms/LoopUnroll/unroll-loop-invalidation.ll \
+      test/Transforms/SCCP/ipsccp-preserve-analysis.ll \
+      test/Transforms/SCCP/preserve-analysis.ll \
+      test/Transforms/SROA/dead-inst.ll \
+      test/tools/gold/X86/new-pm.ll \
+      ; do
+      echo "PATCH: $f"
+      substituteInPlace $f \
+        --replace 'Starting llvm::' 'Starting {{.*}}' \
+        --replace 'Finished llvm::' 'Finished {{.*}}'
+    done
   '';
 
   # hacky fix: created binaries need to be run before installation
@@ -130,18 +157,28 @@ in stdenv.mkDerivation (rec {
     ln -sv $PWD/lib $out
   '';
 
-  cmakeFlags = with stdenv; [
-    "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+  cmakeFlags = with stdenv; let
+    # These flags influence llvm-config's BuildVariables.inc in addition to the
+    # general build. We need to make sure these are also passed via
+    # CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native
+    # will return different results from the cross llvm-config.
+    #
+    # Some flags don't need to be repassed because LLVM already does so (like
+    # CMAKE_BUILD_TYPE), others are irrelevant to the result.
+    flagsForLlvmConfig = [
+      "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+      "-DLLVM_ENABLE_RTTI=ON"
+    ] ++ optionals enableSharedLibraries [
+      "-DLLVM_LINK_LLVM_DYLIB=ON"
+    ];
+  in flagsForLlvmConfig ++ [
     "-DCMAKE_BUILD_TYPE=${if debugVersion then "Debug" else "Release"}"
     "-DLLVM_INSTALL_UTILS=ON"  # Needed by rustc
-    "-DLLVM_BUILD_TESTS=ON"
+    "-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}"
     "-DLLVM_ENABLE_FFI=ON"
-    "-DLLVM_ENABLE_RTTI=ON"
     "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_ENABLE_DUMP=ON"
-  ] ++ optionals enableSharedLibraries [
-    "-DLLVM_LINK_LLVM_DYLIB=ON"
   ] ++ optionals enableManpages [
     "-DLLVM_BUILD_DOCS=ON"
     "-DLLVM_ENABLE_SPHINX=ON"
@@ -167,7 +204,21 @@ in stdenv.mkDerivation (rec {
           "-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip"
           "-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib"
         ];
-      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list=${lib.concatStringsSep ";" nativeToolchainFlags}"
+        # We need to repass the custom GNUInstallDirs values, otherwise CMake
+        # will choose them for us, leading to wrong results in llvm-config-native
+        nativeInstallFlags = [
+          "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
+          "-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin"
+          "-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include"
+          "-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib"
+          "-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec"
+        ];
+      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list="
+      + lib.concatStringsSep ";" (lib.concatLists [
+        flagsForLlvmConfig
+        nativeToolchainFlags
+        nativeInstallFlags
+      ])
     )
   ];
 
@@ -197,7 +248,8 @@ in stdenv.mkDerivation (rec {
     cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native
   '';
 
-  doCheck = stdenv.isLinux && (!stdenv.isx86_32);
+  doCheck = stdenv.isLinux && (!stdenv.isx86_32)
+    && (stdenv.hostPlatform == stdenv.buildPlatform);
 
   checkTarget = "check-all";
 
diff --git a/pkgs/development/compilers/llvm/10/llvm/outputs.patch b/pkgs/development/compilers/llvm/10/llvm/outputs.patch
deleted file mode 100644
index 40096fa3497fd..0000000000000
--- a/pkgs/development/compilers/llvm/10/llvm/outputs.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
-index 94d426b..37f7794 100644
---- a/tools/llvm-config/llvm-config.cpp
-+++ b/tools/llvm-config/llvm-config.cpp
-@@ -333,6 +333,21 @@ int main(int argc, char **argv) {
-     ActiveIncludeOption = "-I" + ActiveIncludeDir;
-   }
- 
-+  /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared
-+  if (!IsInDevelopmentTree) {
-+    bool WantShared = true;
-+    for (int i = 1; i < argc; ++i) {
-+      StringRef Arg = argv[i];
-+      if (Arg == "--link-shared")
-+        WantShared = true;
-+      else if (Arg == "--link-static")
-+        WantShared = false; // the last one wins
-+    }
-+
-+    if (WantShared)
-+      ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
-+  }
-+
-   /// We only use `shared library` mode in cases where the static library form
-   /// of the components provided are not available; note however that this is
-   /// skipped if we're run from within the build dir. However, once installed,
diff --git a/pkgs/development/compilers/llvm/11/clang/default.nix b/pkgs/development/compilers/llvm/11/clang/default.nix
index 9eed5269da6bd..58439f02a5c92 100644
--- a/pkgs/development/compilers/llvm/11/clang/default.nix
+++ b/pkgs/development/compilers/llvm/11/clang/default.nix
@@ -30,7 +30,7 @@ let
     cmakeFlags = [
       "-DCMAKE_CXX_FLAGS=-std=c++14"
       "-DCLANGD_BUILD_XPC=OFF"
-      "-DLLVM_CONFIG_PATH=${libllvm.dev}/bin/llvm-config${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "-native"}"
+      "-DLLVM_ENABLE_RTTI=ON"
     ] ++ lib.optionals enableManpages [
       "-DCLANG_INCLUDE_DOCS=ON"
       "-DLLVM_ENABLE_SPHINX=ON"
diff --git a/pkgs/development/compilers/llvm/11/default.nix b/pkgs/development/compilers/llvm/11/default.nix
index ebd0dc672aa35..82a78af85cac9 100644
--- a/pkgs/development/compilers/llvm/11/default.nix
+++ b/pkgs/development/compilers/llvm/11/default.nix
@@ -104,7 +104,11 @@ let
     #   python3 = pkgs.python3;  # don't use python-boot
     # });
 
-    clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang;
+    # pick clang appropriate for package set we are targeting
+    clang =
+      /**/ if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
+      else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
+      else tools.libcxxClang;
 
     libstdcxxClang = wrapCCWith rec {
       cc = tools.clang-unwrapped;
diff --git a/pkgs/development/compilers/llvm/11/llvm/default.nix b/pkgs/development/compilers/llvm/11/llvm/default.nix
index 81ac4cb1ed080..e8cfd23faa7e8 100644
--- a/pkgs/development/compilers/llvm/11/llvm/default.nix
+++ b/pkgs/development/compilers/llvm/11/llvm/default.nix
@@ -57,6 +57,12 @@ in stdenv.mkDerivation (rec {
   propagatedBuildInputs = [ ncurses zlib ];
 
   patches = [
+    # When cross-compiling we configure llvm-config-native with an approximation
+    # of the flags used for the normal LLVM build. To avoid the need for building
+    # a native libLLVM.so (which would fail) we force llvm-config to be linked
+    # statically against the necessary LLVM components always.
+    ../../llvm-config-link-static.patch
+
     ./gnu-install-dirs.patch
     # On older CPUs (e.g. Hydra/wendy) we'd be getting an error in this test.
     (fetchpatch {
@@ -91,11 +97,6 @@ in stdenv.mkDerivation (rec {
     substituteInPlace cmake/modules/AddLLVM.cmake \
       --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \
       --replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}''${LLVM_LIBDIR_SUFFIX}" ''${extra_libdir})' ""
-  ''
-  # Patch llvm-config to return correct library path based on --link-{shared,static}.
-  + optionalString (enableSharedLibraries) ''
-    substitute '${./outputs.patch}' ./outputs.patch --subst-var lib
-    patch -p1 < ./outputs.patch
   '' + ''
     # FileSystem permissions tests fail with various special bits
     substituteInPlace unittests/Support/CMakeLists.txt \
@@ -120,6 +121,32 @@ in stdenv.mkDerivation (rec {
     rm test/ExecutionEngine/frem.ll
   '' + ''
     patchShebangs test/BugPoint/compile-custom.ll.py
+  '' + ''
+    # Tweak tests to ignore namespace part of type to support
+    # gcc-12: https://gcc.gnu.org/PR103598.
+    # The change below mangles strings like:
+    #    CHECK-NEXT: Starting llvm::Function pass manager run.
+    # to:
+    #    CHECK-NEXT: Starting {{.*}}Function pass manager run.
+    for f in \
+      test/Other/new-pass-manager.ll \
+      test/Other/new-pm-defaults.ll \
+      test/Other/new-pm-lto-defaults.ll \
+      test/Other/new-pm-thinlto-defaults.ll \
+      test/Other/pass-pipeline-parsing.ll \
+      test/Transforms/Inline/cgscc-incremental-invalidate.ll \
+      test/Transforms/Inline/clear-analyses.ll \
+      test/Transforms/LoopUnroll/unroll-loop-invalidation.ll \
+      test/Transforms/SCCP/ipsccp-preserve-analysis.ll \
+      test/Transforms/SCCP/preserve-analysis.ll \
+      test/Transforms/SROA/dead-inst.ll \
+      test/tools/gold/X86/new-pm.ll \
+      ; do
+      echo "PATCH: $f"
+      substituteInPlace $f \
+        --replace 'Starting llvm::' 'Starting {{.*}}' \
+        --replace 'Finished llvm::' 'Finished {{.*}}'
+    done
   '';
 
   # hacky fix: created binaries need to be run before installation
@@ -131,18 +158,38 @@ in stdenv.mkDerivation (rec {
   # E.g. mesa.drivers use the build-id as a cache key (see #93946):
   LDFLAGS = optionalString (enableSharedLibraries && !stdenv.isDarwin) "-Wl,--build-id=sha1";
 
-  cmakeFlags = with stdenv; [
-    "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+  cmakeFlags = with stdenv; let
+    # These flags influence llvm-config's BuildVariables.inc in addition to the
+    # general build. We need to make sure these are also passed via
+    # CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native
+    # will return different results from the cross llvm-config.
+    #
+    # Some flags don't need to be repassed because LLVM already does so (like
+    # CMAKE_BUILD_TYPE), others are irrelevant to the result.
+    flagsForLlvmConfig = [
+      "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+      "-DLLVM_ENABLE_RTTI=ON"
+    ] ++ optionals enableSharedLibraries [
+      "-DLLVM_LINK_LLVM_DYLIB=ON"
+    ];
+  in flagsForLlvmConfig ++ [
     "-DCMAKE_BUILD_TYPE=${if debugVersion then "Debug" else "Release"}"
     "-DLLVM_INSTALL_UTILS=ON"  # Needed by rustc
-    "-DLLVM_BUILD_TESTS=ON"
+    "-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}"
     "-DLLVM_ENABLE_FFI=ON"
-    "-DLLVM_ENABLE_RTTI=ON"
     "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_ENABLE_DUMP=ON"
-  ] ++ optionals enableSharedLibraries [
-    "-DLLVM_LINK_LLVM_DYLIB=ON"
+  ] ++ optionals stdenv.hostPlatform.isStatic [
+    # Disables building of shared libs, -fPIC is still injected by cc-wrapper
+    "-DLLVM_ENABLE_PIC=OFF"
+    "-DLLVM_BUILD_STATIC=ON"
+    # libxml2 needs to be disabled because the LLVM build system ignores its .la
+    # file and doesn't link zlib as well.
+    # https://github.com/ClangBuiltLinux/tc-build/issues/150#issuecomment-845418812
+    "-DLLVM_ENABLE_LIBXML2=OFF"
+    # This is a Shared Library not tied to LLVM_ENABLE_PIC
+    "-DLLVM_TOOL_REMARKS_SHLIB_BUILD=OFF"
   ] ++ optionals enableManpages [
     "-DLLVM_BUILD_DOCS=ON"
     "-DLLVM_ENABLE_SPHINX=ON"
@@ -168,7 +215,21 @@ in stdenv.mkDerivation (rec {
           "-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip"
           "-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib"
         ];
-      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list=${lib.concatStringsSep ";" nativeToolchainFlags}"
+        # We need to repass the custom GNUInstallDirs values, otherwise CMake
+        # will choose them for us, leading to wrong results in llvm-config-native
+        nativeInstallFlags = [
+          "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
+          "-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin"
+          "-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include"
+          "-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib"
+          "-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec"
+        ];
+      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list="
+      + lib.concatStringsSep ";" (lib.concatLists [
+        flagsForLlvmConfig
+        nativeToolchainFlags
+        nativeInstallFlags
+      ])
     )
   ];
 
@@ -198,7 +259,8 @@ in stdenv.mkDerivation (rec {
     cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native
   '';
 
-  doCheck = stdenv.isLinux && (!stdenv.isx86_32) && (!stdenv.hostPlatform.isMusl) && (!stdenv.hostPlatform.isRiscV);
+  doCheck = stdenv.isLinux && (!stdenv.isx86_32) && (!stdenv.hostPlatform.isMusl) && (!stdenv.hostPlatform.isRiscV)
+    && (stdenv.hostPlatform == stdenv.buildPlatform);
 
   checkTarget = "check-all";
 
diff --git a/pkgs/development/compilers/llvm/11/llvm/outputs.patch b/pkgs/development/compilers/llvm/11/llvm/outputs.patch
deleted file mode 100644
index 40096fa3497fd..0000000000000
--- a/pkgs/development/compilers/llvm/11/llvm/outputs.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
-index 94d426b..37f7794 100644
---- a/tools/llvm-config/llvm-config.cpp
-+++ b/tools/llvm-config/llvm-config.cpp
-@@ -333,6 +333,21 @@ int main(int argc, char **argv) {
-     ActiveIncludeOption = "-I" + ActiveIncludeDir;
-   }
- 
-+  /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared
-+  if (!IsInDevelopmentTree) {
-+    bool WantShared = true;
-+    for (int i = 1; i < argc; ++i) {
-+      StringRef Arg = argv[i];
-+      if (Arg == "--link-shared")
-+        WantShared = true;
-+      else if (Arg == "--link-static")
-+        WantShared = false; // the last one wins
-+    }
-+
-+    if (WantShared)
-+      ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
-+  }
-+
-   /// We only use `shared library` mode in cases where the static library form
-   /// of the components provided are not available; note however that this is
-   /// skipped if we're run from within the build dir. However, once installed,
diff --git a/pkgs/development/compilers/llvm/12/clang/default.nix b/pkgs/development/compilers/llvm/12/clang/default.nix
index d6ee375244151..0f1e160bbce82 100644
--- a/pkgs/development/compilers/llvm/12/clang/default.nix
+++ b/pkgs/development/compilers/llvm/12/clang/default.nix
@@ -31,7 +31,7 @@ let
     cmakeFlags = [
       "-DCMAKE_CXX_FLAGS=-std=c++14"
       "-DCLANGD_BUILD_XPC=OFF"
-      "-DLLVM_CONFIG_PATH=${libllvm.dev}/bin/llvm-config${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "-native"}"
+      "-DLLVM_ENABLE_RTTI=ON"
     ] ++ lib.optionals enableManpages [
       "-DCLANG_INCLUDE_DOCS=ON"
       "-DLLVM_ENABLE_SPHINX=ON"
diff --git a/pkgs/development/compilers/llvm/12/compiler-rt/default.nix b/pkgs/development/compilers/llvm/12/compiler-rt/default.nix
index 13c611ca8cc6d..4b2907ed30788 100644
--- a/pkgs/development/compilers/llvm/12/compiler-rt/default.nix
+++ b/pkgs/development/compilers/llvm/12/compiler-rt/default.nix
@@ -30,6 +30,7 @@ stdenv.mkDerivation {
     "-DCOMPILER_RT_BUILD_XRAY=OFF"
     "-DCOMPILER_RT_BUILD_LIBFUZZER=OFF"
     "-DCOMPILER_RT_BUILD_PROFILE=OFF"
+    "-DCOMPILER_RT_BUILD_MEMPROF=OFF"
   ] ++ lib.optionals ((useLLVM || bareMetal) && !haveLibc) [
     "-DCMAKE_C_COMPILER_WORKS=ON"
     "-DCMAKE_CXX_COMPILER_WORKS=ON"
diff --git a/pkgs/development/compilers/llvm/12/default.nix b/pkgs/development/compilers/llvm/12/default.nix
index e68522faea06c..4a2a7ee878948 100644
--- a/pkgs/development/compilers/llvm/12/default.nix
+++ b/pkgs/development/compilers/llvm/12/default.nix
@@ -92,7 +92,11 @@ let
     #   python3 = pkgs.python3;  # don't use python-boot
     # });
 
-    clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang;
+    # pick clang appropriate for package set we are targeting
+    clang =
+      /**/ if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
+      else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
+      else tools.libcxxClang;
 
     libstdcxxClang = wrapCCWith rec {
       cc = tools.clang-unwrapped;
diff --git a/pkgs/development/compilers/llvm/12/libcxx/default.nix b/pkgs/development/compilers/llvm/12/libcxx/default.nix
index 30dc3f4f206cb..3ddcb79975050 100644
--- a/pkgs/development/compilers/llvm/12/libcxx/default.nix
+++ b/pkgs/development/compilers/llvm/12/libcxx/default.nix
@@ -23,12 +23,6 @@ stdenv.mkDerivation {
     ../../libcxx-0001-musl-hacks.patch
   ];
 
-  # Prevent errors like "error: 'foo' is unavailable: introduced in macOS yy.zz"
-  postPatch = ''
-    substituteInPlace include/__config \
-      --replace "#    define _LIBCPP_USE_AVAILABILITY_APPLE" ""
-  '';
-
   preConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
     patchShebangs utils/cat_files.py
   '';
diff --git a/pkgs/development/compilers/llvm/12/llvm/default.nix b/pkgs/development/compilers/llvm/12/llvm/default.nix
index 30a1a7a16df83..2c035ee67a9e2 100644
--- a/pkgs/development/compilers/llvm/12/llvm/default.nix
+++ b/pkgs/development/compilers/llvm/12/llvm/default.nix
@@ -58,6 +58,15 @@ in stdenv.mkDerivation (rec {
     ++ [ zlib ];
 
   patches = [
+    # When cross-compiling we configure llvm-config-native with an approximation
+    # of the flags used for the normal LLVM build. To avoid the need for building
+    # a native libLLVM.so (which would fail) we force llvm-config to be linked
+    # statically against the necessary LLVM components always.
+    ../../llvm-config-link-static.patch
+    # Fix llvm being miscompiled by some gccs. See llvm/llvm-project#49955
+    # Fix llvm being miscompiled by some gccs. See https://github.com/llvm/llvm-project/issues/49955
+    ./fix-llvm-issue-49955.patch
+
     ./gnu-install-dirs.patch
     # On older CPUs (e.g. Hydra/wendy) we'd be getting an error in this test.
     (fetchpatch {
@@ -72,11 +81,6 @@ in stdenv.mkDerivation (rec {
     substituteInPlace cmake/modules/AddLLVM.cmake \
       --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \
       --replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}''${LLVM_LIBDIR_SUFFIX}" ''${extra_libdir})' ""
-  ''
-  # Patch llvm-config to return correct library path based on --link-{shared,static}.
-  + optionalString (enableSharedLibraries) ''
-    substitute '${./outputs.patch}' ./outputs.patch --subst-var lib
-    patch -p1 < ./outputs.patch
   '' + ''
     # FileSystem permissions tests fail with various special bits
     substituteInPlace unittests/Support/CMakeLists.txt \
@@ -105,6 +109,33 @@ in stdenv.mkDerivation (rec {
     rm test/ExecutionEngine/frem.ll
   '' + ''
     patchShebangs test/BugPoint/compile-custom.ll.py
+  '' + ''
+    # Tweak tests to ignore namespace part of type to support
+    # gcc-12: https://gcc.gnu.org/PR103598.
+    # The change below mangles strings like:
+    #    CHECK-NEXT: Starting llvm::Function pass manager run.
+    # to:
+    #    CHECK-NEXT: Starting {{.*}}Function pass manager run.
+    for f in \
+      test/Other/new-pass-manager.ll \
+      test/Other/new-pm-O0-defaults.ll \
+      test/Other/new-pm-defaults.ll \
+      test/Other/new-pm-lto-defaults.ll \
+      test/Other/new-pm-thinlto-defaults.ll \
+      test/Other/pass-pipeline-parsing.ll \
+      test/Transforms/Inline/cgscc-incremental-invalidate.ll \
+      test/Transforms/Inline/clear-analyses.ll \
+      test/Transforms/LoopUnroll/unroll-loop-invalidation.ll \
+      test/Transforms/SCCP/ipsccp-preserve-analysis.ll \
+      test/Transforms/SCCP/preserve-analysis.ll \
+      test/Transforms/SROA/dead-inst.ll \
+      test/tools/gold/X86/new-pm.ll \
+      ; do
+      echo "PATCH: $f"
+      substituteInPlace $f \
+        --replace 'Starting llvm::' 'Starting {{.*}}' \
+        --replace 'Finished llvm::' 'Finished {{.*}}'
+    done
   '';
 
   # hacky fix: created binaries need to be run before installation
@@ -116,18 +147,36 @@ in stdenv.mkDerivation (rec {
   # E.g. mesa.drivers use the build-id as a cache key (see #93946):
   LDFLAGS = optionalString (enableSharedLibraries && !stdenv.isDarwin) "-Wl,--build-id=sha1";
 
-  cmakeFlags = with stdenv; [
-    "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+  cmakeFlags = with stdenv; let
+    # These flags influence llvm-config's BuildVariables.inc in addition to the
+    # general build. We need to make sure these are also passed via
+    # CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native
+    # will return different results from the cross llvm-config.
+    #
+    # Some flags don't need to be repassed because LLVM already does so (like
+    # CMAKE_BUILD_TYPE), others are irrelevant to the result.
+    flagsForLlvmConfig = [
+      "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+      "-DLLVM_ENABLE_RTTI=ON"
+    ] ++ optionals enableSharedLibraries [
+      "-DLLVM_LINK_LLVM_DYLIB=ON"
+    ];
+  in flagsForLlvmConfig ++ [
     "-DCMAKE_BUILD_TYPE=${if debugVersion then "Debug" else "Release"}"
     "-DLLVM_INSTALL_UTILS=ON"  # Needed by rustc
-    "-DLLVM_BUILD_TESTS=ON"
+    "-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}"
     "-DLLVM_ENABLE_FFI=ON"
-    "-DLLVM_ENABLE_RTTI=ON"
     "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_ENABLE_DUMP=ON"
-  ] ++ optionals enableSharedLibraries [
-    "-DLLVM_LINK_LLVM_DYLIB=ON"
+  ] ++ optionals stdenv.hostPlatform.isStatic [
+    # Disables building of shared libs, -fPIC is still injected by cc-wrapper
+    "-DLLVM_ENABLE_PIC=OFF"
+    "-DLLVM_BUILD_STATIC=ON"
+    # libxml2 needs to be disabled because the LLVM build system ignores its .la
+    # file and doesn't link zlib as well.
+    # https://github.com/ClangBuiltLinux/tc-build/issues/150#issuecomment-845418812
+    "-DLLVM_ENABLE_LIBXML2=OFF"
   ] ++ optionals enableManpages [
     "-DLLVM_BUILD_DOCS=ON"
     "-DLLVM_ENABLE_SPHINX=ON"
@@ -153,7 +202,21 @@ in stdenv.mkDerivation (rec {
           "-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip"
           "-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib"
         ];
-      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list=${lib.concatStringsSep ";" nativeToolchainFlags}"
+        # We need to repass the custom GNUInstallDirs values, otherwise CMake
+        # will choose them for us, leading to wrong results in llvm-config-native
+        nativeInstallFlags = [
+          "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
+          "-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin"
+          "-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include"
+          "-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib"
+          "-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec"
+        ];
+      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list="
+      + lib.concatStringsSep ";" (lib.concatLists [
+        flagsForLlvmConfig
+        nativeToolchainFlags
+        nativeInstallFlags
+      ])
     )
   ];
 
@@ -183,7 +246,8 @@ in stdenv.mkDerivation (rec {
     cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native
   '';
 
-  doCheck = stdenv.isLinux && (!stdenv.isx86_32) && (!stdenv.hostPlatform.isMusl);
+  doCheck = stdenv.isLinux && (!stdenv.isx86_32) && (!stdenv.hostPlatform.isMusl)
+    && (stdenv.hostPlatform == stdenv.buildPlatform);
 
   checkTarget = "check-all";
 
diff --git a/pkgs/development/compilers/llvm/12/llvm/fix-llvm-issue-49955.patch b/pkgs/development/compilers/llvm/12/llvm/fix-llvm-issue-49955.patch
new file mode 100644
index 0000000000000..b515583a0c421
--- /dev/null
+++ b/pkgs/development/compilers/llvm/12/llvm/fix-llvm-issue-49955.patch
@@ -0,0 +1,13 @@
+diff --git a/lib/CodeGen/AsmPrinter/CMakeLists.txt b/lib/CodeGen/AsmPrinter/CMakeLists.txt
+index eb924282..c77c140b 100644
+--- a/lib/CodeGen/AsmPrinter/CMakeLists.txt
++++ b/lib/CodeGen/AsmPrinter/CMakeLists.txt
+@@ -44,3 +44,8 @@ add_llvm_component_library(LLVMAsmPrinter
+   Support
+   Target
+   )
++
++if (CMAKE_COMPILER_IS_GNUCXX)
++  set_source_files_properties(DwarfCompileUnit.cpp PROPERTIES
++                              COMPILE_FLAGS -fno-strict-aliasing)
++endif()
diff --git a/pkgs/development/compilers/llvm/12/llvm/outputs.patch b/pkgs/development/compilers/llvm/12/llvm/outputs.patch
deleted file mode 100644
index 40096fa3497fd..0000000000000
--- a/pkgs/development/compilers/llvm/12/llvm/outputs.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
-index 94d426b..37f7794 100644
---- a/tools/llvm-config/llvm-config.cpp
-+++ b/tools/llvm-config/llvm-config.cpp
-@@ -333,6 +333,21 @@ int main(int argc, char **argv) {
-     ActiveIncludeOption = "-I" + ActiveIncludeDir;
-   }
- 
-+  /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared
-+  if (!IsInDevelopmentTree) {
-+    bool WantShared = true;
-+    for (int i = 1; i < argc; ++i) {
-+      StringRef Arg = argv[i];
-+      if (Arg == "--link-shared")
-+        WantShared = true;
-+      else if (Arg == "--link-static")
-+        WantShared = false; // the last one wins
-+    }
-+
-+    if (WantShared)
-+      ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
-+  }
-+
-   /// We only use `shared library` mode in cases where the static library form
-   /// of the components provided are not available; note however that this is
-   /// skipped if we're run from within the build dir. However, once installed,
diff --git a/pkgs/development/compilers/llvm/13/clang/default.nix b/pkgs/development/compilers/llvm/13/clang/default.nix
index ab826fa315261..6c227f1ae72bb 100644
--- a/pkgs/development/compilers/llvm/13/clang/default.nix
+++ b/pkgs/development/compilers/llvm/13/clang/default.nix
@@ -21,7 +21,7 @@ let
     cmakeFlags = [
       "-DCMAKE_CXX_FLAGS=-std=c++14"
       "-DCLANGD_BUILD_XPC=OFF"
-      "-DLLVM_CONFIG_PATH=${libllvm.dev}/bin/llvm-config${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "-native"}"
+      "-DLLVM_ENABLE_RTTI=ON"
     ] ++ lib.optionals enableManpages [
       "-DCLANG_INCLUDE_DOCS=ON"
       "-DLLVM_ENABLE_SPHINX=ON"
diff --git a/pkgs/development/compilers/llvm/13/compiler-rt/default.nix b/pkgs/development/compilers/llvm/13/compiler-rt/default.nix
index e30db5fcd9541..10b89b91b96f7 100644
--- a/pkgs/development/compilers/llvm/13/compiler-rt/default.nix
+++ b/pkgs/development/compilers/llvm/13/compiler-rt/default.nix
@@ -33,6 +33,8 @@ stdenv.mkDerivation {
     "-DCOMPILER_RT_BUILD_SANITIZERS=OFF"
     "-DCOMPILER_RT_BUILD_XRAY=OFF"
     "-DCOMPILER_RT_BUILD_PROFILE=OFF"
+    "-DCOMPILER_RT_BUILD_MEMPROF=OFF"
+    "-DCOMPILER_RT_BUILD_ORC=OFF" # may be possible to build with musl if necessary
   ] ++ lib.optionals ((useLLVM || bareMetal) && !haveLibc) [
     "-DCMAKE_C_COMPILER_WORKS=ON"
     "-DCMAKE_CXX_COMPILER_WORKS=ON"
diff --git a/pkgs/development/compilers/llvm/13/default.nix b/pkgs/development/compilers/llvm/13/default.nix
index a89c6dabe3912..be5e9404cdd48 100644
--- a/pkgs/development/compilers/llvm/13/default.nix
+++ b/pkgs/development/compilers/llvm/13/default.nix
@@ -93,7 +93,11 @@ let
     #   python3 = pkgs.python3;  # don't use python-boot
     # });
 
-    clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang;
+    # pick clang appropriate for package set we are targeting
+    clang =
+      /**/ if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
+      else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
+      else tools.libcxxClang;
 
     libstdcxxClang = wrapCCWith rec {
       cc = tools.clang-unwrapped;
diff --git a/pkgs/development/compilers/llvm/13/libcxx/default.nix b/pkgs/development/compilers/llvm/13/libcxx/default.nix
index ddf51d9a2fa4d..0ce73ed97af6c 100644
--- a/pkgs/development/compilers/llvm/13/libcxx/default.nix
+++ b/pkgs/development/compilers/llvm/13/libcxx/default.nix
@@ -25,12 +25,6 @@ stdenv.mkDerivation rec {
     ../../libcxx-0001-musl-hacks.patch
   ];
 
-  # Prevent errors like "error: 'foo' is unavailable: introduced in macOS yy.zz"
-  postPatch = ''
-    substituteInPlace include/__config \
-      --replace "#    define _LIBCPP_USE_AVAILABILITY_APPLE" ""
-  '';
-
   preConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
     patchShebangs utils/cat_files.py
   '';
diff --git a/pkgs/development/compilers/llvm/13/llvm/default.nix b/pkgs/development/compilers/llvm/13/llvm/default.nix
index 957f29e44994a..abfb2b36d18f8 100644
--- a/pkgs/development/compilers/llvm/13/llvm/default.nix
+++ b/pkgs/development/compilers/llvm/13/llvm/default.nix
@@ -52,6 +52,12 @@ in stdenv.mkDerivation (rec {
   checkInputs = [ which ];
 
   patches = [
+    # When cross-compiling we configure llvm-config-native with an approximation
+    # of the flags used for the normal LLVM build. To avoid the need for building
+    # a native libLLVM.so (which would fail) we force llvm-config to be linked
+    # statically against the necessary LLVM components always.
+    ../../llvm-config-link-static.patch
+
     ./gnu-install-dirs.patch
 
     # Fix random compiler crashes: https://bugs.llvm.org/show_bug.cgi?id=50611
@@ -66,11 +72,6 @@ in stdenv.mkDerivation (rec {
     substituteInPlace cmake/modules/AddLLVM.cmake \
       --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \
       --replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}''${LLVM_LIBDIR_SUFFIX}" ''${extra_libdir})' ""
-  ''
-  # Patch llvm-config to return correct library path based on --link-{shared,static}.
-  + optionalString (enableSharedLibraries) ''
-    substitute '${./outputs.patch}' ./outputs.patch --subst-var lib
-    patch -p1 < ./outputs.patch
   '' + ''
     # FileSystem permissions tests fail with various special bits
     substituteInPlace unittests/Support/CMakeLists.txt \
@@ -109,18 +110,36 @@ in stdenv.mkDerivation (rec {
   # E.g. mesa.drivers use the build-id as a cache key (see #93946):
   LDFLAGS = optionalString (enableSharedLibraries && !stdenv.isDarwin) "-Wl,--build-id=sha1";
 
-  cmakeFlags = with stdenv; [
-    "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+  cmakeFlags = with stdenv; let
+    # These flags influence llvm-config's BuildVariables.inc in addition to the
+    # general build. We need to make sure these are also passed via
+    # CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native
+    # will return different results from the cross llvm-config.
+    #
+    # Some flags don't need to be repassed because LLVM already does so (like
+    # CMAKE_BUILD_TYPE), others are irrelevant to the result.
+    flagsForLlvmConfig = [
+      "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+      "-DLLVM_ENABLE_RTTI=ON"
+    ] ++ optionals enableSharedLibraries [
+      "-DLLVM_LINK_LLVM_DYLIB=ON"
+    ];
+  in flagsForLlvmConfig ++ [
     "-DCMAKE_BUILD_TYPE=${if debugVersion then "Debug" else "Release"}"
     "-DLLVM_INSTALL_UTILS=ON"  # Needed by rustc
-    "-DLLVM_BUILD_TESTS=ON"
+    "-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}"
     "-DLLVM_ENABLE_FFI=ON"
-    "-DLLVM_ENABLE_RTTI=ON"
     "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_ENABLE_DUMP=ON"
-  ] ++ optionals enableSharedLibraries [
-    "-DLLVM_LINK_LLVM_DYLIB=ON"
+  ] ++ optionals stdenv.hostPlatform.isStatic [
+    # Disables building of shared libs, -fPIC is still injected by cc-wrapper
+    "-DLLVM_ENABLE_PIC=OFF"
+    "-DLLVM_BUILD_STATIC=ON"
+    # libxml2 needs to be disabled because the LLVM build system ignores its .la
+    # file and doesn't link zlib as well.
+    # https://github.com/ClangBuiltLinux/tc-build/issues/150#issuecomment-845418812
+    "-DLLVM_ENABLE_LIBXML2=OFF"
   ] ++ optionals enableManpages [
     "-DLLVM_BUILD_DOCS=ON"
     "-DLLVM_ENABLE_SPHINX=ON"
@@ -146,7 +165,21 @@ in stdenv.mkDerivation (rec {
           "-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip"
           "-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib"
         ];
-      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list=${lib.concatStringsSep ";" nativeToolchainFlags}"
+        # We need to repass the custom GNUInstallDirs values, otherwise CMake
+        # will choose them for us, leading to wrong results in llvm-config-native
+        nativeInstallFlags = [
+          "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
+          "-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin"
+          "-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include"
+          "-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib"
+          "-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec"
+        ];
+      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list="
+      + lib.concatStringsSep ";" (lib.concatLists [
+        flagsForLlvmConfig
+        nativeToolchainFlags
+        nativeInstallFlags
+      ])
     )
   ];
 
@@ -176,7 +209,8 @@ in stdenv.mkDerivation (rec {
     cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native
   '';
 
-  doCheck = stdenv.isLinux && (!stdenv.isx86_32) && (!stdenv.hostPlatform.isMusl);
+  doCheck = stdenv.isLinux && (!stdenv.isx86_32) && (!stdenv.hostPlatform.isMusl)
+    && (stdenv.hostPlatform == stdenv.buildPlatform);
 
   checkTarget = "check-all";
 
diff --git a/pkgs/development/compilers/llvm/13/llvm/outputs.patch b/pkgs/development/compilers/llvm/13/llvm/outputs.patch
deleted file mode 100644
index 40096fa3497fd..0000000000000
--- a/pkgs/development/compilers/llvm/13/llvm/outputs.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
-index 94d426b..37f7794 100644
---- a/tools/llvm-config/llvm-config.cpp
-+++ b/tools/llvm-config/llvm-config.cpp
-@@ -333,6 +333,21 @@ int main(int argc, char **argv) {
-     ActiveIncludeOption = "-I" + ActiveIncludeDir;
-   }
- 
-+  /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared
-+  if (!IsInDevelopmentTree) {
-+    bool WantShared = true;
-+    for (int i = 1; i < argc; ++i) {
-+      StringRef Arg = argv[i];
-+      if (Arg == "--link-shared")
-+        WantShared = true;
-+      else if (Arg == "--link-static")
-+        WantShared = false; // the last one wins
-+    }
-+
-+    if (WantShared)
-+      ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
-+  }
-+
-   /// We only use `shared library` mode in cases where the static library form
-   /// of the components provided are not available; note however that this is
-   /// skipped if we're run from within the build dir. However, once installed,
diff --git a/pkgs/development/compilers/llvm/5/compiler-rt/compiler-rt-5-cstddef.patch b/pkgs/development/compilers/llvm/5/compiler-rt/compiler-rt-5-cstddef.patch
new file mode 100644
index 0000000000000..e7abf9735b908
--- /dev/null
+++ b/pkgs/development/compilers/llvm/5/compiler-rt/compiler-rt-5-cstddef.patch
@@ -0,0 +1,10 @@
+--- a/lib/xray/xray_buffer_queue.h
++++ b/lib/xray/xray_buffer_queue.h
+@@ -17,6 +17,7 @@
+ 
+ #include "sanitizer_common/sanitizer_atomic.h"
+ #include "sanitizer_common/sanitizer_mutex.h"
++#include <cstddef>
+ #include <deque>
+ #include <unordered_set>
+ #include <utility>
diff --git a/pkgs/development/compilers/llvm/5/compiler-rt/default.nix b/pkgs/development/compilers/llvm/5/compiler-rt/default.nix
index 874540dd8c3b2..f6f59bb6d99b4 100644
--- a/pkgs/development/compilers/llvm/5/compiler-rt/default.nix
+++ b/pkgs/development/compilers/llvm/5/compiler-rt/default.nix
@@ -58,6 +58,7 @@ stdenv.mkDerivation {
 
     ./sys-ustat.patch
     ../../common/compiler-rt/libsanitizer-no-cyclades-9.patch
+    ./compiler-rt-5-cstddef.patch
   ] ++ lib.optional stdenv.hostPlatform.isAarch32 ./armv7l.patch;
 
   # TSAN requires XPC on Darwin, which we have no public/free source files for. We can depend on the Apple frameworks
diff --git a/pkgs/development/compilers/llvm/5/default.nix b/pkgs/development/compilers/llvm/5/default.nix
index 4593580b72fda..ef9886fb5ea76 100644
--- a/pkgs/development/compilers/llvm/5/default.nix
+++ b/pkgs/development/compilers/llvm/5/default.nix
@@ -65,7 +65,11 @@ let
       python3 = pkgs.python3;  # don't use python-boot
     });
 
-    clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang;
+    # pick clang appropriate for package set we are targeting
+    clang =
+      /**/ if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
+      else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
+      else tools.libcxxClang;
 
     libstdcxxClang = wrapCCWith rec {
       cc = tools.clang-unwrapped;
diff --git a/pkgs/development/compilers/llvm/5/llvm/default.nix b/pkgs/development/compilers/llvm/5/llvm/default.nix
index fa99e275a6231..cf668cd566a65 100644
--- a/pkgs/development/compilers/llvm/5/llvm/default.nix
+++ b/pkgs/development/compilers/llvm/5/llvm/default.nix
@@ -27,7 +27,7 @@ let
     imap (i: _: concatStringsSep "." (take i parts)) parts;
 in
 
-stdenv.mkDerivation ({
+stdenv.mkDerivation (rec {
   pname = "llvm";
   inherit version;
 
@@ -65,6 +65,13 @@ stdenv.mkDerivation ({
     #  sha256 = "0injj1hqgrbcbihhwp2nbal88jfykad30r54f2cdcx7gws2fcy8i";
     #  stripLen = 1;
     #})
+
+    # When cross-compiling we configure llvm-config-native with an approximation
+    # of the flags used for the normal LLVM build. To avoid the need for building
+    # a native libLLVM.so (which would fail) we force llvm-config to be linked
+    # statically against the necessary LLVM components always.
+    ../../llvm-config-link-static.patch
+
     ./gnu-install-dirs.patch
 
     # Fix invalid std::string(nullptr) for GCC 12
@@ -80,11 +87,6 @@ stdenv.mkDerivation ({
     substituteInPlace cmake/modules/AddLLVM.cmake \
       --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \
       --replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}" ''${extra_libdir})' ""
-  ''
-  # Patch llvm-config to return correct library path based on --link-{shared,static}.
-  + optionalString (enableSharedLibraries) ''
-    substitute '${./outputs.patch}' ./outputs.patch --subst-var lib
-    patch -p1 < ./outputs.patch
   '' + ''
     # FileSystem permissions tests fail with various special bits
     substituteInPlace unittests/Support/CMakeLists.txt \
@@ -100,6 +102,27 @@ stdenv.mkDerivation ({
     substituteInPlace unittests/Support/CMakeLists.txt \
       --replace "add_subdirectory(DynamicLibrary)" ""
     rm unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp
+  '' + ''
+    # Tweak tests to ignore namespace part of type to support
+    # gcc-12: https://gcc.gnu.org/PR103598.
+    # The change below mangles strings like:
+    #    CHECK-NEXT: Starting llvm::Function pass manager run.
+    # to:
+    #    CHECK-NEXT: Starting {{.*}}Function pass manager run.
+    for f in \
+      test/Other/new-pass-manager.ll \
+      test/Other/new-pm-defaults.ll \
+      test/Other/new-pm-lto-defaults.ll \
+      test/Other/new-pm-thinlto-defaults.ll \
+      test/Other/pass-pipeline-parsing.ll \
+      test/Transforms/Inline/cgscc-incremental-invalidate.ll \
+      test/Transforms/Inline/clear-analyses.ll \
+      ; do
+      echo "PATCH: $f"
+      substituteInPlace $f \
+        --replace 'Starting llvm::' 'Starting {{.*}}' \
+        --replace 'Finished llvm::' 'Finished {{.*}}'
+    done
   '';
 
   # hacky fix: created binaries need to be run before installation
@@ -108,20 +131,30 @@ stdenv.mkDerivation ({
     ln -sv $PWD/lib $out
   '';
 
-  cmakeFlags = with stdenv; [
-    "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+  cmakeFlags = with stdenv; let
+    # These flags influence llvm-config's BuildVariables.inc in addition to the
+    # general build. We need to make sure these are also passed via
+    # CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native
+    # will return different results from the cross llvm-config.
+    #
+    # Some flags don't need to be repassed because LLVM already does so (like
+    # CMAKE_BUILD_TYPE), others are irrelevant to the result.
+    flagsForLlvmConfig = [
+      "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+      "-DLLVM_ENABLE_RTTI=ON"
+    ] ++ optionals enableSharedLibraries [
+      "-DLLVM_LINK_LLVM_DYLIB=ON"
+    ];
+  in flagsForLlvmConfig ++ [
     "-DCMAKE_BUILD_TYPE=${if debugVersion then "Debug" else "Release"}"
     "-DLLVM_INSTALL_UTILS=ON"  # Needed by rustc
-    "-DLLVM_BUILD_TESTS=ON"
+    "-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}"
     "-DLLVM_ENABLE_FFI=ON"
-    "-DLLVM_ENABLE_RTTI=ON"
 
     "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}"
     "-DTARGET_TRIPLE=${stdenv.hostPlatform.config}"
   ]
-  ++ lib.optional enableSharedLibraries
-    "-DLLVM_LINK_LLVM_DYLIB=ON"
   ++ lib.optionals enableManpages [
     "-DLLVM_BUILD_DOCS=ON"
     "-DLLVM_ENABLE_SPHINX=ON"
@@ -148,7 +181,21 @@ stdenv.mkDerivation ({
           "-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip"
           "-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib"
         ];
-      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list=${lib.concatStringsSep ";" nativeToolchainFlags}"
+        # We need to repass the custom GNUInstallDirs values, otherwise CMake
+        # will choose them for us, leading to wrong results in llvm-config-native
+        nativeInstallFlags = [
+          "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
+          "-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin"
+          "-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include"
+          "-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib"
+          "-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec"
+        ];
+      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list="
+      + lib.concatStringsSep ";" (lib.concatLists [
+        flagsForLlvmConfig
+        nativeToolchainFlags
+        nativeInstallFlags
+      ])
     )
   ];
 
@@ -179,7 +226,8 @@ stdenv.mkDerivation ({
     cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native
   '';
 
-  doCheck = stdenv.isLinux && (!stdenv.isi686);
+  doCheck = stdenv.isLinux && (!stdenv.isi686)
+    && (stdenv.hostPlatform == stdenv.buildPlatform);
 
   checkTarget = "check-all";
 
diff --git a/pkgs/development/compilers/llvm/5/llvm/outputs.patch b/pkgs/development/compilers/llvm/5/llvm/outputs.patch
deleted file mode 100644
index 40096fa3497fd..0000000000000
--- a/pkgs/development/compilers/llvm/5/llvm/outputs.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
-index 94d426b..37f7794 100644
---- a/tools/llvm-config/llvm-config.cpp
-+++ b/tools/llvm-config/llvm-config.cpp
-@@ -333,6 +333,21 @@ int main(int argc, char **argv) {
-     ActiveIncludeOption = "-I" + ActiveIncludeDir;
-   }
- 
-+  /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared
-+  if (!IsInDevelopmentTree) {
-+    bool WantShared = true;
-+    for (int i = 1; i < argc; ++i) {
-+      StringRef Arg = argv[i];
-+      if (Arg == "--link-shared")
-+        WantShared = true;
-+      else if (Arg == "--link-static")
-+        WantShared = false; // the last one wins
-+    }
-+
-+    if (WantShared)
-+      ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
-+  }
-+
-   /// We only use `shared library` mode in cases where the static library form
-   /// of the components provided are not available; note however that this is
-   /// skipped if we're run from within the build dir. However, once installed,
diff --git a/pkgs/development/compilers/llvm/6/default.nix b/pkgs/development/compilers/llvm/6/default.nix
index 9b1caf410bc26..4acfe6cd85d79 100644
--- a/pkgs/development/compilers/llvm/6/default.nix
+++ b/pkgs/development/compilers/llvm/6/default.nix
@@ -66,7 +66,11 @@ let
       python3 = pkgs.python3;  # don't use python-boot
     });
 
-    clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang;
+    # pick clang appropriate for package set we are targeting
+    clang =
+      /**/ if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
+      else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
+      else tools.libcxxClang;
 
     libstdcxxClang = wrapCCWith rec {
       cc = tools.clang-unwrapped;
diff --git a/pkgs/development/compilers/llvm/6/llvm/default.nix b/pkgs/development/compilers/llvm/6/llvm/default.nix
index 5925fab104fa2..61f9234274d35 100644
--- a/pkgs/development/compilers/llvm/6/llvm/default.nix
+++ b/pkgs/development/compilers/llvm/6/llvm/default.nix
@@ -27,7 +27,7 @@ let
     imap (i: _: concatStringsSep "." (take i parts)) parts;
 in
 
-stdenv.mkDerivation ({
+stdenv.mkDerivation (rec {
   pname = "llvm";
   inherit version;
 
@@ -63,6 +63,13 @@ stdenv.mkDerivation ({
       includes = [ "test/tools/gold/X86/common.ll" ];
       sha256 = "0fxgrxmfnjx17w3lcq19rk68b2xksh1bynz3ina784kma7hp4wdb";
     })
+
+    # When cross-compiling we configure llvm-config-native with an approximation
+    # of the flags used for the normal LLVM build. To avoid the need for building
+    # a native libLLVM.so (which would fail) we force llvm-config to be linked
+    # statically against the necessary LLVM components always.
+    ../../llvm-config-link-static.patch
+
     ./gnu-install-dirs.patch
 
     # Fix invalid std::string(nullptr) for GCC 12
@@ -78,11 +85,6 @@ stdenv.mkDerivation ({
     substituteInPlace cmake/modules/AddLLVM.cmake \
       --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \
       --replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}" ''${extra_libdir})' ""
-  ''
-  # Patch llvm-config to return correct library path based on --link-{shared,static}.
-  + optionalString (enableSharedLibraries) ''
-    substitute '${./outputs.patch}' ./outputs.patch --subst-var lib
-    patch -p1 < ./outputs.patch
   '' + ''
     # FileSystem permissions tests fail with various special bits
     substituteInPlace unittests/Support/CMakeLists.txt \
@@ -93,6 +95,29 @@ stdenv.mkDerivation ({
     substituteInPlace unittests/Support/CMakeLists.txt \
       --replace "add_subdirectory(DynamicLibrary)" ""
     rm unittests/Support/DynamicLibrary/DynamicLibraryTest.cpp
+  '' + ''
+    # Tweak tests to ignore namespace part of type to support
+    # gcc-12: https://gcc.gnu.org/PR103598.
+    # The change below mangles strings like:
+    #    CHECK-NEXT: Starting llvm::Function pass manager run.
+    # to:
+    #    CHECK-NEXT: Starting {{.*}}Function pass manager run.
+    for f in \
+      test/Other/new-pass-manager.ll \
+      test/Other/new-pm-defaults.ll \
+      test/Other/new-pm-lto-defaults.ll \
+      test/Other/new-pm-thinlto-defaults.ll \
+      test/Other/pass-pipeline-parsing.ll \
+      test/Transforms/Inline/cgscc-incremental-invalidate.ll \
+      test/Transforms/Inline/clear-analyses.ll \
+      test/Transforms/LoopUnroll/unroll-loop-invalidation.ll \
+      test/Transforms/SROA/dead-inst.ll \
+      ; do
+      echo "PATCH: $f"
+      substituteInPlace $f \
+        --replace 'Starting llvm::' 'Starting {{.*}}' \
+        --replace 'Finished llvm::' 'Finished {{.*}}'
+    done
   '';
 
   # hacky fix: created binaries need to be run before installation
@@ -101,19 +126,29 @@ stdenv.mkDerivation ({
     ln -sv $PWD/lib $out
   '';
 
-  cmakeFlags = with stdenv; [
-    "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+  cmakeFlags = with stdenv; let
+    # These flags influence llvm-config's BuildVariables.inc in addition to the
+    # general build. We need to make sure these are also passed via
+    # CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native
+    # will return different results from the cross llvm-config.
+    #
+    # Some flags don't need to be repassed because LLVM already does so (like
+    # CMAKE_BUILD_TYPE), others are irrelevant to the result.
+    flagsForLlvmConfig = [
+      "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+      "-DLLVM_ENABLE_RTTI=ON"
+    ] ++ optionals enableSharedLibraries [
+      "-DLLVM_LINK_LLVM_DYLIB=ON"
+    ];
+  in flagsForLlvmConfig ++ [
     "-DCMAKE_BUILD_TYPE=${if debugVersion then "Debug" else "Release"}"
     "-DLLVM_INSTALL_UTILS=ON"  # Needed by rustc
-    "-DLLVM_BUILD_TESTS=ON"
+    "-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}"
     "-DLLVM_ENABLE_FFI=ON"
-    "-DLLVM_ENABLE_RTTI=ON"
     "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly"
     "-DLLVM_ENABLE_DUMP=ON"
-  ] ++ optionals enableSharedLibraries [
-    "-DLLVM_LINK_LLVM_DYLIB=ON"
   ] ++ optionals enableManpages [
     "-DLLVM_BUILD_DOCS=ON"
     "-DLLVM_ENABLE_SPHINX=ON"
@@ -139,7 +174,21 @@ stdenv.mkDerivation ({
           "-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip"
           "-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib"
         ];
-      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list=${lib.concatStringsSep ";" nativeToolchainFlags}"
+        # We need to repass the custom GNUInstallDirs values, otherwise CMake
+        # will choose them for us, leading to wrong results in llvm-config-native
+        nativeInstallFlags = [
+          "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
+          "-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin"
+          "-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include"
+          "-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib"
+          "-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec"
+        ];
+      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list="
+      + lib.concatStringsSep ";" (lib.concatLists [
+        flagsForLlvmConfig
+        nativeToolchainFlags
+        nativeInstallFlags
+      ])
     )
   ];
 
@@ -170,7 +219,8 @@ stdenv.mkDerivation ({
     cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native
   '';
 
-  doCheck = stdenv.isLinux && (!stdenv.isi686);
+  doCheck = stdenv.isLinux && (!stdenv.isi686)
+    && (stdenv.hostPlatform == stdenv.buildPlatform);
 
   checkTarget = "check-all";
 
diff --git a/pkgs/development/compilers/llvm/6/llvm/outputs.patch b/pkgs/development/compilers/llvm/6/llvm/outputs.patch
deleted file mode 100644
index 40096fa3497fd..0000000000000
--- a/pkgs/development/compilers/llvm/6/llvm/outputs.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
-index 94d426b..37f7794 100644
---- a/tools/llvm-config/llvm-config.cpp
-+++ b/tools/llvm-config/llvm-config.cpp
-@@ -333,6 +333,21 @@ int main(int argc, char **argv) {
-     ActiveIncludeOption = "-I" + ActiveIncludeDir;
-   }
- 
-+  /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared
-+  if (!IsInDevelopmentTree) {
-+    bool WantShared = true;
-+    for (int i = 1; i < argc; ++i) {
-+      StringRef Arg = argv[i];
-+      if (Arg == "--link-shared")
-+        WantShared = true;
-+      else if (Arg == "--link-static")
-+        WantShared = false; // the last one wins
-+    }
-+
-+    if (WantShared)
-+      ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
-+  }
-+
-   /// We only use `shared library` mode in cases where the static library form
-   /// of the components provided are not available; note however that this is
-   /// skipped if we're run from within the build dir. However, once installed,
diff --git a/pkgs/development/compilers/llvm/7/default.nix b/pkgs/development/compilers/llvm/7/default.nix
index d014c043a80db..f0908f30775d7 100644
--- a/pkgs/development/compilers/llvm/7/default.nix
+++ b/pkgs/development/compilers/llvm/7/default.nix
@@ -96,7 +96,11 @@ let
       python3 = pkgs.python3;  # don't use python-boot
     });
 
-    clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang;
+    # pick clang appropriate for package set we are targeting
+    clang =
+      /**/ if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
+      else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
+      else tools.libcxxClang;
 
     libstdcxxClang = wrapCCWith rec {
       cc = tools.clang-unwrapped;
diff --git a/pkgs/development/compilers/llvm/7/llvm/default.nix b/pkgs/development/compilers/llvm/7/llvm/default.nix
index e4410bedf9170..b324e1a0e4d61 100644
--- a/pkgs/development/compilers/llvm/7/llvm/default.nix
+++ b/pkgs/development/compilers/llvm/7/llvm/default.nix
@@ -31,7 +31,7 @@ let
     let parts = splitVersion release_version; in
     imap (i: _: concatStringsSep "." (take i parts)) parts;
 
-in stdenv.mkDerivation ({
+in stdenv.mkDerivation (rec {
   pname = "llvm";
   inherit version;
 
@@ -67,6 +67,13 @@ in stdenv.mkDerivation ({
       url = "https://github.com/llvm-mirror/llvm/commit/cc1f2a595ead516812a6c50398f0f3480ebe031f.patch";
       sha256 = "0k6k1p5yisgwx417a67s7sr9930rqh1n0zv5jvply8vjjy4b3kf8";
     })
+
+    # When cross-compiling we configure llvm-config-native with an approximation
+    # of the flags used for the normal LLVM build. To avoid the need for building
+    # a native libLLVM.so (which would fail) we force llvm-config to be linked
+    # statically against the necessary LLVM components always.
+    ../../llvm-config-link-static.patch
+
     ./gnu-install-dirs.patch
 
     # Fix invalid std::string(nullptr) for GCC 12
@@ -82,11 +89,6 @@ in stdenv.mkDerivation ({
     substituteInPlace cmake/modules/AddLLVM.cmake \
       --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \
       --replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}" ''${extra_libdir})' ""
-  ''
-  # Patch llvm-config to return correct library path based on --link-{shared,static}.
-  + optionalString (enableSharedLibraries) ''
-    substitute '${./outputs.patch}' ./outputs.patch --subst-var lib
-    patch -p1 < ./outputs.patch
   '' + ''
     # FileSystem permissions tests fail with various special bits
     substituteInPlace unittests/Support/CMakeLists.txt \
@@ -110,6 +112,31 @@ in stdenv.mkDerivation ({
     rm test/ExecutionEngine/frem.ll
   '' + ''
     patchShebangs test/BugPoint/compile-custom.ll.py
+  '' + ''
+    # Tweak tests to ignore namespace part of type to support
+    # gcc-12: https://gcc.gnu.org/PR103598.
+    # The change below mangles strings like:
+    #    CHECK-NEXT: Starting llvm::Function pass manager run.
+    # to:
+    #    CHECK-NEXT: Starting {{.*}}Function pass manager run.
+    for f in \
+      test/Other/new-pass-manager.ll \
+      test/Other/new-pm-defaults.ll \
+      test/Other/new-pm-lto-defaults.ll \
+      test/Other/new-pm-thinlto-defaults.ll \
+      test/Other/pass-pipeline-parsing.ll \
+      test/Transforms/Inline/cgscc-incremental-invalidate.ll \
+      test/Transforms/Inline/clear-analyses.ll \
+      test/Transforms/LoopUnroll/unroll-loop-invalidation.ll \
+      test/Transforms/SCCP/preserve-analysis.ll \
+      test/Transforms/SROA/dead-inst.ll \
+      test/tools/gold/X86/new-pm.ll \
+      ; do
+      echo "PATCH: $f"
+      substituteInPlace $f \
+        --replace 'Starting llvm::' 'Starting {{.*}}' \
+        --replace 'Finished llvm::' 'Finished {{.*}}'
+    done
   '';
 
   # hacky fix: created binaries need to be run before installation
@@ -118,19 +145,29 @@ in stdenv.mkDerivation ({
     ln -sv $PWD/lib $out
   '';
 
-  cmakeFlags = with stdenv; [
-    "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+  cmakeFlags = with stdenv; let
+    # These flags influence llvm-config's BuildVariables.inc in addition to the
+    # general build. We need to make sure these are also passed via
+    # CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native
+    # will return different results from the cross llvm-config.
+    #
+    # Some flags don't need to be repassed because LLVM already does so (like
+    # CMAKE_BUILD_TYPE), others are irrelevant to the result.
+    flagsForLlvmConfig = [
+      "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+      "-DLLVM_ENABLE_RTTI=ON"
+    ] ++ optionals enableSharedLibraries [
+      "-DLLVM_LINK_LLVM_DYLIB=ON"
+    ];
+  in flagsForLlvmConfig ++ [
     "-DCMAKE_BUILD_TYPE=${if debugVersion then "Debug" else "Release"}"
     "-DLLVM_INSTALL_UTILS=ON"  # Needed by rustc
-    "-DLLVM_BUILD_TESTS=ON"
+    "-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}"
     "-DLLVM_ENABLE_FFI=ON"
-    "-DLLVM_ENABLE_RTTI=ON"
     "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly"
     "-DLLVM_ENABLE_DUMP=ON"
-  ] ++ optionals enableSharedLibraries [
-    "-DLLVM_LINK_LLVM_DYLIB=ON"
   ] ++ optionals enableManpages [
     "-DLLVM_BUILD_DOCS=ON"
     "-DLLVM_ENABLE_SPHINX=ON"
@@ -156,7 +193,21 @@ in stdenv.mkDerivation ({
           "-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip"
           "-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib"
         ];
-      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list=${lib.concatStringsSep ";" nativeToolchainFlags}"
+        # We need to repass the custom GNUInstallDirs values, otherwise CMake
+        # will choose them for us, leading to wrong results in llvm-config-native
+        nativeInstallFlags = [
+          "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
+          "-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin"
+          "-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include"
+          "-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib"
+          "-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec"
+        ];
+      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list="
+      + lib.concatStringsSep ";" (lib.concatLists [
+        flagsForLlvmConfig
+        nativeToolchainFlags
+        nativeInstallFlags
+      ])
     )
   ];
 
@@ -187,7 +238,8 @@ in stdenv.mkDerivation ({
     cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native
   '';
 
-  doCheck = stdenv.isLinux && (!stdenv.isx86_32);
+  doCheck = stdenv.isLinux && (!stdenv.isx86_32)
+    && (stdenv.hostPlatform == stdenv.buildPlatform);
 
   checkTarget = "check-all";
 
diff --git a/pkgs/development/compilers/llvm/7/llvm/outputs.patch b/pkgs/development/compilers/llvm/7/llvm/outputs.patch
deleted file mode 100644
index 40096fa3497fd..0000000000000
--- a/pkgs/development/compilers/llvm/7/llvm/outputs.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
-index 94d426b..37f7794 100644
---- a/tools/llvm-config/llvm-config.cpp
-+++ b/tools/llvm-config/llvm-config.cpp
-@@ -333,6 +333,21 @@ int main(int argc, char **argv) {
-     ActiveIncludeOption = "-I" + ActiveIncludeDir;
-   }
- 
-+  /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared
-+  if (!IsInDevelopmentTree) {
-+    bool WantShared = true;
-+    for (int i = 1; i < argc; ++i) {
-+      StringRef Arg = argv[i];
-+      if (Arg == "--link-shared")
-+        WantShared = true;
-+      else if (Arg == "--link-static")
-+        WantShared = false; // the last one wins
-+    }
-+
-+    if (WantShared)
-+      ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
-+  }
-+
-   /// We only use `shared library` mode in cases where the static library form
-   /// of the components provided are not available; note however that this is
-   /// skipped if we're run from within the build dir. However, once installed,
diff --git a/pkgs/development/compilers/llvm/8/clang/default.nix b/pkgs/development/compilers/llvm/8/clang/default.nix
index 5cb7720d026f2..1d6a5b7d74df5 100644
--- a/pkgs/development/compilers/llvm/8/clang/default.nix
+++ b/pkgs/development/compilers/llvm/8/clang/default.nix
@@ -30,7 +30,6 @@ let
       "-DCMAKE_CXX_FLAGS=-std=c++11"
       "-DCLANGD_BUILD_XPC=OFF"
       "-DLLVM_ENABLE_RTTI=ON"
-      "-DLLVM_CONFIG_PATH=${libllvm.dev}/bin/llvm-config${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "-native"}"
     ] ++ lib.optionals enableManpages [
       "-DCLANG_INCLUDE_DOCS=ON"
       "-DLLVM_ENABLE_SPHINX=ON"
diff --git a/pkgs/development/compilers/llvm/8/default.nix b/pkgs/development/compilers/llvm/8/default.nix
index 7252b75a33974..43050a72b922b 100644
--- a/pkgs/development/compilers/llvm/8/default.nix
+++ b/pkgs/development/compilers/llvm/8/default.nix
@@ -97,7 +97,11 @@ let
       python3 = pkgs.python3;  # don't use python-boot
     });
 
-    clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang;
+    # pick clang appropriate for package set we are targeting
+    clang =
+      /**/ if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
+      else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
+      else tools.libcxxClang;
 
     libstdcxxClang = wrapCCWith rec {
       cc = tools.clang-unwrapped;
diff --git a/pkgs/development/compilers/llvm/8/llvm/default.nix b/pkgs/development/compilers/llvm/8/llvm/default.nix
index 8bb2293f81899..efd1707eb3378 100644
--- a/pkgs/development/compilers/llvm/8/llvm/default.nix
+++ b/pkgs/development/compilers/llvm/8/llvm/default.nix
@@ -30,7 +30,7 @@ let
   shortVersion = with lib;
     concatStringsSep "." (take 1 (splitVersion release_version));
 
-in stdenv.mkDerivation ({
+in stdenv.mkDerivation (rec {
   pname = "llvm";
   inherit version;
 
@@ -57,6 +57,12 @@ in stdenv.mkDerivation ({
   propagatedBuildInputs = [ ncurses zlib ];
 
   patches = [
+    # When cross-compiling we configure llvm-config-native with an approximation
+    # of the flags used for the normal LLVM build. To avoid the need for building
+    # a native libLLVM.so (which would fail) we force llvm-config to be linked
+    # statically against the necessary LLVM components always.
+    ../../llvm-config-link-static.patch
+
     # Fix missing includes for GCC 10
     (fetchpatch {
       url = "https://bugs.gentoo.org/attachment.cgi?id=612792";
@@ -85,11 +91,6 @@ in stdenv.mkDerivation ({
     substituteInPlace cmake/modules/AddLLVM.cmake \
       --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \
       --replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}" ''${extra_libdir})' ""
-  ''
-  # Patch llvm-config to return correct library path based on --link-{shared,static}.
-  + optionalString (enableSharedLibraries) ''
-    substitute '${./outputs.patch}' ./outputs.patch --subst-var lib
-    patch -p1 < ./outputs.patch
   '' + ''
     # FileSystem permissions tests fail with various special bits
     substituteInPlace unittests/Support/CMakeLists.txt \
@@ -104,6 +105,32 @@ in stdenv.mkDerivation ({
     rm test/CodeGen/AArch64/wineh4.mir
   '' + ''
     patchShebangs test/BugPoint/compile-custom.ll.py
+  '' + ''
+    # Tweak tests to ignore namespace part of type to support
+    # gcc-12: https://gcc.gnu.org/PR103598.
+    # The change below mangles strings like:
+    #    CHECK-NEXT: Starting llvm::Function pass manager run.
+    # to:
+    #    CHECK-NEXT: Starting {{.*}}Function pass manager run.
+    for f in \
+      test/Other/new-pass-manager.ll \
+      test/Other/new-pm-defaults.ll \
+      test/Other/new-pm-lto-defaults.ll \
+      test/Other/new-pm-thinlto-defaults.ll \
+      test/Other/pass-pipeline-parsing.ll \
+      test/Transforms/Inline/cgscc-incremental-invalidate.ll \
+      test/Transforms/Inline/clear-analyses.ll \
+      test/Transforms/LoopUnroll/unroll-loop-invalidation.ll \
+      test/Transforms/SCCP/ipsccp-preserve-analysis.ll \
+      test/Transforms/SCCP/preserve-analysis.ll \
+      test/Transforms/SROA/dead-inst.ll \
+      test/tools/gold/X86/new-pm.ll \
+      ; do
+      echo "PATCH: $f"
+      substituteInPlace $f \
+        --replace 'Starting llvm::' 'Starting {{.*}}' \
+        --replace 'Finished llvm::' 'Finished {{.*}}'
+    done
   '';
 
   # hacky fix: created binaries need to be run before installation
@@ -112,18 +139,28 @@ in stdenv.mkDerivation ({
     ln -sv $PWD/lib $out
   '';
 
-  cmakeFlags = with stdenv; [
-    "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+  cmakeFlags = with stdenv; let
+    # These flags influence llvm-config's BuildVariables.inc in addition to the
+    # general build. We need to make sure these are also passed via
+    # CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native
+    # will return different results from the cross llvm-config.
+    #
+    # Some flags don't need to be repassed because LLVM already does so (like
+    # CMAKE_BUILD_TYPE), others are irrelevant to the result.
+    flagsForLlvmConfig = [
+      "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+      "-DLLVM_ENABLE_RTTI=ON"
+    ] ++ optionals enableSharedLibraries [
+      "-DLLVM_LINK_LLVM_DYLIB=ON"
+    ];
+  in flagsForLlvmConfig ++ [
     "-DCMAKE_BUILD_TYPE=${if debugVersion then "Debug" else "Release"}"
     "-DLLVM_INSTALL_UTILS=ON"  # Needed by rustc
-    "-DLLVM_BUILD_TESTS=ON"
+    "-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}"
     "-DLLVM_ENABLE_FFI=ON"
-    "-DLLVM_ENABLE_RTTI=ON"
     "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_ENABLE_DUMP=ON"
-  ] ++ optionals enableSharedLibraries [
-    "-DLLVM_LINK_LLVM_DYLIB=ON"
   ] ++ optionals enableManpages [
     "-DLLVM_BUILD_DOCS=ON"
     "-DLLVM_ENABLE_SPHINX=ON"
@@ -149,7 +186,21 @@ in stdenv.mkDerivation ({
           "-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip"
           "-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib"
         ];
-      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list=${lib.concatStringsSep ";" nativeToolchainFlags}"
+        # We need to repass the custom GNUInstallDirs values, otherwise CMake
+        # will choose them for us, leading to wrong results in llvm-config-native
+        nativeInstallFlags = [
+          "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
+          "-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin"
+          "-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include"
+          "-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib"
+          "-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec"
+        ];
+      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list="
+      + lib.concatStringsSep ";" (lib.concatLists [
+        flagsForLlvmConfig
+        nativeToolchainFlags
+        nativeInstallFlags
+      ])
     )
   ];
 
@@ -179,7 +230,8 @@ in stdenv.mkDerivation ({
     cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native
   '';
 
-  doCheck = stdenv.isLinux && (!stdenv.isx86_32);
+  doCheck = stdenv.isLinux && (!stdenv.isx86_32)
+    && (stdenv.hostPlatform == stdenv.buildPlatform);
 
   checkTarget = "check-all";
 
diff --git a/pkgs/development/compilers/llvm/8/llvm/outputs.patch b/pkgs/development/compilers/llvm/8/llvm/outputs.patch
deleted file mode 100644
index 40096fa3497fd..0000000000000
--- a/pkgs/development/compilers/llvm/8/llvm/outputs.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
-index 94d426b..37f7794 100644
---- a/tools/llvm-config/llvm-config.cpp
-+++ b/tools/llvm-config/llvm-config.cpp
-@@ -333,6 +333,21 @@ int main(int argc, char **argv) {
-     ActiveIncludeOption = "-I" + ActiveIncludeDir;
-   }
- 
-+  /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared
-+  if (!IsInDevelopmentTree) {
-+    bool WantShared = true;
-+    for (int i = 1; i < argc; ++i) {
-+      StringRef Arg = argv[i];
-+      if (Arg == "--link-shared")
-+        WantShared = true;
-+      else if (Arg == "--link-static")
-+        WantShared = false; // the last one wins
-+    }
-+
-+    if (WantShared)
-+      ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
-+  }
-+
-   /// We only use `shared library` mode in cases where the static library form
-   /// of the components provided are not available; note however that this is
-   /// skipped if we're run from within the build dir. However, once installed,
diff --git a/pkgs/development/compilers/llvm/9/clang/default.nix b/pkgs/development/compilers/llvm/9/clang/default.nix
index c98b4a830c422..ee124b43bfce7 100644
--- a/pkgs/development/compilers/llvm/9/clang/default.nix
+++ b/pkgs/development/compilers/llvm/9/clang/default.nix
@@ -30,7 +30,6 @@ let
       "-DCMAKE_CXX_FLAGS=-std=c++11"
       "-DCLANGD_BUILD_XPC=OFF"
       "-DLLVM_ENABLE_RTTI=ON"
-      "-DLLVM_CONFIG_PATH=${libllvm.dev}/bin/llvm-config${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "-native"}"
     ] ++ lib.optionals enableManpages [
       "-DCLANG_INCLUDE_DOCS=ON"
       "-DLLVM_ENABLE_SPHINX=ON"
diff --git a/pkgs/development/compilers/llvm/9/default.nix b/pkgs/development/compilers/llvm/9/default.nix
index 9126a614b106b..7efe8486a387b 100644
--- a/pkgs/development/compilers/llvm/9/default.nix
+++ b/pkgs/development/compilers/llvm/9/default.nix
@@ -97,7 +97,11 @@ let
       python3 = pkgs.python3;  # don't use python-boot
     });
 
-    clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang;
+    # pick clang appropriate for package set we are targeting
+    clang =
+      /**/ if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
+      else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
+      else tools.libcxxClang;
 
     libstdcxxClang = wrapCCWith rec {
       cc = tools.clang-unwrapped;
diff --git a/pkgs/development/compilers/llvm/9/llvm/default.nix b/pkgs/development/compilers/llvm/9/llvm/default.nix
index f8c474775e48c..1dd1455ed6d69 100644
--- a/pkgs/development/compilers/llvm/9/llvm/default.nix
+++ b/pkgs/development/compilers/llvm/9/llvm/default.nix
@@ -57,6 +57,12 @@ in stdenv.mkDerivation (rec {
   propagatedBuildInputs = [ ncurses zlib ];
 
   patches = [
+    # When cross-compiling we configure llvm-config-native with an approximation
+    # of the flags used for the normal LLVM build. To avoid the need for building
+    # a native libLLVM.so (which would fail) we force llvm-config to be linked
+    # statically against the necessary LLVM components always.
+    ../../llvm-config-link-static.patch
+
     ./gnu-install-dirs.patch
     # Force a test to evaluate the saved benchmark for a CPU for which LLVM has
     # an execution model. See NixOS/nixpkgs#119673.
@@ -83,11 +89,6 @@ in stdenv.mkDerivation (rec {
     substituteInPlace cmake/modules/AddLLVM.cmake \
       --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \
       --replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}" ''${extra_libdir})' ""
-  ''
-  # Patch llvm-config to return correct library path based on --link-{shared,static}.
-  + optionalString (enableSharedLibraries) ''
-    substitute '${./outputs.patch}' ./outputs.patch --subst-var lib
-    patch -p1 < ./outputs.patch
   '' + ''
     # FileSystem permissions tests fail with various special bits
     substituteInPlace unittests/Support/CMakeLists.txt \
@@ -119,6 +120,32 @@ in stdenv.mkDerivation (rec {
     # Fix x86 gold test on non-x86 platforms
     # (similar fix made to others in this directory previously, FWIW)
     patch -p1 -i  ${./fix-test-on-non-x86-like-others.patch}
+  '' + ''
+    # Tweak tests to ignore namespace part of type to support
+    # gcc-12: https://gcc.gnu.org/PR103598.
+    # The change below mangles strings like:
+    #    CHECK-NEXT: Starting llvm::Function pass manager run.
+    # to:
+    #    CHECK-NEXT: Starting {{.*}}Function pass manager run.
+    for f in \
+      test/Other/new-pass-manager.ll \
+      test/Other/new-pm-defaults.ll \
+      test/Other/new-pm-lto-defaults.ll \
+      test/Other/new-pm-thinlto-defaults.ll \
+      test/Other/pass-pipeline-parsing.ll \
+      test/Transforms/Inline/cgscc-incremental-invalidate.ll \
+      test/Transforms/Inline/clear-analyses.ll \
+      test/Transforms/LoopUnroll/unroll-loop-invalidation.ll \
+      test/Transforms/SCCP/ipsccp-preserve-analysis.ll \
+      test/Transforms/SCCP/preserve-analysis.ll \
+      test/Transforms/SROA/dead-inst.ll \
+      test/tools/gold/X86/new-pm.ll \
+      ; do
+      echo "PATCH: $f"
+      substituteInPlace $f \
+        --replace 'Starting llvm::' 'Starting {{.*}}' \
+        --replace 'Finished llvm::' 'Finished {{.*}}'
+    done
   '';
 
   # hacky fix: created binaries need to be run before installation
@@ -127,18 +154,28 @@ in stdenv.mkDerivation (rec {
     ln -sv $PWD/lib $out
   '';
 
-  cmakeFlags = with stdenv; [
-    "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+  cmakeFlags = with stdenv; let
+    # These flags influence llvm-config's BuildVariables.inc in addition to the
+    # general build. We need to make sure these are also passed via
+    # CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native
+    # will return different results from the cross llvm-config.
+    #
+    # Some flags don't need to be repassed because LLVM already does so (like
+    # CMAKE_BUILD_TYPE), others are irrelevant to the result.
+    flagsForLlvmConfig = [
+      "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+      "-DLLVM_ENABLE_RTTI=ON"
+    ] ++ optionals enableSharedLibraries [
+      "-DLLVM_LINK_LLVM_DYLIB=ON"
+    ];
+  in flagsForLlvmConfig ++ [
     "-DCMAKE_BUILD_TYPE=${if debugVersion then "Debug" else "Release"}"
     "-DLLVM_INSTALL_UTILS=ON"  # Needed by rustc
-    "-DLLVM_BUILD_TESTS=ON"
+    "-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}"
     "-DLLVM_ENABLE_FFI=ON"
-    "-DLLVM_ENABLE_RTTI=ON"
     "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_ENABLE_DUMP=ON"
-  ] ++ optionals enableSharedLibraries [
-    "-DLLVM_LINK_LLVM_DYLIB=ON"
   ] ++ optionals enableManpages [
     "-DLLVM_BUILD_DOCS=ON"
     "-DLLVM_ENABLE_SPHINX=ON"
@@ -164,7 +201,21 @@ in stdenv.mkDerivation (rec {
           "-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip"
           "-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib"
         ];
-      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list=${lib.concatStringsSep ";" nativeToolchainFlags}"
+        # We need to repass the custom GNUInstallDirs values, otherwise CMake
+        # will choose them for us, leading to wrong results in llvm-config-native
+        nativeInstallFlags = [
+          "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
+          "-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin"
+          "-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include"
+          "-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib"
+          "-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec"
+        ];
+      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list="
+      + lib.concatStringsSep ";" (lib.concatLists [
+        flagsForLlvmConfig
+        nativeToolchainFlags
+        nativeInstallFlags
+      ])
     )
   ];
 
@@ -194,7 +245,8 @@ in stdenv.mkDerivation (rec {
     cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native
   '';
 
-  doCheck = stdenv.isLinux && (!stdenv.isx86_32) && (!stdenv.hostPlatform.isRiscV);
+  doCheck = stdenv.isLinux && (!stdenv.isx86_32) && (!stdenv.hostPlatform.isRiscV)
+    && (stdenv.hostPlatform == stdenv.buildPlatform);
 
   checkTarget = "check-all";
 
diff --git a/pkgs/development/compilers/llvm/9/llvm/outputs.patch b/pkgs/development/compilers/llvm/9/llvm/outputs.patch
deleted file mode 100644
index 40096fa3497fd..0000000000000
--- a/pkgs/development/compilers/llvm/9/llvm/outputs.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
-index 94d426b..37f7794 100644
---- a/tools/llvm-config/llvm-config.cpp
-+++ b/tools/llvm-config/llvm-config.cpp
-@@ -333,6 +333,21 @@ int main(int argc, char **argv) {
-     ActiveIncludeOption = "-I" + ActiveIncludeDir;
-   }
- 
-+  /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared
-+  if (!IsInDevelopmentTree) {
-+    bool WantShared = true;
-+    for (int i = 1; i < argc; ++i) {
-+      StringRef Arg = argv[i];
-+      if (Arg == "--link-shared")
-+        WantShared = true;
-+      else if (Arg == "--link-static")
-+        WantShared = false; // the last one wins
-+    }
-+
-+    if (WantShared)
-+      ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
-+  }
-+
-   /// We only use `shared library` mode in cases where the static library form
-   /// of the components provided are not available; note however that this is
-   /// skipped if we're run from within the build dir. However, once installed,
diff --git a/pkgs/development/compilers/llvm/git/clang/default.nix b/pkgs/development/compilers/llvm/git/clang/default.nix
index a775af3031b7f..3873bda2b6d5d 100644
--- a/pkgs/development/compilers/llvm/git/clang/default.nix
+++ b/pkgs/development/compilers/llvm/git/clang/default.nix
@@ -21,7 +21,7 @@ let
     cmakeFlags = [
       "-DCMAKE_CXX_FLAGS=-std=c++14"
       "-DCLANGD_BUILD_XPC=OFF"
-      "-DLLVM_CONFIG_PATH=${libllvm.dev}/bin/llvm-config${lib.optionalString (stdenv.hostPlatform != stdenv.buildPlatform) "-native"}"
+      "-DLLVM_ENABLE_RTTI=ON"
     ] ++ lib.optionals enableManpages [
       "-DCLANG_INCLUDE_DOCS=ON"
       "-DLLVM_ENABLE_SPHINX=ON"
diff --git a/pkgs/development/compilers/llvm/git/compiler-rt/default.nix b/pkgs/development/compilers/llvm/git/compiler-rt/default.nix
index 5874a91e03c8b..019148039d175 100644
--- a/pkgs/development/compilers/llvm/git/compiler-rt/default.nix
+++ b/pkgs/development/compilers/llvm/git/compiler-rt/default.nix
@@ -32,6 +32,8 @@ stdenv.mkDerivation {
     "-DCOMPILER_RT_BUILD_XRAY=OFF"
     "-DCOMPILER_RT_BUILD_LIBFUZZER=OFF"
     "-DCOMPILER_RT_BUILD_PROFILE=OFF"
+    "-DCOMPILER_RT_BUILD_MEMPROF=OFF"
+    "-DCOMPILER_RT_BUILD_ORC=OFF" # may be possible to build with musl if necessary
   ] ++ lib.optionals ((useLLVM || bareMetal) && !haveLibc) [
     "-DCMAKE_C_COMPILER_WORKS=ON"
     "-DCMAKE_CXX_COMPILER_WORKS=ON"
diff --git a/pkgs/development/compilers/llvm/git/default.nix b/pkgs/development/compilers/llvm/git/default.nix
index 666e9be3cd89e..890270c851dbc 100644
--- a/pkgs/development/compilers/llvm/git/default.nix
+++ b/pkgs/development/compilers/llvm/git/default.nix
@@ -93,7 +93,11 @@ let
     #   python3 = pkgs.python3;  # don't use python-boot
     # });
 
-    clang = if stdenv.cc.isGNU then tools.libstdcxxClang else tools.libcxxClang;
+    # pick clang appropriate for package set we are targeting
+    clang =
+      /**/ if stdenv.targetPlatform.useLLVM or false then tools.clangUseLLVM
+      else if (pkgs.targetPackages.stdenv or stdenv).cc.isGNU then tools.libstdcxxClang
+      else tools.libcxxClang;
 
     libstdcxxClang = wrapCCWith rec {
       cc = tools.clang-unwrapped;
diff --git a/pkgs/development/compilers/llvm/git/libcxx/default.nix b/pkgs/development/compilers/llvm/git/libcxx/default.nix
index bedfd5afee150..0ddf28909b8e8 100644
--- a/pkgs/development/compilers/llvm/git/libcxx/default.nix
+++ b/pkgs/development/compilers/llvm/git/libcxx/default.nix
@@ -25,12 +25,6 @@ stdenv.mkDerivation rec {
     ../../libcxx-0001-musl-hacks.patch
   ];
 
-  # Prevent errors like "error: 'foo' is unavailable: introduced in macOS yy.zz"
-  postPatch = ''
-    substituteInPlace include/__config \
-      --replace "#    define _LIBCPP_USE_AVAILABILITY_APPLE" ""
-  '';
-
   preConfigure = lib.optionalString stdenv.hostPlatform.isMusl ''
     patchShebangs utils/cat_files.py
   '';
diff --git a/pkgs/development/compilers/llvm/git/llvm/default.nix b/pkgs/development/compilers/llvm/git/llvm/default.nix
index daf4cfe808b6c..fc7030810c5bd 100644
--- a/pkgs/development/compilers/llvm/git/llvm/default.nix
+++ b/pkgs/development/compilers/llvm/git/llvm/default.nix
@@ -51,6 +51,12 @@ in stdenv.mkDerivation (rec {
   checkInputs = [ which ];
 
   patches = [
+    # When cross-compiling we configure llvm-config-native with an approximation
+    # of the flags used for the normal LLVM build. To avoid the need for building
+    # a native libLLVM.so (which would fail) we force llvm-config to be linked
+    # statically against the necessary LLVM components always.
+    ../../llvm-config-link-static.patch
+
     ./gnu-install-dirs.patch
   ] ++ lib.optional enablePolly ./gnu-install-dirs-polly.patch;
 
@@ -58,11 +64,6 @@ in stdenv.mkDerivation (rec {
     substituteInPlace cmake/modules/AddLLVM.cmake \
       --replace 'set(_install_name_dir INSTALL_NAME_DIR "@rpath")' "set(_install_name_dir)" \
       --replace 'set(_install_rpath "@loader_path/../''${CMAKE_INSTALL_LIBDIR}''${LLVM_LIBDIR_SUFFIX}" ''${extra_libdir})' ""
-  ''
-  # Patch llvm-config to return correct library path based on --link-{shared,static}.
-  + optionalString (enableSharedLibraries) ''
-    substitute '${./outputs.patch}' ./outputs.patch --subst-var lib
-    patch -p1 < ./outputs.patch
   '' + ''
     # FileSystem permissions tests fail with various special bits
     substituteInPlace unittests/Support/CMakeLists.txt \
@@ -101,18 +102,36 @@ in stdenv.mkDerivation (rec {
   # E.g. mesa.drivers use the build-id as a cache key (see #93946):
   LDFLAGS = optionalString (enableSharedLibraries && !stdenv.isDarwin) "-Wl,--build-id=sha1";
 
-  cmakeFlags = with stdenv; [
-    "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+  cmakeFlags = with stdenv; let
+    # These flags influence llvm-config's BuildVariables.inc in addition to the
+    # general build. We need to make sure these are also passed via
+    # CROSS_TOOLCHAIN_FLAGS_NATIVE when cross-compiling or llvm-config-native
+    # will return different results from the cross llvm-config.
+    #
+    # Some flags don't need to be repassed because LLVM already does so (like
+    # CMAKE_BUILD_TYPE), others are irrelevant to the result.
+    flagsForLlvmConfig = [
+      "-DLLVM_INSTALL_CMAKE_DIR=${placeholder "dev"}/lib/cmake/llvm/"
+      "-DLLVM_ENABLE_RTTI=ON"
+    ] ++ optionals enableSharedLibraries [
+      "-DLLVM_LINK_LLVM_DYLIB=ON"
+    ];
+  in flagsForLlvmConfig ++ [
     "-DCMAKE_BUILD_TYPE=${if debugVersion then "Debug" else "Release"}"
     "-DLLVM_INSTALL_UTILS=ON"  # Needed by rustc
-    "-DLLVM_BUILD_TESTS=ON"
+    "-DLLVM_BUILD_TESTS=${if doCheck then "ON" else "OFF"}"
     "-DLLVM_ENABLE_FFI=ON"
-    "-DLLVM_ENABLE_RTTI=ON"
     "-DLLVM_HOST_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_DEFAULT_TARGET_TRIPLE=${stdenv.hostPlatform.config}"
     "-DLLVM_ENABLE_DUMP=ON"
-  ] ++ optionals enableSharedLibraries [
-    "-DLLVM_LINK_LLVM_DYLIB=ON"
+  ] ++ optionals stdenv.hostPlatform.isStatic [
+    # Disables building of shared libs, -fPIC is still injected by cc-wrapper
+    "-DLLVM_ENABLE_PIC=OFF"
+    "-DLLVM_BUILD_STATIC=ON"
+    # libxml2 needs to be disabled because the LLVM build system ignores its .la
+    # file and doesn't link zlib as well.
+    # https://github.com/ClangBuiltLinux/tc-build/issues/150#issuecomment-845418812
+    "-DLLVM_ENABLE_LIBXML2=OFF"
   ] ++ optionals enableManpages [
     "-DLLVM_BUILD_DOCS=ON"
     "-DLLVM_ENABLE_SPHINX=ON"
@@ -138,7 +157,21 @@ in stdenv.mkDerivation (rec {
           "-DCMAKE_STRIP=${nativeBintools}/bin/${nativeBintools.targetPrefix}strip"
           "-DCMAKE_RANLIB=${nativeBintools}/bin/${nativeBintools.targetPrefix}ranlib"
         ];
-      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list=${lib.concatStringsSep ";" nativeToolchainFlags}"
+        # We need to repass the custom GNUInstallDirs values, otherwise CMake
+        # will choose them for us, leading to wrong results in llvm-config-native
+        nativeInstallFlags = [
+          "-DCMAKE_INSTALL_PREFIX=${placeholder "out"}"
+          "-DCMAKE_INSTALL_BINDIR=${placeholder "out"}/bin"
+          "-DCMAKE_INSTALL_INCLUDEDIR=${placeholder "dev"}/include"
+          "-DCMAKE_INSTALL_LIBDIR=${placeholder "lib"}/lib"
+          "-DCMAKE_INSTALL_LIBEXECDIR=${placeholder "lib"}/libexec"
+        ];
+      in "-DCROSS_TOOLCHAIN_FLAGS_NATIVE:list="
+      + lib.concatStringsSep ";" (lib.concatLists [
+        flagsForLlvmConfig
+        nativeToolchainFlags
+        nativeInstallFlags
+      ])
     )
   ];
 
@@ -168,7 +201,8 @@ in stdenv.mkDerivation (rec {
     cp NATIVE/bin/llvm-config $dev/bin/llvm-config-native
   '';
 
-  doCheck = stdenv.isLinux && (!stdenv.isx86_32) && (!stdenv.hostPlatform.isMusl);
+  doCheck = stdenv.isLinux && (!stdenv.isx86_32) && (!stdenv.hostPlatform.isMusl)
+    && (stdenv.hostPlatform == stdenv.buildPlatform);
 
   checkTarget = "check-all";
 
diff --git a/pkgs/development/compilers/llvm/git/llvm/outputs.patch b/pkgs/development/compilers/llvm/git/llvm/outputs.patch
deleted file mode 100644
index 40096fa3497fd..0000000000000
--- a/pkgs/development/compilers/llvm/git/llvm/outputs.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.cpp
-index 94d426b..37f7794 100644
---- a/tools/llvm-config/llvm-config.cpp
-+++ b/tools/llvm-config/llvm-config.cpp
-@@ -333,6 +333,21 @@ int main(int argc, char **argv) {
-     ActiveIncludeOption = "-I" + ActiveIncludeDir;
-   }
- 
-+  /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared
-+  if (!IsInDevelopmentTree) {
-+    bool WantShared = true;
-+    for (int i = 1; i < argc; ++i) {
-+      StringRef Arg = argv[i];
-+      if (Arg == "--link-shared")
-+        WantShared = true;
-+      else if (Arg == "--link-static")
-+        WantShared = false; // the last one wins
-+    }
-+
-+    if (WantShared)
-+      ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
-+  }
-+
-   /// We only use `shared library` mode in cases where the static library form
-   /// of the components provided are not available; note however that this is
-   /// skipped if we're run from within the build dir. However, once installed,
diff --git a/pkgs/development/compilers/llvm/llvm-config-link-static.patch b/pkgs/development/compilers/llvm/llvm-config-link-static.patch
new file mode 100644
index 0000000000000..3881cc5206e27
--- /dev/null
+++ b/pkgs/development/compilers/llvm/llvm-config-link-static.patch
@@ -0,0 +1,12 @@
+diff --git llvm/tools/llvm-config/CMakeLists.txt llvm/tools/llvm-config/CMakeLists.txt
+index 16ba54c0cf2f..20b017195e84 100644
+--- llvm/tools/llvm-config/CMakeLists.txt
++++ llvm/tools/llvm-config/CMakeLists.txt
+@@ -6,6 +6,7 @@ set(BUILDVARIABLES_OBJPATH ${CMAKE_CURRENT_BINARY_DIR}/BuildVariables.inc)
+ # Add the llvm-config tool.
+ add_llvm_tool(llvm-config
+   llvm-config.cpp
++  DISABLE_LLVM_LINK_LLVM_DYLIB
+   )
+ 
+ # Compute the substitution values for various items.
diff --git a/pkgs/development/compilers/llvm/rocm/llvm/outputs.patch b/pkgs/development/compilers/llvm/rocm/llvm/outputs.patch
index 40096fa3497fd..878460e05b8af 100644
--- a/pkgs/development/compilers/llvm/rocm/llvm/outputs.patch
+++ b/pkgs/development/compilers/llvm/rocm/llvm/outputs.patch
@@ -2,23 +2,13 @@ diff --git a/tools/llvm-config/llvm-config.cpp b/tools/llvm-config/llvm-config.c
 index 94d426b..37f7794 100644
 --- a/tools/llvm-config/llvm-config.cpp
 +++ b/tools/llvm-config/llvm-config.cpp
-@@ -333,6 +333,21 @@ int main(int argc, char **argv) {
+@@ -333,6 +333,11 @@ int main(int argc, char **argv) {
      ActiveIncludeOption = "-I" + ActiveIncludeDir;
    }
  
-+  /// Nix-specific multiple-output handling: override ActiveLibDir if --link-shared
++  /// Nix-specific multiple-output handling: override ActiveLibDir
 +  if (!IsInDevelopmentTree) {
-+    bool WantShared = true;
-+    for (int i = 1; i < argc; ++i) {
-+      StringRef Arg = argv[i];
-+      if (Arg == "--link-shared")
-+        WantShared = true;
-+      else if (Arg == "--link-static")
-+        WantShared = false; // the last one wins
-+    }
-+
-+    if (WantShared)
-+      ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
++    ActiveLibDir = std::string("@lib@") + "/lib" + LLVM_LIBDIR_SUFFIX;
 +  }
 +
    /// We only use `shared library` mode in cases where the static library form