From ca59a201ca1dfe77bdd5b6ce98b7ac75142549d2 Mon Sep 17 00:00:00 2001 From: Rahul Butani Date: Fri, 7 Oct 2022 15:22:55 -0500 Subject: [PATCH] llvmPackages_15.libcxx: use clang 15 instead of the stdenv's compiler libc++ has switched to using `__attribute__((using_if_exists))` to handle incomplete libc implementations; see: https://github.com/llvm/llvm-project/commit/a9c9183ca42629fa83cdda297d1d30c7bc1d7c91 These essentially require a modern C++ compiler (clang gained support in LLVM 13: https://github.com/llvm/llvm-project/commit/369c64839946d89cf5697550b6feeea031b2f270, gcc appears to not have support yet: https://gcc.gnu.org/bugzilla//show_bug.cgi?id=105584). Previously this was not an issue for us (despite the transition happening around LLVM 13) but something about the changes to the libc++/libc++-abi build has made it so that on platforms with incomplete libc impls (i.e. Darwin is missing `quick_exit`/`at_quick_exit`) we error during the `libcxx-abi` build when the stdenv's (older, not supporting `using_if_exists`) compiler tries to import libc symbols that aren't present. The libc++ docs suggest we use a modern compiler to build libc++ anyways (https://releases.llvm.org/15.0.0/projects/libcxx/docs/index.html#platform-and-compiler-support) so this commit uses stdenv's containing the package set's clang to build libcxx/libcxx-abi. This is similar to how libc++ bootstrapping builds (https://releases.llvm.org/15.0.0/projects/libcxx/docs/BuildingLibcxx.html#bootstrapping-build) work. --- .../development/compilers/llvm/15/default.nix | 34 +++++++++++++------ .../compilers/llvm/15/libcxxabi/default.nix | 7 ++++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/pkgs/development/compilers/llvm/15/default.nix b/pkgs/development/compilers/llvm/15/default.nix index 964ec5acd58d..d9b117ee2343 100644 --- a/pkgs/development/compilers/llvm/15/default.nix +++ b/pkgs/development/compilers/llvm/15/default.nix @@ -247,27 +247,39 @@ let libcxxStdenv = overrideCC stdenv buildLlvmTools.libcxxClang; - libcxx = callPackage ./libcxx { - inherit llvm_meta; - stdenv = if stdenv.hostPlatform.useLLVM or false - then overrideCC stdenv buildLlvmTools.clangNoLibcxx - else stdenv; - }; - libcxxabi = let - stdenv_ = if stdenv.hostPlatform.useLLVM or false - then overrideCC stdenv buildLlvmTools.clangNoLibcxx - else stdenv; + # CMake will "require" a compiler capable of compiling C++ programs + # cxx-header's build does not actually use one so it doesn't really matter + # what stdenv we use here, as long as CMake is happy. cxx-headers = callPackage ./libcxx { inherit llvm_meta; - stdenv = stdenv_; headersOnly = true; }; + + # `libcxxabi` *doesn't* need a compiler with a working C++ stdlib but it + # *does* need a relatively modern C++ compiler (see: + # https://releases.llvm.org/15.0.0/projects/libcxx/docs/index.html#platform-and-compiler-support). + # + # So, we use the clang from this LLVM package set, like libc++ + # "boostrapping builds" do: + # https://releases.llvm.org/15.0.0/projects/libcxx/docs/BuildingLibcxx.html#bootstrapping-build + # + # We cannot use `clangNoLibcxx` because that contains `compiler-rt` which, + # on macOS, depends on `libcxxabi`, thus forming a cycle. + stdenv_ = overrideCC stdenv buildLlvmTools.clangNoCompilerRtWithLibc; in callPackage ./libcxxabi { stdenv = stdenv_; inherit llvm_meta cxx-headers; }; + # Like `libcxxabi` above, `libcxx` requires a fairly modern C++ compiler, + # so: we use the clang from this LLVM package set instead of the regular + # stdenv's compiler. + libcxx = callPackage ./libcxx { + inherit llvm_meta; + stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcxx; + }; + libunwind = callPackage ./libunwind { inherit llvm_meta; stdenv = overrideCC stdenv buildLlvmTools.clangNoLibcxx; diff --git a/pkgs/development/compilers/llvm/15/libcxxabi/default.nix b/pkgs/development/compilers/llvm/15/libcxxabi/default.nix index 22fbcc67c935..ea9f7cb0772e 100644 --- a/pkgs/development/compilers/llvm/15/libcxxabi/default.nix +++ b/pkgs/development/compilers/llvm/15/libcxxabi/default.nix @@ -58,6 +58,13 @@ stdenv.mkDerivation rec { cmakeFlags = [ "-DLLVM_ENABLE_RUNTIMES=libcxxabi" "-DLIBCXXABI_LIBCXX_INCLUDES=${cxx-headers}/include/c++/v1" + + # `libcxxabi`'s build does not need a toolchain with a c++ stdlib attached + # (we specify the headers it should use explicitly above). + # + # CMake however checks for this anyways; this flag tells it not to. See: + # https://github.com/llvm/llvm-project/blob/4bd3f3759259548e159aeba5c76efb9a0864e6fa/llvm/runtimes/CMakeLists.txt#L243 + "-DCMAKE_CXX_COMPILER_WORKS=ON" ] ++ lib.optionals (stdenv.hostPlatform.useLLVM or false) [ "-DLLVM_ENABLE_LIBCXX=ON" "-DLIBCXXABI_USE_LLVM_UNWINDER=ON"