forked from OSchip/llvm-project
[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:
parent
586acd8490
commit
b18cb9c471
|
@ -2686,19 +2686,49 @@ void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const {
|
||||
// FIXME: The Linux behavior would probaby be a better approach here.
|
||||
addSystemInclude(DriverArgs, CC1Args,
|
||||
getDriver().SysRoot + "/usr/include/c++/v1");
|
||||
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
|
||||
Generic_GCC::addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const {
|
||||
// By default, we don't assume we know where libstdc++ might be installed.
|
||||
// FIXME: If we have a valid GCCInstallation, use it.
|
||||
Generic_GCC::addLibCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const {
|
||||
const std::string& SysRoot = getDriver().SysRoot;
|
||||
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.
|
||||
|
@ -2734,6 +2764,60 @@ bool Generic_GCC::addLibStdCXXIncludePaths(
|
|||
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 *
|
||||
Generic_GCC::TranslateArgs(const llvm::opt::DerivedArgList &Args, StringRef,
|
||||
Action::OffloadKind DeviceOffloadKind) const {
|
||||
|
|
|
@ -300,6 +300,11 @@ protected:
|
|||
Tool *buildAssembler() 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
|
||||
/// @{
|
||||
|
||||
|
@ -322,6 +327,10 @@ protected:
|
|||
addLibStdCxxIncludePaths(const llvm::opt::ArgList &DriverArgs,
|
||||
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,
|
||||
StringRef GCCMultiarchTriple,
|
||||
StringRef TargetMultiarchTriple,
|
||||
|
|
|
@ -27,9 +27,9 @@ using tools::addPathIfExists;
|
|||
/// a target-triple directory in the library and header search paths.
|
||||
/// Unfortunately, this triple does not align with the vanilla target triple,
|
||||
/// so we provide a rough mapping here.
|
||||
static std::string getMultiarchTriple(const Driver &D,
|
||||
const llvm::Triple &TargetTriple,
|
||||
StringRef SysRoot) {
|
||||
std::string Hurd::getMultiarchTriple(const Driver &D,
|
||||
const llvm::Triple &TargetTriple,
|
||||
StringRef SysRoot) const {
|
||||
if (TargetTriple.getArch() == llvm::Triple::x86) {
|
||||
// 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
|
||||
|
|
|
@ -36,6 +36,10 @@ public:
|
|||
protected:
|
||||
Tool *buildAssembler() const override;
|
||||
Tool *buildLinker() const override;
|
||||
|
||||
std::string getMultiarchTriple(const Driver &D,
|
||||
const llvm::Triple &TargetTriple,
|
||||
StringRef SysRoot) const override;
|
||||
};
|
||||
|
||||
} // end namespace toolchains
|
||||
|
|
|
@ -37,9 +37,9 @@ using tools::addPathIfExists;
|
|||
/// a target-triple directory in the library and header search paths.
|
||||
/// Unfortunately, this triple does not align with the vanilla target triple,
|
||||
/// 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,
|
||||
StringRef SysRoot) {
|
||||
StringRef SysRoot) const {
|
||||
llvm::Triple::EnvironmentType TargetEnvironment =
|
||||
TargetTriple.getEnvironment();
|
||||
bool IsAndroid = TargetTriple.isAndroid();
|
||||
|
@ -865,86 +865,23 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
|
|||
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,
|
||||
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
|
||||
// headers.
|
||||
// headers in odd Linuxish places.
|
||||
if (!GCCInstallation.isValid())
|
||||
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 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;
|
||||
|
||||
// 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,
|
||||
// Android standalone toolchain has C++ headers in yet another place.
|
||||
LibDir.str() + "/../" + TripleStr.str() + "/include/c++/" + Version.Text,
|
||||
// Freescale SDK C++ headers are directly in <sysroot>/usr/include/c++,
|
||||
|
|
|
@ -26,9 +26,6 @@ public:
|
|||
void
|
||||
AddClangSystemIncludeArgs(const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const override;
|
||||
void addLibCxxIncludePaths(
|
||||
const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const override;
|
||||
void addLibStdCxxIncludePaths(
|
||||
const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const override;
|
||||
|
@ -52,6 +49,10 @@ public:
|
|||
protected:
|
||||
Tool *buildAssembler() const override;
|
||||
Tool *buildLinker() const override;
|
||||
|
||||
std::string getMultiarchTriple(const Driver &D,
|
||||
const llvm::Triple &TargetTriple,
|
||||
StringRef SysRoot) const override;
|
||||
};
|
||||
|
||||
} // end namespace toolchains
|
||||
|
|
Loading…
Reference in New Issue