forked from OSchip/llvm-project
[Driver] Move GCC multilib/multiarch paths support from Linux.cpp to Gnu.cpp
The current code for GNU/Linux is actually completely generic, and can be moved to ToolChains/Gnu.cpp, so that it can benefit GNU/Hurd and GNU/kFreeBSD. Reviewed By: MaskRay, phosek Differential Revision: https://reviews.llvm.org/D73845
This commit is contained in:
parent
c3770c5d6d
commit
6395980370
|
@ -35,6 +35,7 @@ using namespace clang;
|
|||
using namespace llvm::opt;
|
||||
|
||||
using tools::addMultilibFlag;
|
||||
using tools::addPathIfExists;
|
||||
|
||||
void tools::GnuTool::anchor() {}
|
||||
|
||||
|
@ -2670,6 +2671,140 @@ bool Generic_GCC::IsIntegratedAssemblerDefault() const {
|
|||
}
|
||||
}
|
||||
|
||||
static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
|
||||
const Multilib &Multilib,
|
||||
StringRef InstallPath,
|
||||
ToolChain::path_list &Paths) {
|
||||
if (const auto &PathsCallback = Multilibs.filePathsCallback())
|
||||
for (const auto &Path : PathsCallback(Multilib))
|
||||
addPathIfExists(D, InstallPath + Path, Paths);
|
||||
}
|
||||
|
||||
void Generic_GCC::PushPPaths(ToolChain::path_list &PPaths) {
|
||||
// Cross-compiling binutils and GCC installations (vanilla and openSUSE at
|
||||
// least) put various tools in a triple-prefixed directory off of the parent
|
||||
// of the GCC installation. We use the GCC triple here to ensure that we end
|
||||
// up with tools that support the same amount of cross compiling as the
|
||||
// detected GCC installation. For example, if we find a GCC installation
|
||||
// targeting x86_64, but it is a bi-arch GCC installation, it can also be
|
||||
// used to target i386.
|
||||
if (GCCInstallation.isValid()) {
|
||||
PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
|
||||
GCCInstallation.getTriple().str() + "/bin")
|
||||
.str());
|
||||
}
|
||||
}
|
||||
|
||||
void Generic_GCC::AddMultilibPaths(const Driver &D,
|
||||
const std::string &SysRoot,
|
||||
const std::string &OSLibDir,
|
||||
const std::string &MultiarchTriple,
|
||||
path_list &Paths) {
|
||||
// Add the multilib suffixed paths where they are available.
|
||||
if (GCCInstallation.isValid()) {
|
||||
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
|
||||
const std::string &LibPath =
|
||||
std::string(GCCInstallation.getParentLibPath());
|
||||
|
||||
// Add toolchain / multilib specific file paths.
|
||||
addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
|
||||
GCCInstallation.getInstallPath(), Paths);
|
||||
|
||||
// Sourcery CodeBench MIPS toolchain holds some libraries under
|
||||
// a biarch-like suffix of the GCC installation.
|
||||
addPathIfExists(
|
||||
D, GCCInstallation.getInstallPath() + SelectedMultilib.gccSuffix(),
|
||||
Paths);
|
||||
|
||||
// GCC cross compiling toolchains will install target libraries which ship
|
||||
// as part of the toolchain under <prefix>/<triple>/<libdir> rather than as
|
||||
// any part of the GCC installation in
|
||||
// <prefix>/<libdir>/gcc/<triple>/<version>. This decision is somewhat
|
||||
// debatable, but is the reality today. We need to search this tree even
|
||||
// when we have a sysroot somewhere else. It is the responsibility of
|
||||
// whomever is doing the cross build targeting a sysroot using a GCC
|
||||
// installation that is *not* within the system root to ensure two things:
|
||||
//
|
||||
// 1) Any DSOs that are linked in from this tree or from the install path
|
||||
// above must be present on the system root and found via an
|
||||
// appropriate rpath.
|
||||
// 2) There must not be libraries installed into
|
||||
// <prefix>/<triple>/<libdir> unless they should be preferred over
|
||||
// those within the system root.
|
||||
//
|
||||
// Note that this matches the GCC behavior. See the below comment for where
|
||||
// Clang diverges from GCC's behavior.
|
||||
addPathIfExists(D,
|
||||
LibPath + "/../" + GCCTriple.str() + "/lib/../" + OSLibDir +
|
||||
SelectedMultilib.osSuffix(),
|
||||
Paths);
|
||||
|
||||
// If the GCC installation we found is inside of the sysroot, we want to
|
||||
// prefer libraries installed in the parent prefix of the GCC installation.
|
||||
// It is important to *not* use these paths when the GCC installation is
|
||||
// outside of the system root as that can pick up unintended libraries.
|
||||
// This usually happens when there is an external cross compiler on the
|
||||
// host system, and a more minimal sysroot available that is the target of
|
||||
// the cross. Note that GCC does include some of these directories in some
|
||||
// configurations but this seems somewhere between questionable and simply
|
||||
// a bug.
|
||||
if (StringRef(LibPath).startswith(SysRoot)) {
|
||||
addPathIfExists(D, LibPath + "/" + MultiarchTriple, Paths);
|
||||
addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Generic_GCC::AddMultiarchPaths(const Driver &D,
|
||||
const std::string &SysRoot,
|
||||
const std::string &OSLibDir,
|
||||
path_list &Paths) {
|
||||
// Try walking via the GCC triple path in case of biarch or multiarch GCC
|
||||
// installations with strange symlinks.
|
||||
if (GCCInstallation.isValid()) {
|
||||
addPathIfExists(D,
|
||||
SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
|
||||
"/../../" + OSLibDir,
|
||||
Paths);
|
||||
|
||||
// Add the 'other' biarch variant path
|
||||
Multilib BiarchSibling;
|
||||
if (GCCInstallation.getBiarchSibling(BiarchSibling)) {
|
||||
addPathIfExists(
|
||||
D, GCCInstallation.getInstallPath() + BiarchSibling.gccSuffix(),
|
||||
Paths);
|
||||
}
|
||||
|
||||
// See comments above on the multilib variant for details of why this is
|
||||
// included even from outside the sysroot.
|
||||
const std::string &LibPath =
|
||||
std::string(GCCInstallation.getParentLibPath());
|
||||
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
|
||||
const Multilib &Multilib = GCCInstallation.getMultilib();
|
||||
addPathIfExists(
|
||||
D, LibPath + "/../" + GCCTriple.str() + "/lib" + Multilib.osSuffix(),
|
||||
Paths);
|
||||
|
||||
// See comments above on the multilib variant for details of why this is
|
||||
// only included from within the sysroot.
|
||||
if (StringRef(LibPath).startswith(SysRoot))
|
||||
addPathIfExists(D, LibPath, Paths);
|
||||
}
|
||||
}
|
||||
|
||||
void Generic_GCC::AddMultilibIncludeArgs(const ArgList &DriverArgs,
|
||||
ArgStringList &CC1Args) const {
|
||||
// Add include directories specific to the selected multilib set and multilib.
|
||||
if (GCCInstallation.isValid()) {
|
||||
const auto &Callback = Multilibs.includeDirsCallback();
|
||||
if (Callback) {
|
||||
for (const auto &Path : Callback(GCCInstallation.getMultilib()))
|
||||
addExternCSystemIncludeIfExists(
|
||||
DriverArgs, CC1Args, GCCInstallation.getInstallPath() + Path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Generic_GCC::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
|
||||
ArgStringList &CC1Args) const {
|
||||
if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
|
||||
|
|
|
@ -314,6 +314,16 @@ protected:
|
|||
/// Check whether the target triple's architecture is 32-bits.
|
||||
bool isTarget32Bit() const { return getTriple().isArch32Bit(); }
|
||||
|
||||
void PushPPaths(ToolChain::path_list &PPaths);
|
||||
void AddMultilibPaths(const Driver &D, const std::string &SysRoot,
|
||||
const std::string &OSLibDir,
|
||||
const std::string &MultiarchTriple,
|
||||
path_list &Paths);
|
||||
void AddMultiarchPaths(const Driver &D, const std::string &SysRoot,
|
||||
const std::string &OSLibDir, path_list &Paths);
|
||||
void AddMultilibIncludeArgs(const llvm::opt::ArgList &DriverArgs,
|
||||
llvm::opt::ArgStringList &CC1Args) const;
|
||||
|
||||
// FIXME: This should be final, but the CrossWindows toolchain does weird
|
||||
// things that can't be easily generalized.
|
||||
void AddClangCXXStdlibIncludeArgs(
|
||||
|
|
|
@ -208,15 +208,6 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
|
|||
return Triple.isArch32Bit() ? "lib" : "lib64";
|
||||
}
|
||||
|
||||
static void addMultilibsFilePaths(const Driver &D, const MultilibSet &Multilibs,
|
||||
const Multilib &Multilib,
|
||||
StringRef InstallPath,
|
||||
ToolChain::path_list &Paths) {
|
||||
if (const auto &PathsCallback = Multilibs.filePathsCallback())
|
||||
for (const auto &Path : PathsCallback(Multilib))
|
||||
addPathIfExists(D, InstallPath + Path, Paths);
|
||||
}
|
||||
|
||||
Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
||||
: Generic_ELF(D, Triple, Args) {
|
||||
GCCInstallation.init(Triple, Args);
|
||||
|
@ -224,21 +215,9 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
|||
SelectedMultilib = GCCInstallation.getMultilib();
|
||||
llvm::Triple::ArchType Arch = Triple.getArch();
|
||||
std::string SysRoot = computeSysRoot();
|
||||
|
||||
// Cross-compiling binutils and GCC installations (vanilla and openSUSE at
|
||||
// least) put various tools in a triple-prefixed directory off of the parent
|
||||
// of the GCC installation. We use the GCC triple here to ensure that we end
|
||||
// up with tools that support the same amount of cross compiling as the
|
||||
// detected GCC installation. For example, if we find a GCC installation
|
||||
// targeting x86_64, but it is a bi-arch GCC installation, it can also be
|
||||
// used to target i386.
|
||||
// FIXME: This seems unlikely to be Linux-specific.
|
||||
ToolChain::path_list &PPaths = getProgramPaths();
|
||||
if (GCCInstallation.isValid()) {
|
||||
PPaths.push_back(Twine(GCCInstallation.getParentLibPath() + "/../" +
|
||||
GCCInstallation.getTriple().str() + "/bin")
|
||||
.str());
|
||||
}
|
||||
|
||||
Generic_GCC::PushPPaths(PPaths);
|
||||
|
||||
Distro Distro(D.getVFS(), Triple);
|
||||
|
||||
|
@ -316,58 +295,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
|||
const std::string OSLibDir = std::string(getOSLibDir(Triple, Args));
|
||||
const std::string MultiarchTriple = getMultiarchTriple(D, Triple, SysRoot);
|
||||
|
||||
// Add the multilib suffixed paths where they are available.
|
||||
if (GCCInstallation.isValid()) {
|
||||
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
|
||||
const std::string &LibPath =
|
||||
std::string(GCCInstallation.getParentLibPath());
|
||||
|
||||
// Add toolchain / multilib specific file paths.
|
||||
addMultilibsFilePaths(D, Multilibs, SelectedMultilib,
|
||||
GCCInstallation.getInstallPath(), Paths);
|
||||
|
||||
// Sourcery CodeBench MIPS toolchain holds some libraries under
|
||||
// a biarch-like suffix of the GCC installation.
|
||||
addPathIfExists(
|
||||
D, GCCInstallation.getInstallPath() + SelectedMultilib.gccSuffix(),
|
||||
Paths);
|
||||
|
||||
// GCC cross compiling toolchains will install target libraries which ship
|
||||
// as part of the toolchain under <prefix>/<triple>/<libdir> rather than as
|
||||
// any part of the GCC installation in
|
||||
// <prefix>/<libdir>/gcc/<triple>/<version>. This decision is somewhat
|
||||
// debatable, but is the reality today. We need to search this tree even
|
||||
// when we have a sysroot somewhere else. It is the responsibility of
|
||||
// whomever is doing the cross build targeting a sysroot using a GCC
|
||||
// installation that is *not* within the system root to ensure two things:
|
||||
//
|
||||
// 1) Any DSOs that are linked in from this tree or from the install path
|
||||
// above must be present on the system root and found via an
|
||||
// appropriate rpath.
|
||||
// 2) There must not be libraries installed into
|
||||
// <prefix>/<triple>/<libdir> unless they should be preferred over
|
||||
// those within the system root.
|
||||
//
|
||||
// Note that this matches the GCC behavior. See the below comment for where
|
||||
// Clang diverges from GCC's behavior.
|
||||
addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib/../" +
|
||||
OSLibDir + SelectedMultilib.osSuffix(),
|
||||
Paths);
|
||||
|
||||
// If the GCC installation we found is inside of the sysroot, we want to
|
||||
// prefer libraries installed in the parent prefix of the GCC installation.
|
||||
// It is important to *not* use these paths when the GCC installation is
|
||||
// outside of the system root as that can pick up unintended libraries.
|
||||
// This usually happens when there is an external cross compiler on the
|
||||
// host system, and a more minimal sysroot available that is the target of
|
||||
// the cross. Note that GCC does include some of these directories in some
|
||||
// configurations but this seems somewhere between questionable and simply
|
||||
// a bug.
|
||||
if (StringRef(LibPath).startswith(SysRoot)) {
|
||||
addPathIfExists(D, LibPath + "/" + MultiarchTriple, Paths);
|
||||
addPathIfExists(D, LibPath + "/../" + OSLibDir, Paths);
|
||||
}
|
||||
}
|
||||
Generic_GCC::AddMultilibPaths(D, SysRoot, OSLibDir, MultiarchTriple, Paths);
|
||||
|
||||
// Similar to the logic for GCC above, if we currently running Clang inside
|
||||
// of the requested system root, add its parent library paths to
|
||||
|
@ -411,37 +339,7 @@ Linux::Linux(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
|
|||
addPathIfExists(D, SysRoot + "/usr/" + OSLibDir + "/" + ABIName, Paths);
|
||||
}
|
||||
|
||||
// Try walking via the GCC triple path in case of biarch or multiarch GCC
|
||||
// installations with strange symlinks.
|
||||
if (GCCInstallation.isValid()) {
|
||||
addPathIfExists(D,
|
||||
SysRoot + "/usr/lib/" + GCCInstallation.getTriple().str() +
|
||||
"/../../" + OSLibDir,
|
||||
Paths);
|
||||
|
||||
// Add the 'other' biarch variant path
|
||||
Multilib BiarchSibling;
|
||||
if (GCCInstallation.getBiarchSibling(BiarchSibling)) {
|
||||
addPathIfExists(D, GCCInstallation.getInstallPath() +
|
||||
BiarchSibling.gccSuffix(),
|
||||
Paths);
|
||||
}
|
||||
|
||||
// See comments above on the multilib variant for details of why this is
|
||||
// included even from outside the sysroot.
|
||||
const std::string &LibPath =
|
||||
std::string(GCCInstallation.getParentLibPath());
|
||||
const llvm::Triple &GCCTriple = GCCInstallation.getTriple();
|
||||
const Multilib &Multilib = GCCInstallation.getMultilib();
|
||||
addPathIfExists(D, LibPath + "/../" + GCCTriple.str() + "/lib" +
|
||||
Multilib.osSuffix(),
|
||||
Paths);
|
||||
|
||||
// See comments above on the multilib variant for details of why this is
|
||||
// only included from within the sysroot.
|
||||
if (StringRef(LibPath).startswith(SysRoot))
|
||||
addPathIfExists(D, LibPath, Paths);
|
||||
}
|
||||
Generic_GCC::AddMultiarchPaths(D, SysRoot, OSLibDir, Paths);
|
||||
|
||||
// Similar to the logic for GCC above, if we are currently running Clang
|
||||
// inside of the requested system root, add its parent library path to those
|
||||
|
@ -684,15 +582,7 @@ void Linux::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
|
|||
// Lacking those, try to detect the correct set of system includes for the
|
||||
// target triple.
|
||||
|
||||
// Add include directories specific to the selected multilib set and multilib.
|
||||
if (GCCInstallation.isValid()) {
|
||||
const auto &Callback = Multilibs.includeDirsCallback();
|
||||
if (Callback) {
|
||||
for (const auto &Path : Callback(GCCInstallation.getMultilib()))
|
||||
addExternCSystemIncludeIfExists(
|
||||
DriverArgs, CC1Args, GCCInstallation.getInstallPath() + Path);
|
||||
}
|
||||
}
|
||||
AddMultilibIncludeArgs(DriverArgs, CC1Args);
|
||||
|
||||
// Implement generic Debian multiarch support.
|
||||
const StringRef X86_64MultiarchIncludeDirs[] = {
|
||||
|
|
Loading…
Reference in New Issue