forked from OSchip/llvm-project
[Clang][Driver] Fix include paths for `--sysroot /` on Linux
Currently if `--sysroot /` is passed to the Clang driver, the include paths generated by the Clang driver will start with a double slash: `//usr/include/...`. If VFS is used to inject files into the include paths (for example, the Swift compiler does this), VFS will get confused and the injected files won't be visible. This change makes sure that the include paths start with a single slash. Fixes #28283. Differential Revision: https://reviews.llvm.org/D126289
This commit is contained in:
parent
684c080108
commit
e917801edd
|
@ -215,6 +215,9 @@ protected:
|
|||
static void addSystemIncludes(const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args,
|
||||
ArrayRef<StringRef> Paths);
|
||||
|
||||
static std::string concat(StringRef Path, const Twine &A, const Twine &B = "",
|
||||
const Twine &C = "", const Twine &D = "");
|
||||
///@}
|
||||
|
||||
public:
|
||||
|
|
|
@ -942,6 +942,14 @@ void ToolChain::addExternCSystemIncludeIfExists(const ArgList &DriverArgs,
|
|||
}
|
||||
}
|
||||
|
||||
/*static*/ std::string ToolChain::concat(StringRef Path, const Twine &A,
|
||||
const Twine &B, const Twine &C,
|
||||
const Twine &D) {
|
||||
SmallString<128> Result(Path);
|
||||
llvm::sys::path::append(Result, llvm::sys::path::Style::posix, A, B, C, D);
|
||||
return std::string(Result);
|
||||
}
|
||||
|
||||
std::string ToolChain::detectLibcxxVersion(StringRef IncludePath) const {
|
||||
std::error_code EC;
|
||||
int MaxVersion = 0;
|
||||
|
|
|
@ -2038,7 +2038,7 @@ void Generic_GCC::GCCInstallationDetector::init(
|
|||
if (!VFS.exists(Prefix))
|
||||
continue;
|
||||
for (StringRef Suffix : CandidateLibDirs) {
|
||||
const std::string LibDir = Prefix + Suffix.str();
|
||||
const std::string LibDir = concat(Prefix, Suffix);
|
||||
if (!VFS.exists(LibDir))
|
||||
continue;
|
||||
// Maybe filter out <libdir>/gcc and <libdir>/gcc-cross.
|
||||
|
@ -2104,7 +2104,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
|
|||
// so we need to find those /usr/gcc/*/lib/gcc libdirs and go with
|
||||
// /usr/gcc/<version> as a prefix.
|
||||
|
||||
std::string PrefixDir = SysRoot.str() + "/usr/gcc";
|
||||
std::string PrefixDir = concat(SysRoot, "/usr/gcc");
|
||||
std::error_code EC;
|
||||
for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC),
|
||||
LE;
|
||||
|
@ -2144,7 +2144,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
|
|||
}
|
||||
|
||||
// Fall back to /usr which is used by most non-Solaris systems.
|
||||
Prefixes.push_back(SysRoot.str() + "/usr");
|
||||
Prefixes.push_back(concat(SysRoot, "/usr"));
|
||||
}
|
||||
|
||||
/*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples(
|
||||
|
@ -2667,7 +2667,7 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooConfigs(
|
|||
const llvm::Triple &TargetTriple, const ArgList &Args,
|
||||
const SmallVectorImpl<StringRef> &CandidateTriples,
|
||||
const SmallVectorImpl<StringRef> &CandidateBiarchTriples) {
|
||||
if (!D.getVFS().exists(D.SysRoot + GentooConfigDir))
|
||||
if (!D.getVFS().exists(concat(D.SysRoot, GentooConfigDir)))
|
||||
return false;
|
||||
|
||||
for (StringRef CandidateTriple : CandidateTriples) {
|
||||
|
@ -2686,8 +2686,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
|
|||
const llvm::Triple &TargetTriple, const ArgList &Args,
|
||||
StringRef CandidateTriple, bool NeedsBiarchSuffix) {
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
|
||||
D.getVFS().getBufferForFile(D.SysRoot + GentooConfigDir + "/config-" +
|
||||
CandidateTriple.str());
|
||||
D.getVFS().getBufferForFile(concat(D.SysRoot, GentooConfigDir,
|
||||
"/config-" + CandidateTriple.str()));
|
||||
if (File) {
|
||||
SmallVector<StringRef, 2> Lines;
|
||||
File.get()->getBuffer().split(Lines, "\n");
|
||||
|
@ -2698,8 +2698,8 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
|
|||
continue;
|
||||
// Process the config file pointed to by CURRENT.
|
||||
llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> ConfigFile =
|
||||
D.getVFS().getBufferForFile(D.SysRoot + GentooConfigDir + "/" +
|
||||
Line.str());
|
||||
D.getVFS().getBufferForFile(
|
||||
concat(D.SysRoot, GentooConfigDir, "/" + Line));
|
||||
std::pair<StringRef, StringRef> ActiveVersion = Line.rsplit('-');
|
||||
// List of paths to scan for libraries.
|
||||
SmallVector<StringRef, 4> GentooScanPaths;
|
||||
|
@ -2732,7 +2732,7 @@ bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig(
|
|||
|
||||
// Scan all paths for GCC libraries.
|
||||
for (const auto &GentooScanPath : GentooScanPaths) {
|
||||
std::string GentooPath = D.SysRoot + std::string(GentooScanPath);
|
||||
std::string GentooPath = concat(D.SysRoot, GentooScanPath);
|
||||
if (D.getVFS().exists(GentooPath + "/crtbegin.o")) {
|
||||
if (!ScanGCCForMultilibs(TargetTriple, Args, GentooPath,
|
||||
NeedsBiarchSuffix))
|
||||
|
@ -3025,9 +3025,9 @@ Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
|
|||
// If this is a development, non-installed, clang, libcxx will
|
||||
// not be found at ../include/c++ but it likely to be found at
|
||||
// one of the following two locations:
|
||||
if (AddIncludePath(SysRoot + "/usr/local/include"))
|
||||
if (AddIncludePath(concat(SysRoot, "/usr/local/include")))
|
||||
return;
|
||||
if (AddIncludePath(SysRoot + "/usr/include"))
|
||||
if (AddIncludePath(concat(SysRoot, "/usr/include")))
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -97,9 +97,9 @@ std::string Linux::getMultiarchTriple(const Driver &D,
|
|||
case llvm::Triple::mips64: {
|
||||
std::string MT = std::string(IsMipsR6 ? "mipsisa64r6" : "mips64") +
|
||||
"-linux-" + (IsMipsN32Abi ? "gnuabin32" : "gnuabi64");
|
||||
if (D.getVFS().exists(SysRoot + "/lib/" + MT))
|
||||
if (D.getVFS().exists(concat(SysRoot, "/lib", MT)))
|
||||
return MT;
|
||||
if (D.getVFS().exists(SysRoot + "/lib/mips64-linux-gnu"))
|
||||
if (D.getVFS().exists(concat(SysRoot, "/lib/mips64-linux-gnu")))
|
||||
return "mips64-linux-gnu";
|
||||
break;
|
||||
}
|
||||
|
@ -108,14 +108,14 @@ std::string Linux::getMultiarchTriple(const Driver &D,
|
|||
return "mips64el-linux-android";
|
||||
std::string MT = std::string(IsMipsR6 ? "mipsisa64r6el" : "mips64el") +
|
||||
"-linux-" + (IsMipsN32Abi ? "gnuabin32" : "gnuabi64");
|
||||
if (D.getVFS().exists(SysRoot + "/lib/" + MT))
|
||||
if (D.getVFS().exists(concat(SysRoot, "/lib", MT)))
|
||||
return MT;
|
||||
if (D.getVFS().exists(SysRoot + "/lib/mips64el-linux-gnu"))
|
||||
if (D.getVFS().exists(concat(SysRoot, "/lib/mips64el-linux-gnu")))
|
||||
return "mips64el-linux-gnu";
|
||||
break;
|
||||
}
|
||||
case llvm::Triple::ppc:
|
||||
if (D.getVFS().exists(SysRoot + "/lib/powerpc-linux-gnuspe"))
|
||||
if (D.getVFS().exists(concat(SysRoot, "/lib/powerpc-linux-gnuspe")))
|
||||
return "powerpc-linux-gnuspe";
|
||||
return "powerpc-linux-gnu";
|
||||
case llvm::Triple::ppcle:
|
||||
|
@ -269,13 +269,13 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
|||
// used. We need add both libo32 and /lib.
|
||||
if (Arch == llvm::Triple::mips || Arch == llvm::Triple::mipsel) {
|
||||
Generic_GCC::AddMultilibPaths(D, SysRoot, "libo32", MultiarchTriple, Paths);
|
||||
addPathIfExists(D, SysRoot + "/libo32", Paths);
|
||||
addPathIfExists(D, SysRoot + "/usr/libo32", Paths);
|
||||
addPathIfExists(D, concat(SysRoot, "/libo32"), Paths);
|
||||
addPathIfExists(D, concat(SysRoot, "/usr/libo32"), Paths);
|
||||
}
|
||||
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
|
||||
|
||||
addPathIfExists(D, SysRoot + "/lib/" + MultiarchTriple, Paths);
|
||||
addPathIfExists(D, SysRoot + "/lib/../" + OSLibDir, Paths);
|
||||
addPathIfExists(D, concat(SysRoot, "/lib", MultiarchTriple), Paths);
|
||||
addPathIfExists(D, concat(SysRoot, "/lib/..", OSLibDir), Paths);
|
||||
|
||||
if (IsAndroid) {
|
||||
// Android sysroots contain a library directory for each supported OS
|
||||
|
@ -283,24 +283,24 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
|||
// directory.
|
||||
addPathIfExists(
|
||||
D,
|
||||
SysRoot + "/usr/lib/" + MultiarchTriple + "/" +
|
||||
llvm::to_string(Triple.getEnvironmentVersion().getMajor()),
|
||||
concat(SysRoot, "/usr/lib", MultiarchTriple,
|
||||
llvm::to_string(Triple.getEnvironmentVersion().getMajor())),
|
||||
Paths);
|
||||
}
|
||||
|
||||
addPathIfExists(D, SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
|
||||
addPathIfExists(D, concat(SysRoot, "/usr/lib", MultiarchTriple), Paths);
|
||||
// 64-bit OpenEmbedded sysroots may not have a /usr/lib dir. So they cannot
|
||||
// find /usr/lib64 as it is referenced as /usr/lib/../lib64. So we handle
|
||||
// this here.
|
||||
if (Triple.getVendor() == llvm::Triple::OpenEmbedded &&
|
||||
Triple.isArch64Bit())
|
||||
addPathIfExists(D, SysRoot + "/usr/" + OSLibDir, Paths);
|
||||
addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir), Paths);
|
||||
else
|
||||
addPathIfExists(D, SysRoot + "/usr/lib/../" + OSLibDir, Paths);
|
||||
addPathIfExists(D, concat(SysRoot, "/usr/lib/..", OSLibDir), Paths);
|
||||
if (IsRISCV) {
|
||||
StringRef ABIName = tools::riscv::getRISCVABI(Args, Triple);
|
||||
addPathIfExists(D, SysRoot + "/" + OSLibDir + "/" + ABIName, Paths);
|
||||
addPathIfExists(D, SysRoot + "/usr/" + OSLibDir + "/" + ABIName, Paths);
|
||||
addPathIfExists(D, concat(SysRoot, "/", OSLibDir, ABIName), Paths);
|
||||
addPathIfExists(D, concat(SysRoot, "/usr", OSLibDir, ABIName), Paths);
|
||||
}
|
||||
|
||||
Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths);
|
||||
|
@ -312,8 +312,8 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
|||
D.getVFS().exists(D.Dir + "/../lib/libc++.so"))
|
||||
addPathIfExists(D, D.Dir + "/../lib", Paths);
|
||||
|
||||
addPathIfExists(D, SysRoot + "/lib", Paths);
|
||||
addPathIfExists(D, SysRoot + "/usr/lib", Paths);
|
||||
addPathIfExists(D, concat(SysRoot, "/lib"), Paths);
|
||||
addPathIfExists(D, concat(SysRoot, "/usr/lib"), Paths);
|
||||
}
|
||||
|
||||
ToolChain::RuntimeLibType Linux::GetDefaultRuntimeLibType() const {
|
||||
|
@ -586,7 +586,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
|
|||
return;
|
||||
|
||||
// LOCAL_INCLUDE_DIR
|
||||
addSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/local/include");
|
||||
addSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/usr/local/include"));
|
||||
// TOOL_INCLUDE_DIR
|
||||
AddMultilibIncludeArgs(DriverArgs, CC1Args);
|
||||
|
||||
|
@ -607,9 +607,10 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
|
|||
// /usr/include.
|
||||
std::string MultiarchIncludeDir = getMultiarchTriple(D, getTriple(), SysRoot);
|
||||
if (!MultiarchIncludeDir.empty() &&
|
||||
D.getVFS().exists(SysRoot + "/usr/include/" + MultiarchIncludeDir))
|
||||
addExternCSystemInclude(DriverArgs, CC1Args,
|
||||
SysRoot + "/usr/include/" + MultiarchIncludeDir);
|
||||
D.getVFS().exists(concat(SysRoot, "/usr/include", MultiarchIncludeDir)))
|
||||
addExternCSystemInclude(
|
||||
DriverArgs, CC1Args,
|
||||
concat(SysRoot, "/usr/include", MultiarchIncludeDir));
|
||||
|
||||
if (getTriple().getOS() == llvm::Triple::RTEMS)
|
||||
return;
|
||||
|
@ -617,9 +618,9 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
|
|||
// Add an include of '/include' directly. This isn't provided by default by
|
||||
// system GCCs, but is often used with cross-compiling GCCs, and harmless to
|
||||
// add even when Clang is acting as-if it were a system compiler.
|
||||
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/include");
|
||||
addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/include"));
|
||||
|
||||
addExternCSystemInclude(DriverArgs, CC1Args, SysRoot + "/usr/include");
|
||||
addExternCSystemInclude(DriverArgs, CC1Args, concat(SysRoot, "/usr/include"));
|
||||
|
||||
if (!DriverArgs.hasArg(options::OPT_nobuiltininc) && getTriple().isMusl())
|
||||
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
|
||||
|
|
|
@ -16,6 +16,22 @@
|
|||
// CHECK-BASIC-LIBCXX-SYSROOT: "-internal-isystem" "[[SYSROOT]]/usr/include/x86_64-unknown-linux-gnu/c++/v1"
|
||||
// CHECK-BASIC-LIBCXX-SYSROOT: "-internal-isystem" "[[SYSROOT]]/usr/include/c++/v1"
|
||||
// CHECK-BASIC-LIBCXX-SYSROOT: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
|
||||
|
||||
// Test include paths when the sysroot path ends with `/`.
|
||||
// RUN: %clang -### %s -fsyntax-only 2>&1 \
|
||||
// RUN: --target=x86_64-unknown-linux-gnu \
|
||||
// RUN: -stdlib=libc++ \
|
||||
// RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir \
|
||||
// RUN: --sysroot=%S/Inputs/basic_linux_libcxx_tree/ \
|
||||
// RUN: --gcc-toolchain="" \
|
||||
// RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBCXX-SYSROOT-SLASH %s
|
||||
// CHECK-BASIC-LIBCXX-SYSROOT-SLASH: "-cc1"
|
||||
// CHECK-BASIC-LIBCXX-SYSROOT-SLASH-SAME: "-isysroot" "[[SYSROOT:[^"]+/]]"
|
||||
// CHECK-BASIC-LIBCXX-SYSROOT-SLASH-SAME: "-internal-isystem" "[[SYSROOT]]usr/include/x86_64-unknown-linux-gnu/c++/v1"
|
||||
// CHECK-BASIC-LIBCXX-SYSROOT-SLASH-SAME: "-internal-isystem" "[[SYSROOT]]usr/include/c++/v1"
|
||||
// CHECK-BASIC-LIBCXX-SYSROOT-SLASH-SAME: "-internal-isystem" "[[SYSROOT]]usr/local/include"
|
||||
|
||||
// RUN: %clang -### %s -fsyntax-only 2>&1 \
|
||||
// RUN: --target=x86_64-unknown-linux-gnu \
|
||||
// RUN: -stdlib=libc++ \
|
||||
|
@ -56,7 +72,20 @@
|
|||
// CHECK-BASIC-LIBCXXV2-INSTALL: "-internal-isystem" "[[SYSROOT]]/usr/bin/../include/x86_64-unknown-linux-gnu/c++/v2"
|
||||
// CHECK-BASIC-LIBCXXV2-INSTALL: "-internal-isystem" "[[SYSROOT]]/usr/bin/../include/c++/v2"
|
||||
// CHECK-BASIC-LIBCXXV2-INSTALL: "-internal-isystem" "[[SYSROOT]]/usr/local/include"
|
||||
//
|
||||
|
||||
// Test Linux with libstdc++ when the sysroot path ends with `/`.
|
||||
// RUN: %clang -### %s -fsyntax-only 2>&1 \
|
||||
// RUN: --target=x86_64-unknown-linux-gnu \
|
||||
// RUN: -stdlib=libstdc++ \
|
||||
// RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir \
|
||||
// RUN: --sysroot=%S/Inputs/basic_linux_libstdcxx_tree/ \
|
||||
// RUN: --gcc-toolchain="" \
|
||||
// RUN: | FileCheck --check-prefix=CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH %s
|
||||
// CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH: "-cc1"
|
||||
// CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH-SAME: "-isysroot" "[[SYSROOT:[^"]+/]]"
|
||||
// CHECK-BASIC-LIBSTDCXX-SYSROOT-SLASH-SAME: "-internal-isystem" "[[SYSROOT]]usr/lib/gcc/x86_64-unknown-linux-gnu/4.8/../../../../x86_64-unknown-linux-gnu/include"
|
||||
|
||||
// Test Linux with both libc++ and libstdc++ installed.
|
||||
// RUN: %clang -### %s -fsyntax-only 2>&1 \
|
||||
// RUN: --target=x86_64-unknown-linux-gnu \
|
||||
|
|
Loading…
Reference in New Issue