Author: Liviu Ionescu Date: 2023-11-20T11:14:36-05:00 New Revision: a32a2b2ceb6b4c1bbcbcb39363c8dee44daf86ab
URL: https://github.com/llvm/llvm-project/commit/a32a2b2ceb6b4c1bbcbcb39363c8dee44daf86ab DIFF: https://github.com/llvm/llvm-project/commit/a32a2b2ceb6b4c1bbcbcb39363c8dee44daf86ab.diff LOG: [clang][driver] Add <executable>/../include/c++/v1 to include path on Darwin (#70817) On macOS, when clang is invoked via a symlink, since the InstalledDir is where the link is located, the C++ headers are not identified and the default system headers from the SDK are used. This can be undesirable if a toolchain is created by symlinking clang into a directory and placing libc++ headers in that directory with the intent of those headers overriding the SDK headers. This change solves that problem by also looking for libc++ headers in the toolchain-relative location of the executable symlink, if any. Added: Modified: clang/lib/Driver/ToolChains/Darwin.cpp clang/test/Driver/darwin-header-search-libcxx.cpp Removed: ################################################################################ diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp index 7481f6cab9a968d..7c3d4982d8f6a8c 100644 --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -2470,14 +2470,19 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs( switch (GetCXXStdlibType(DriverArgs)) { case ToolChain::CST_Libcxx: { - // On Darwin, libc++ can be installed in one of the following two places: - // 1. Alongside the compiler in <install>/include/c++/v1 - // 2. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1 + // On Darwin, libc++ can be installed in one of the following places: + // 1. Alongside the compiler in <install>/include/c++/v1 + // 2. Alongside the compiler in <clang-executable-folder>/../include/c++/v1 + // 3. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1 // - // The precendence of paths is as listed above, i.e. we take the first path - // that exists. Also note that we never include libc++ twice -- we take the - // first path that exists and don't send the other paths to CC1 (otherwise + // The precedence of paths is as listed above, i.e. we take the first path + // that exists. Note that we never include libc++ twice -- we take the first + // path that exists and don't send the other paths to CC1 (otherwise // include_next could break). + // + // Also note that in most cases, (1) and (2) are exactly the same path. + // Those two paths will diff er only when the `clang` program being run + // is actually a symlink to the real executable. // Check for (1) // Get from '<install>/bin' to '<install>/include/c++/v1'. @@ -2494,7 +2499,20 @@ void DarwinClang::AddClangCXXStdlibIncludeArgs( << "\"\n"; } - // Otherwise, check for (2) + // (2) Check for the folder where the executable is located, if diff erent. + if (getDriver().getInstalledDir() != getDriver().Dir) { + InstallBin = llvm::StringRef(getDriver().Dir); + llvm::sys::path::append(InstallBin, "..", "include", "c++", "v1"); + if (getVFS().exists(InstallBin)) { + addSystemInclude(DriverArgs, CC1Args, InstallBin); + return; + } else if (DriverArgs.hasArg(options::OPT_v)) { + llvm::errs() << "ignoring nonexistent directory \"" << InstallBin + << "\"\n"; + } + } + + // Otherwise, check for (3) llvm::SmallString<128> SysrootUsr = Sysroot; llvm::sys::path::append(SysrootUsr, "usr", "include", "c++", "v1"); if (getVFS().exists(SysrootUsr)) { diff --git a/clang/test/Driver/darwin-header-search-libcxx.cpp b/clang/test/Driver/darwin-header-search-libcxx.cpp index cc8ec9ceb89b3ab..8f530299d53c6d8 100644 --- a/clang/test/Driver/darwin-header-search-libcxx.cpp +++ b/clang/test/Driver/darwin-header-search-libcxx.cpp @@ -172,3 +172,60 @@ // RUN: --check-prefix=CHECK-LIBCXX-STDLIB-UNSPECIFIED %s // CHECK-LIBCXX-STDLIB-UNSPECIFIED: "-cc1" // CHECK-LIBCXX-STDLIB-UNSPECIFIED: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1" + +// ---------------------------------------------------------------------------- +// On Darwin, libc++ can be installed in one of the following places: +// 1. Alongside the compiler in <install>/include/c++/v1 +// 2. Alongside the compiler in <clang-executable-folder>/../include/c++/v1 +// 3. In a SDK (or a custom sysroot) in <sysroot>/usr/include/c++/v1 + +// The build folders do not have an `include/c++/v1`; create a new +// local folder hierarchy that meets this requirement. +// Note: this might not work with weird RPATH configurations. +// RUN: rm -rf %t/install +// RUN: mkdir -pv %t/install/bin +// RUN: cp %clang %t/install/bin/clang +// RUN: mkdir -pv %t/install/include/c++/v1 + +// Headers in (1) and in (2) -> (1) is preferred over (2) +// RUN: rm -rf %t/symlinked1 +// RUN: mkdir -pv %t/symlinked1/bin +// RUN: ln -svf %t/install/bin/clang %t/symlinked1/bin/clang +// RUN: mkdir -pv %t/symlinked1/include/c++/v1 + +// RUN: %t/symlinked1/bin/clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -stdlib=libc++ \ +// RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ +// RUN: | FileCheck -DSYMLINKED=%t/symlinked1 \ +// RUN: -DTOOLCHAIN=%t/install \ +// RUN: -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ +// RUN: --check-prefix=CHECK-SYMLINKED-INCLUDE-CXX-V1 %s +// CHECK-SYMLINKED-INCLUDE-CXX-V1: "-internal-isystem" "[[SYMLINKED]]/bin/../include/c++/v1" +// CHECK-SYMLINKED-INCLUDE-CXX-V1-NOT: "-internal-isystem" "[[TOOLCHAIN]]/bin/../include/c++/v1" +// CHECK-SYMLINKED-INCLUDE-CXX-V1-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1" + +// Headers in (2) and in (3) -> (2) is preferred over (3) +// RUN: rm -rf %t/symlinked2 +// RUN: mkdir -pv %t/symlinked2/bin +// RUN: ln -svf %t/install/bin/clang %t/symlinked2/bin/clang + +// RUN: %t/symlinked2/bin/clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -stdlib=libc++ \ +// RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ +// RUN: | FileCheck -DTOOLCHAIN=%t/install \ +// RUN: -DSYSROOT=%S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ +// RUN: --check-prefix=CHECK-TOOLCHAIN-INCLUDE-CXX-V1 %s +// CHECK-TOOLCHAIN-INCLUDE-CXX-V1: "-internal-isystem" "[[TOOLCHAIN]]/bin/../include/c++/v1" +// CHECK-TOOLCHAIN-INCLUDE-CXX-V1-NOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1" + +// Headers in (2) and nowhere else -> (2) is used +// RUN: %t/symlinked2/bin/clang -### %s -fsyntax-only 2>&1 \ +// RUN: --target=x86_64-apple-darwin \ +// RUN: -stdlib=libc++ \ +// RUN: -isysroot %S/Inputs/basic_darwin_sdk_usr_cxx_v1 \ +// RUN: | FileCheck -DTOOLCHAIN=%t/install \ +// RUN: -DSYSROOT=%S/Inputs/basic_darwin_sdk_no_libcxx \ +// RUN: --check-prefix=CHECK-TOOLCHAIN-NO-SYSROOT %s +// CHECK-TOOLCHAIN-NO-SYSROOT: "-internal-isystem" "[[TOOLCHAIN]]/bin/../include/c++/v1" _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits