[Gnu toolchain] Look at standard GCC paths for libstdcxx by default

Linux' current addLibCxxIncludePaths and addLibStdCxxIncludePaths
are actually almost non-Linux-specific at all, and can be reused
almost as such for all gcc toolchains. Only keep
Android/Freescale/Cray hacks in Linux's version.

Patch by sthibaul (Samuel Thibault)

Differential Revision: https://reviews.llvm.org/D69758
This commit is contained in:
Kristina Brooks 2020-01-05 21:43:16 +00:00
parent 586acd8490
commit b18cb9c471
6 changed files with 121 additions and 86 deletions

View File

@ -2686,19 +2686,49 @@ void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
} }
} }
void static std::string DetectLibcxxIncludePath(llvm::vfs::FileSystem &vfs,
Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, StringRef base) {
llvm::opt::ArgStringList &CC1Args) const { std::error_code EC;
// FIXME: The Linux behavior would probaby be a better approach here. int MaxVersion = 0;
addSystemInclude(DriverArgs, CC1Args, std::string MaxVersionString;
getDriver().SysRoot + "/usr/include/c++/v1"); for (llvm::vfs::directory_iterator LI = vfs.dir_begin(base, EC), LE;
!EC && LI != LE; LI = LI.increment(EC)) {
StringRef VersionText = llvm::sys::path::filename(LI->path());
int Version;
if (VersionText[0] == 'v' &&
!VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
if (Version > MaxVersion) {
MaxVersion = Version;
MaxVersionString = VersionText;
}
}
}
return MaxVersion ? (base + "/" + MaxVersionString).str() : "";
} }
void void
Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const { llvm::opt::ArgStringList &CC1Args) const {
// By default, we don't assume we know where libstdc++ might be installed. const std::string& SysRoot = getDriver().SysRoot;
// FIXME: If we have a valid GCCInstallation, use it. auto AddIncludePath = [&](std::string Path) {
std::string IncludePath = DetectLibcxxIncludePath(getVFS(), Path);
if (IncludePath.empty() || !getVFS().exists(IncludePath))
return false;
addSystemInclude(DriverArgs, CC1Args, IncludePath);
return true;
};
// Android never uses the libc++ headers installed alongside the toolchain,
// which are generally incompatible with the NDK libraries anyway.
if (!getTriple().isAndroid())
if (AddIncludePath(getDriver().Dir + "/../include/c++"))
return;
// 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/c++"))
return;
if (AddIncludePath(SysRoot + "/usr/include/c++"))
return;
} }
/// Helper to add the variant paths of a libstdc++ installation. /// Helper to add the variant paths of a libstdc++ installation.
@ -2734,6 +2764,60 @@ bool Generic_GCC::addLibStdCXXIncludePaths(
return true; return true;
} }
bool
Generic_GCC::addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
// Use GCCInstallation to know where libstdc++ headers are installed.
if (!GCCInstallation.isValid())
return false;
// By default, look for the C++ headers in an include directory adjacent to
// the lib directory of the GCC installation. Note that this is expect to be
// equivalent to '/usr/include/c++/X.Y' in almost all cases.
StringRef LibDir = GCCInstallation.getParentLibPath();
StringRef InstallDir = GCCInstallation.getInstallPath();
StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib();
const std::string GCCMultiarchTriple = getMultiarchTriple(
getDriver(), GCCInstallation.getTriple(), getDriver().SysRoot);
const std::string TargetMultiarchTriple =
getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
const GCCVersion &Version = GCCInstallation.getVersion();
// The primary search for libstdc++ supports multiarch variants.
if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
"/c++/" + Version.Text, TripleStr,
GCCMultiarchTriple, TargetMultiarchTriple,
Multilib.includeSuffix(), DriverArgs, CC1Args))
return true;
// Otherwise, fall back on a bunch of options which don't use multiarch
// layouts for simplicity.
const std::string LibStdCXXIncludePathCandidates[] = {
// Gentoo is weird and places its headers inside the GCC install,
// so if the first attempt to find the headers fails, try these patterns.
InstallDir.str() + "/include/g++-v" + Version.Text,
InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +
Version.MinorStr,
InstallDir.str() + "/include/g++-v" + Version.MajorStr,
};
for (const auto &IncludePath : LibStdCXXIncludePathCandidates) {
if (addLibStdCXXIncludePaths(IncludePath, /*Suffix*/ "", TripleStr,
/*GCCMultiarchTriple*/ "",
/*TargetMultiarchTriple*/ "",
Multilib.includeSuffix(), DriverArgs, CC1Args))
return true;
}
return false;
}
void
Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args);
}
llvm::opt::DerivedArgList * llvm::opt::DerivedArgList *
Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef, Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef,
Action::OffloadKind DeviceOffloadKind) const { Action::OffloadKind DeviceOffloadKind) const {

View File

@ -300,6 +300,11 @@ protected:
Tool *buildAssembler() const override; Tool *buildAssembler() const override;
Tool *buildLinker() const override; Tool *buildLinker() const override;
virtual std::string getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef SysRoot) const
{ return TargetTriple.str(); }
/// \name ToolChain Implementation Helper Functions /// \name ToolChain Implementation Helper Functions
/// @{ /// @{
@ -322,6 +327,10 @@ protected:
addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const; llvm::opt::ArgStringList &CC1Args) const;
bool
addGCCLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const;
bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, StringRef GCCTriple, bool addLibStdCXXIncludePaths(Twine Base, Twine Suffix, StringRef GCCTriple,
StringRef GCCMultiarchTriple, StringRef GCCMultiarchTriple,
StringRef TargetMultiarchTriple, StringRef TargetMultiarchTriple,

View File

@ -27,9 +27,9 @@ using tools::addPathIfExists;
/// a target-triple directory in the library and header search paths. /// a target-triple directory in the library and header search paths.
/// Unfortunately, this triple does not align with the vanilla target triple, /// Unfortunately, this triple does not align with the vanilla target triple,
/// so we provide a rough mapping here. /// so we provide a rough mapping here.
static std::string getMultiarchTriple(const Driver &D, std::string Hurd::getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple, const llvm::Triple &TargetTriple,
StringRef SysRoot) { StringRef SysRoot) const {
if (TargetTriple.getArch() == llvm::Triple::x86) { if (TargetTriple.getArch() == llvm::Triple::x86) {
// We use the existence of '/lib/<triple>' as a directory to detect some // We use the existence of '/lib/<triple>' as a directory to detect some
// common hurd triples that don't quite match the Clang triple for both // common hurd triples that don't quite match the Clang triple for both

View File

@ -36,6 +36,10 @@ public:
protected: protected:
Tool *buildAssembler() const override; Tool *buildAssembler() const override;
Tool *buildLinker() const override; Tool *buildLinker() const override;
std::string getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef SysRoot) const override;
}; };
} // end namespace toolchains } // end namespace toolchains

View File

@ -37,9 +37,9 @@ using tools::addPathIfExists;
/// a target-triple directory in the library and header search paths. /// a target-triple directory in the library and header search paths.
/// Unfortunately, this triple does not align with the vanilla target triple, /// Unfortunately, this triple does not align with the vanilla target triple,
/// so we provide a rough mapping here. /// so we provide a rough mapping here.
static std::string getMultiarchTriple(const Driver &D, std::string Linux::getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple, const llvm::Triple &TargetTriple,
StringRef SysRoot) { StringRef SysRoot) const {
llvm::Triple::EnvironmentType TargetEnvironment = llvm::Triple::EnvironmentType TargetEnvironment =
TargetTriple.getEnvironment(); TargetTriple.getEnvironment();
bool IsAndroid = TargetTriple.isAndroid(); bool IsAndroid = TargetTriple.isAndroid();
@ -865,86 +865,23 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude); addSystemInclude(DriverArgs, CC1Args, ResourceDirInclude);
} }
static std::string DetectLibcxxIncludePath(llvm::vfs::FileSystem &vfs,
StringRef base) {
std::error_code EC;
int MaxVersion = 0;
std::string MaxVersionString = "";
for (llvm::vfs::directory_iterator LI = vfs.dir_begin(base, EC), LE;
!EC && LI != LE; LI = LI.increment(EC)) {
StringRef VersionText = llvm::sys::path::filename(LI->path());
int Version;
if (VersionText[0] == 'v' &&
!VersionText.slice(1, StringRef::npos).getAsInteger(10, Version)) {
if (Version > MaxVersion) {
MaxVersion = Version;
MaxVersionString = VersionText;
}
}
}
return MaxVersion ? (base + "/" + MaxVersionString).str() : "";
}
void Linux::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const {
const std::string& SysRoot = computeSysRoot();
auto AddIncludePath = [&](std::string Path) {
std::string IncludePath = DetectLibcxxIncludePath(getVFS(), Path);
if (IncludePath.empty() || !getVFS().exists(IncludePath))
return false;
addSystemInclude(DriverArgs, CC1Args, IncludePath);
return true;
};
// Android never uses the libc++ headers installed alongside the toolchain,
// which are generally incompatible with the NDK libraries anyway.
if (!getTriple().isAndroid())
if (AddIncludePath(getDriver().Dir + "/../include/c++"))
return;
// 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/c++"))
return;
if (AddIncludePath(SysRoot + "/usr/include/c++"))
return;
}
void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs, void Linux::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const { llvm::opt::ArgStringList &CC1Args) const {
// Try generic GCC detection first.
if (Generic_GCC::addGCCLibStdCxxIncludePaths(DriverArgs, CC1Args))
return;
// We need a detected GCC installation on Linux to provide libstdc++'s // We need a detected GCC installation on Linux to provide libstdc++'s
// headers. // headers in odd Linuxish places.
if (!GCCInstallation.isValid()) if (!GCCInstallation.isValid())
return; return;
// By default, look for the C++ headers in an include directory adjacent to
// the lib directory of the GCC installation. Note that this is expect to be
// equivalent to '/usr/include/c++/X.Y' in almost all cases.
StringRef LibDir = GCCInstallation.getParentLibPath(); StringRef LibDir = GCCInstallation.getParentLibPath();
StringRef InstallDir = GCCInstallation.getInstallPath();
StringRef TripleStr = GCCInstallation.getTriple().str(); StringRef TripleStr = GCCInstallation.getTriple().str();
const Multilib &Multilib = GCCInstallation.getMultilib(); const Multilib &Multilib = GCCInstallation.getMultilib();
const std::string GCCMultiarchTriple = getMultiarchTriple(
getDriver(), GCCInstallation.getTriple(), getDriver().SysRoot);
const std::string TargetMultiarchTriple =
getMultiarchTriple(getDriver(), getTriple(), getDriver().SysRoot);
const GCCVersion &Version = GCCInstallation.getVersion(); const GCCVersion &Version = GCCInstallation.getVersion();
// The primary search for libstdc++ supports multiarch variants.
if (addLibStdCXXIncludePaths(LibDir.str() + "/../include",
"/c++/" + Version.Text, TripleStr,
GCCMultiarchTriple, TargetMultiarchTriple,
Multilib.includeSuffix(), DriverArgs, CC1Args))
return;
// Otherwise, fall back on a bunch of options which don't use multiarch
// layouts for simplicity.
const std::string LibStdCXXIncludePathCandidates[] = { const std::string LibStdCXXIncludePathCandidates[] = {
// Gentoo is weird and places its headers inside the GCC install,
// so if the first attempt to find the headers fails, try these patterns.
InstallDir.str() + "/include/g++-v" + Version.Text,
InstallDir.str() + "/include/g++-v" + Version.MajorStr + "." +
Version.MinorStr,
InstallDir.str() + "/include/g++-v" + Version.MajorStr,
// Android standalone toolchain has C++ headers in yet another place. // Android standalone toolchain has C++ headers in yet another place.
LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text, LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
// Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++, // Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++,

View File

@ -26,9 +26,6 @@ public:
void void
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs, AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override; llvm::opt::ArgStringList &CC1Args) const override;
void addLibCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override;
void addLibStdCxxIncludePaths( void addLibStdCxxIncludePaths(
const llvm::opt::ArgList &DriverArgs, const llvm::opt::ArgList &DriverArgs,
llvm::opt::ArgStringList &CC1Args) const override; llvm::opt::ArgStringList &CC1Args) const override;
@ -52,6 +49,10 @@ public:
protected: protected:
Tool *buildAssembler() const override; Tool *buildAssembler() const override;
Tool *buildLinker() const override; Tool *buildLinker() const override;
std::string getMultiarchTriple(const Driver &D,
const llvm::Triple &TargetTriple,
StringRef SysRoot) const override;
}; };
} // end namespace toolchains } // end namespace toolchains