From 65709c96d7596101330603ee469067a595104e05 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Tue, 2 Dec 2025 08:25:02 -0500 Subject: [PATCH 1/4] [clang][Darwin] Prefer the toolchain-provided libc++.dylib if there is one When libc++ is bootstrapped with clang, the resulting clang uses the just-built libcxx headers from /bin/../include/c++/v1. However, before this patch, clang would still use the system-provided libc++.dylib (usually in the Apple SDK) because it would fail to add the corresponding linker flag to find the just-built libc++. After this patch, Clang will also add `-L /bin/../lib` to the linker search paths, which will allow the just-built libc++.dylib to be found. Fixes #77653 rdar://107060541 --- clang/lib/Driver/ToolChains/Darwin.cpp | 18 +++++++++ .../Driver/darwin-header-search-libcxx.cpp | 4 +- .../darwin-link-libcxx-from-toolchain.cpp | 39 +++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) create mode 100644 clang/test/Driver/darwin-link-libcxx-from-toolchain.cpp diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index fc3cd9030f71d..be17546c9c4ba 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -426,6 +426,24 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args, Args.AddAllArgs(CmdArgs, options::OPT_sub__library); Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella); + // Pass -L /bin/../lib/ to linker to prioritize the + // toolchain's libc++.dylib over the sysroot-provided one. This matches + // what we do for determining which libc++ headers to use. + // + // If the toolchain does not provide libc++.dylib, we will fall back to the + // normal system search paths for finding libc++.dylib (on Darwin, that would + // be in the SDK so we would find Apple's system libc++ instead of using + // LLVM's). + { + llvm::SmallString<128> InstallBinPath = + llvm::StringRef(D.Dir); // /bin + llvm::SmallString<128> InstallLibPath = InstallBinPath; + llvm::sys::path::append(InstallLibPath, "..", + "lib"); // /bin/../lib + CmdArgs.push_back("-L"); + CmdArgs.push_back(C.getArgs().MakeArgString(InstallLibPath)); + } + // Give --sysroot= preference, over the Apple specific behavior to also use // --isysroot as the syslibroot. // We check `OPT__sysroot_EQ` directly instead of `getSysRoot` to make sure we diff --git a/clang/test/Driver/darwin-header-search-libcxx.cpp b/clang/test/Driver/darwin-header-search-libcxx.cpp index cc8ec9ceb89b3..e8985a4e22b2f 100644 --- a/clang/test/Driver/darwin-header-search-libcxx.cpp +++ b/clang/test/Driver/darwin-header-search-libcxx.cpp @@ -92,7 +92,7 @@ // CHECK-LIBCXX-SYSROOT_AND_TOOLCHAIN-1: "-internal-isystem" "[[TOOLCHAIN]]/usr/bin/../include/c++/v1" // CHECK-LIBCXX-SYSROOT_AND_TOOLCHAIN-1-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1" -// Make sure that using -nostdinc, -nostdinc++ or -nostdlib will drop both the toolchain +// Make sure that using -nostdinc, -nostdinc++ or -nostdlibinc will drop both the toolchain // C++ include path and the sysroot one. // // RUN: %clang -### %s -fsyntax-only 2>&1 \ @@ -116,7 +116,7 @@ // RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ // RUN: -stdlib=platform \ // RUN: -nostdinc++ \ -// RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr \ +// RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ // RUN: -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ // RUN: --check-prefix=CHECK-LIBCXX-NOSTDINCXX %s // CHECK-LIBCXX-NOSTDINCXX: "-cc1" diff --git a/clang/test/Driver/darwin-link-libcxx-from-toolchain.cpp b/clang/test/Driver/darwin-link-libcxx-from-toolchain.cpp new file mode 100644 index 0000000000000..1d35a1c6bbc0f --- /dev/null +++ b/clang/test/Driver/darwin-link-libcxx-from-toolchain.cpp @@ -0,0 +1,39 @@ +// UNSUPPORTED: system-windows + +// Tests to check that we pass -L /bin/../lib/ to the linker to prioritize the toolchain's +// libc++.dylib over the system's libc++.dylib on Darwin. This matches the behavior we have for +// header search paths, where we prioritize toolchain headers and then fall back to the sysroot ones. + +// Check that we pass the right -L to the linker even when -stdlib=libc++ is not passed. +// +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ +// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain_no_libcxx \ +// RUN: --check-prefix=CHECK-1 %s +// +// CHECK-1: "/usr/bin/ld" +// CHECK-1: "-L" "[[TOOLCHAIN]]/usr/bin/../lib" + +// Check that we pass the right -L to the linker when -stdlib=libc++ is passed, both in the +// case where there is libc++.dylib in the toolchain and when there isn't. +// +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -stdlib=libc++ \ +// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ +// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain_no_libcxx \ +// RUN: --check-prefix=CHECK-2 %s +// +// CHECK-2: "/usr/bin/ld" +// CHECK-2: "-L" "[[TOOLCHAIN]]/usr/bin/../lib" +// +// RUN: %clang -### %s 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -stdlib=libc++ \ +// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ +// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ +// RUN: --check-prefix=CHECK-3 %s +// +// CHECK-3: "/usr/bin/ld" +// CHECK-3: "-L" "[[TOOLCHAIN]]/usr/bin/../lib" From b5e52e58873914f776482b907bb398c3945dd589 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 3 Dec 2025 08:53:03 -0500 Subject: [PATCH 2/4] Pass the specific library path instead, to avoid adding a new directory to -L --- clang/lib/Driver/ToolChains/Darwin.cpp | 62 +++++++++----- .../usr/lib/libc++.dylib | 0 .../usr/lib/libc++experimental.a | 0 .../usr/bin/.keep | 0 .../usr/include/c++/v1/.keep | 0 .../usr/lib/libc++.a | 0 .../usr/lib/libc++experimental.a | 0 .../darwin-link-libcxx-from-toolchain.cpp | 39 --------- clang/test/Driver/darwin-link-libcxx.cpp | 81 +++++++++++++++++++ .../test/Driver/experimental-library-flag.cpp | 8 +- 10 files changed, 127 insertions(+), 63 deletions(-) create mode 100644 clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++.dylib create mode 100644 clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++experimental.a create mode 100644 clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/bin/.keep create mode 100644 clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/include/c++/v1/.keep create mode 100644 clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++.a create mode 100644 clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++experimental.a delete mode 100644 clang/test/Driver/darwin-link-libcxx-from-toolchain.cpp create mode 100644 clang/test/Driver/darwin-link-libcxx.cpp diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index be17546c9c4ba..6665b54ca473d 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -426,24 +426,6 @@ void darwin::Linker::AddLinkArgs(Compilation &C, const ArgList &Args, Args.AddAllArgs(CmdArgs, options::OPT_sub__library); Args.AddAllArgs(CmdArgs, options::OPT_sub__umbrella); - // Pass -L /bin/../lib/ to linker to prioritize the - // toolchain's libc++.dylib over the sysroot-provided one. This matches - // what we do for determining which libc++ headers to use. - // - // If the toolchain does not provide libc++.dylib, we will fall back to the - // normal system search paths for finding libc++.dylib (on Darwin, that would - // be in the SDK so we would find Apple's system libc++ instead of using - // LLVM's). - { - llvm::SmallString<128> InstallBinPath = - llvm::StringRef(D.Dir); // /bin - llvm::SmallString<128> InstallLibPath = InstallBinPath; - llvm::sys::path::append(InstallLibPath, "..", - "lib"); // /bin/../lib - CmdArgs.push_back("-L"); - CmdArgs.push_back(C.getArgs().MakeArgString(InstallLibPath)); - } - // Give --sysroot= preference, over the Apple specific behavior to also use // --isysroot as the syslibroot. // We check `OPT__sysroot_EQ` directly instead of `getSysRoot` to make sure we @@ -2864,11 +2846,49 @@ void AppleMachO::AddCXXStdlibLibArgs(const ArgList &Args, CXXStdlibType Type = GetCXXStdlibType(Args); switch (Type) { - case ToolChain::CST_Libcxx: - CmdArgs.push_back("-lc++"); + case ToolChain::CST_Libcxx: { + // On Darwin, we prioritize a libc++ located in the toolchain to a libc++ + // located in the sysroot. Unlike the driver for most other platforms, on + // Darwin we do that by explicitly passing the library path to the linker + // to avoid having to add the toolchain's `lib/` directory to the linker + // search path, which would make other libraries findable as well. + // + // Prefering the toolchain library over the sysroot library matches the + // behavior we have for headers, where we prefer headers in the toolchain + // over headers in the sysroot if there are any. Note that it's important + // for the header search path behavior to match the link-time search path + // behavior to ensure that we link the program against a library that + // matches the headers that were used to compile it. + // + // Otherwise, we end up compiling against some set of headers and then + // linking against a different library (which, confusingly, shares the same + // name) which may have been configured with different options, be at a + // different version, etc. + SmallString<128> InstallLib = llvm::sys::path::parent_path(getDriver().Dir); + llvm::sys::path::append(InstallLib, "lib"); // /bin/../lib + auto Link = [&](StringRef Library) { + SmallString<128> Shared(InstallLib); + llvm::sys::path::append(Shared, + SmallString<4>("lib") + Library + ".dylib"); + SmallString<128> Static(InstallLib); + llvm::sys::path::append(Static, SmallString<4>("lib") + Library + ".a"); + SmallString<32> Relative("-l"); + Relative += Library; + + if (getVFS().exists(Shared)) { + CmdArgs.push_back(Args.MakeArgString(Shared)); + } else if (getVFS().exists(Static)) { + CmdArgs.push_back(Args.MakeArgString(Static)); + } else { + CmdArgs.push_back(Args.MakeArgString(Relative)); + } + }; + + Link("c++"); if (Args.hasArg(options::OPT_fexperimental_library)) - CmdArgs.push_back("-lc++experimental"); + Link("c++experimental"); break; + } case ToolChain::CST_Libstdcxx: // Unfortunately, -lstdc++ doesn't always exist in the standard search path; diff --git a/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++.dylib b/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++.dylib new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++experimental.a b/clang/test/Driver/Inputs/basic_darwin_toolchain/usr/lib/libc++experimental.a new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/bin/.keep b/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/bin/.keep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/include/c++/v1/.keep b/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/include/c++/v1/.keep new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++.a b/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++.a new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++experimental.a b/clang/test/Driver/Inputs/basic_darwin_toolchain_static/usr/lib/libc++experimental.a new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/clang/test/Driver/darwin-link-libcxx-from-toolchain.cpp b/clang/test/Driver/darwin-link-libcxx-from-toolchain.cpp deleted file mode 100644 index 1d35a1c6bbc0f..0000000000000 --- a/clang/test/Driver/darwin-link-libcxx-from-toolchain.cpp +++ /dev/null @@ -1,39 +0,0 @@ -// UNSUPPORTED: system-windows - -// Tests to check that we pass -L /bin/../lib/ to the linker to prioritize the toolchain's -// libc++.dylib over the system's libc++.dylib on Darwin. This matches the behavior we have for -// header search paths, where we prioritize toolchain headers and then fall back to the sysroot ones. - -// Check that we pass the right -L to the linker even when -stdlib=libc++ is not passed. -// -// RUN: %clang -### %s 2>&1 \ -// RUN: --target=x86_64-apple-darwin \ -// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ -// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain_no_libcxx \ -// RUN: --check-prefix=CHECK-1 %s -// -// CHECK-1: "/usr/bin/ld" -// CHECK-1: "-L" "[[TOOLCHAIN]]/usr/bin/../lib" - -// Check that we pass the right -L to the linker when -stdlib=libc++ is passed, both in the -// case where there is libc++.dylib in the toolchain and when there isn't. -// -// RUN: %clang -### %s 2>&1 \ -// RUN: --target=x86_64-apple-darwin \ -// RUN: -stdlib=libc++ \ -// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ -// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain_no_libcxx \ -// RUN: --check-prefix=CHECK-2 %s -// -// CHECK-2: "/usr/bin/ld" -// CHECK-2: "-L" "[[TOOLCHAIN]]/usr/bin/../lib" -// -// RUN: %clang -### %s 2>&1 \ -// RUN: --target=x86_64-apple-darwin \ -// RUN: -stdlib=libc++ \ -// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ -// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ -// RUN: --check-prefix=CHECK-3 %s -// -// CHECK-3: "/usr/bin/ld" -// CHECK-3: "-L" "[[TOOLCHAIN]]/usr/bin/../lib" diff --git a/clang/test/Driver/darwin-link-libcxx.cpp b/clang/test/Driver/darwin-link-libcxx.cpp new file mode 100644 index 0000000000000..1c4f31b257512 --- /dev/null +++ b/clang/test/Driver/darwin-link-libcxx.cpp @@ -0,0 +1,81 @@ +// UNSUPPORTED: system-windows + +// Tests to check that we link against the toolchain-provided libc++ built library when it is provided. +// This is required to prefer the toolchain's libc++ over the system's libc++, which matches the behavior +// we have for header search paths. + +// When libc++.dylib is NOT in the toolchain, we should use -lc++ and fall back to the libc++ +// in the sysroot. +// +// (1) Without -fexperimental-library. +// RUN: %clangxx -### %s 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ +// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain_no_libcxx \ +// RUN: --check-prefix=CHECK-1 %s +// CHECK-1: "/usr/bin/ld" +// CHECK-1: "-lc++" +// CHECK-1-NOT: "[[TOOLCHAIN]]/usr/lib" +// +// (2) With -fexperimental-library. +// RUN: %clangxx -### %s 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_no_libcxx/usr/bin \ +// RUN: -fexperimental-library \ +// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain_no_libcxx \ +// RUN: --check-prefix=CHECK-2 %s +// CHECK-2: "/usr/bin/ld" +// CHECK-2: "-lc++" "-lc++experimental" +// CHECK-2-NOT: "[[TOOLCHAIN]]/usr/lib" + +// When we have libc++.dylib in the toolchain, it should be used over the one in the sysroot. +// There are a few cases worth testing. +// +// (1) Without -fexperimental-library. +// RUN: %clangxx -### %s 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ +// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ +// RUN: --check-prefix=CHECK-3 %s +// CHECK-3: "/usr/bin/ld" +// CHECK-3: "[[TOOLCHAIN]]/usr/lib/libc++.dylib" +// CHECK-3-NOT: "-lc++" +// +// (2) With -fexperimental-library. +// RUN: %clangxx -### %s 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain/usr/bin \ +// RUN: -fexperimental-library \ +// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \ +// RUN: --check-prefix=CHECK-4 %s +// CHECK-4: "/usr/bin/ld" +// CHECK-4: "[[TOOLCHAIN]]/usr/lib/libc++.dylib" +// CHECK-4: "[[TOOLCHAIN]]/usr/lib/libc++experimental.a" +// CHECK-4-NOT: "-lc++" +// CHECK-4-NOT: "-lc++experimental" + +// When we have libc++.a in the toolchain instead of libc++.dylib, it should be +// used over the one in the sysroot. +// +// (1) Without -fexperimental-library. +// RUN: %clangxx -### %s 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_static/usr/bin \ +// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain_static \ +// RUN: --check-prefix=CHECK-5 %s +// CHECK-5: "/usr/bin/ld" +// CHECK-5: "[[TOOLCHAIN]]/usr/lib/libc++.a" +// CHECK-5-NOT: "-lc++" +// +// (2) With -fexperimental-library. +// RUN: %clangxx -### %s 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -ccc-install-dir %S/Inputs/basic_darwin_toolchain_static/usr/bin \ +// RUN: -fexperimental-library \ +// RUN: | FileCheck -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain_static \ +// RUN: --check-prefix=CHECK-6 %s +// CHECK-6: "/usr/bin/ld" +// CHECK-6: "[[TOOLCHAIN]]/usr/lib/libc++.a" +// CHECK-6: "[[TOOLCHAIN]]/usr/lib/libc++experimental.a" +// CHECK-6-NOT: "-lc++" +// CHECK-6-NOT: "-lc++experimental" diff --git a/clang/test/Driver/experimental-library-flag.cpp b/clang/test/Driver/experimental-library-flag.cpp index 62b007516897e..0546a09d5518b 100644 --- a/clang/test/Driver/experimental-library-flag.cpp +++ b/clang/test/Driver/experimental-library-flag.cpp @@ -18,6 +18,8 @@ // CHECK: -fexperimental-library // Depending on the stdlib in use, we should (or not) pass -lc++experimental. -// CHECK-LIBCXX: -lc++experimental -// CHECK-LIBSTDCXX-NOT: -lc++experimental -// CHECK-NOSTDLIB-NOT: -lc++experimental +// Note that we don't check for `-lc++experimental` specifically, since some targets +// like Darwin pass the path to the library explicitly instead of using `-lx`. +// CHECK-LIBCXX: c++experimental +// CHECK-LIBSTDCXX-NOT: c++experimental +// CHECK-NOSTDLIB-NOT: c++experimental From 854841e9ef6605a0e49803eafaa01c1dc7b657b5 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Wed, 3 Dec 2025 11:42:22 -0500 Subject: [PATCH 3/4] Fix comment which incorrectly represents the value of the install/lib path --- clang/lib/Driver/ToolChains/Darwin.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 6665b54ca473d..30c53389dc22f 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -2865,7 +2865,7 @@ void AppleMachO::AddCXXStdlibLibArgs(const ArgList &Args, // name) which may have been configured with different options, be at a // different version, etc. SmallString<128> InstallLib = llvm::sys::path::parent_path(getDriver().Dir); - llvm::sys::path::append(InstallLib, "lib"); // /bin/../lib + llvm::sys::path::append(InstallLib, "lib"); // /lib auto Link = [&](StringRef Library) { SmallString<128> Shared(InstallLib); llvm::sys::path::append(Shared, From d1b7b485e5ebf3d3f1b837befb1167febb6c8cf6 Mon Sep 17 00:00:00 2001 From: Louis Dionne Date: Thu, 4 Dec 2025 18:43:28 -0500 Subject: [PATCH 4/4] Avoid default search paths when linking against libc++ from compiler-rt --- compiler-rt/cmake/config-ix.cmake | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/compiler-rt/cmake/config-ix.cmake b/compiler-rt/cmake/config-ix.cmake index 084a7060e8d13..30a78b69515cc 100644 --- a/compiler-rt/cmake/config-ix.cmake +++ b/compiler-rt/cmake/config-ix.cmake @@ -507,8 +507,23 @@ if(APPLE) set(CMAKE_OSX_DEPLOYMENT_TARGET "") set(DARWIN_COMMON_CFLAGS -stdlib=libc++) + + # This is tricky: We want to link against libc++, however the libc++ for the + # architecture we're currently building may not have been built yet, since + # compiler-rt on Darwin builds for all targets at once while libc++ builds for + # a single target. Hence, we pass -nostdlib++ to disable the default mechanism + # for finding libc++, and we pass -lc++ which will end up finding libc++ in the + # SDK currently in use. That libc++ is the wrong libc++ to use if we're using + # headers from a just-built libc++, but at least it contains all the architectures + # we should be interested in. + # + # Fixing this properly would require removing the impedence mismatch between + # the compiler-rt build on Darwin (which wants to build all architectures at + # once) and the libc++ build, which produces a single architecture per CMake + # invocation. set(DARWIN_COMMON_LINK_FLAGS -stdlib=libc++ + -nostdlib++ -lc++ -lc++abi)