Fix part of PR11223 and probably a few dups as well. This teaches the

library search logic to "properly" handle multiarch installations. I've
tested this on both Debian unstable and the latest Ubuntu which both use
this setup, and this appears to work largely the same way as GCC does.
It isn't exactly the same, but it is close enough and more principled in
its behavior where it differs. This should resolve any failures to find
'crt1.o' etc on Debian-based Linux distributions. If folks find more
cases where we fail, please file bugs and CC me.

Test cases for all of the debian silliness are waiting both to simplify
the process of merging these down into the 3.0 release, and because
they're so crazy I haven't yet been able to really produce a fake tree
that represents what we need to test for. I'll eventually add them
though.

llvm-svn: 143344
This commit is contained in:
Chandler Carruth 2011-10-31 08:42:24 +00:00
parent 3b36df5556
commit fb7fa24e5c
1 changed files with 42 additions and 4 deletions

View File

@ -1740,6 +1740,41 @@ static void addPathIfExists(const std::string &Path,
if (PathExists(Path)) Paths.push_back(Path);
}
/// \brief Get our best guess at the multiarch triple for a target.
///
/// Debian-based systems are starting to use a multiarch setup where they use
/// 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 llvm::Triple TargetTriple,
StringRef SysRoot) {
// For most architectures, just use whatever we have rather than trying to be
// clever.
switch (TargetTriple.getArch()) {
default:
return TargetTriple.str();
// We use the existence of '/lib/<triple>' as a directory to detect some
// common linux triples that don't quite match the Clang triple for both
// 32-bit and 64-bit targets. This works around annoying discrepancies on
// Debian-based systems.
case llvm::Triple::x86:
if (llvm::sys::fs::exists(SysRoot + "/lib/i686-linux-gnu"))
return "i686-linux-gnu";
if (llvm::sys::fs::exists(SysRoot + "/lib/i386-linux-gnu"))
return "i386-linux-gnu";
return TargetTriple.str();
case llvm::Triple::x86_64:
if (llvm::sys::fs::exists(SysRoot + "/lib/x86_64-linux-gnu"))
return "x86_64-linux-gnu";
if (llvm::sys::fs::exists(SysRoot + "/lib/x86_64-pc-linux-gnu"))
return "x86_64-pc-linux-gnu";
if (llvm::sys::fs::exists(SysRoot + "/lib/x86_64-unknown-linux-gnu"))
return "x86_64-unknown-linux-gnu";
return TargetTriple.str();
}
}
Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple)
: Generic_ELF(Host, Triple) {
llvm::Triple::ArchType Arch =
@ -1800,6 +1835,7 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple)
const std::string Suffix64 = Arch == llvm::Triple::x86_64 ? "" : "/64";
const std::string Suffix = Is32Bits ? Suffix32 : Suffix64;
const std::string Multilib = Is32Bits ? "lib32" : "lib64";
const std::string MultiarchTriple = getMultiarchTriple(Triple, SysRoot);
// FIXME: Because we add paths only when they exist on the system, I think we
// should remove the concept of 'HasMultilib'. It's more likely to break the
@ -1817,9 +1853,12 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple)
addPathIfExists(GCCInstallation.getInstallPath() + Suffix, Paths);
addPathIfExists(LibPath + "/../" + GccTriple + "/lib/../" + Multilib,
Paths);
addPathIfExists(LibPath + "/" + MultiarchTriple, Paths);
addPathIfExists(LibPath + "/../" + Multilib, Paths);
}
addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths);
addPathIfExists(SysRoot + "/lib/../" + Multilib, Paths);
addPathIfExists(SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
addPathIfExists(SysRoot + "/usr/lib/../" + Multilib, Paths);
// Try walking via the GCC triple path in case of multiarch GCC
@ -1836,14 +1875,13 @@ Linux::Linux(const HostInfo &Host, const llvm::Triple &Triple)
if (!Suffix.empty() || !HasMultilib(Arch, Distro))
addPathIfExists(GCCInstallation.getInstallPath(), Paths);
addPathIfExists(LibPath + "/../" + GccTriple + "/lib", Paths);
addPathIfExists(LibPath + "/" + MultiarchTriple, Paths);
addPathIfExists(LibPath, Paths);
}
addPathIfExists(SysRoot + "/lib/" + MultiarchTriple, Paths);
addPathIfExists(SysRoot + "/lib", Paths);
addPathIfExists(SysRoot + "/usr/lib/" + MultiarchTriple, Paths);
addPathIfExists(SysRoot + "/usr/lib", Paths);
// Add a multiarch lib directory whenever it exists and is plausible.
if (GCCInstallation.isValid() && Arch == getArch())
addPathIfExists(SysRoot + "/usr/lib/" + GCCInstallation.getTriple(), Paths);
}
bool Linux::HasNativeLLVMSupport() const {