[clang] Revert changes to prefer the toolchain-provided libc++.dylib

This patch reverts the change that made clang prefer the toolchain
libc++.dylib when there is one (#170303), and the subsequent test
workaround we landed to fix bots (#170912).

We are seeing some failure on macOS LLDB bots that need to be
investigated, and that will require more time than I can spare
before the end of today.

This reverts commits bad1a88963 and 190b8d0b.
This commit is contained in:
Louis Dionne
2025-12-05 16:41:56 -05:00
parent 7982688b69
commit a55221da60
11 changed files with 8 additions and 147 deletions

View File

@@ -2846,49 +2846,11 @@ void AppleMachO::AddCXXStdlibLibArgs(const ArgList &Args,
CXXStdlibType Type = GetCXXStdlibType(Args);
switch (Type) {
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"); // <install>/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++");
case ToolChain::CST_Libcxx:
CmdArgs.push_back("-lc++");
if (Args.hasArg(options::OPT_fexperimental_library))
Link("c++experimental");
CmdArgs.push_back("-lc++experimental");
break;
}
case ToolChain::CST_Libstdcxx:
// Unfortunately, -lstdc++ doesn't always exist in the standard search path;

View File

@@ -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 -nostdlibinc will drop both the toolchain
// Make sure that using -nostdinc, -nostdinc++ or -nostdlib 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_cxx_v1 \
// RUN: | FileCheck -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr \
// RUN: -DTOOLCHAIN=%S/Inputs/basic_darwin_toolchain \
// RUN: --check-prefix=CHECK-LIBCXX-NOSTDINCXX %s
// CHECK-LIBCXX-NOSTDINCXX: "-cc1"

View File

@@ -1,84 +0,0 @@
// UNSUPPORTED: system-windows
// TODO: Make this test portable across platforms
// REQUIRES: system-darwin
// 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"

View File

@@ -18,8 +18,6 @@
// CHECK: -fexperimental-library
// Depending on the stdlib in use, we should (or not) pass -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
// CHECK-LIBCXX: -lc++experimental
// CHECK-LIBSTDCXX-NOT: -lc++experimental
// CHECK-NOSTDLIB-NOT: -lc++experimental

View File

@@ -507,23 +507,8 @@ 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)