diff options
Diffstat (limited to 'clang/lib/Driver/ToolChains/Gnu.cpp')
-rw-r--r-- | clang/lib/Driver/ToolChains/Gnu.cpp | 235 |
1 files changed, 136 insertions, 99 deletions
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index d7cc101a60f..367dc190006 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -1450,6 +1450,8 @@ static bool findBiarchMultilibs(const Driver &D, StringRef Path, const ArgList &Args, bool NeedsBiarchSuffix, DetectedMultilibs &Result) { + Multilib Default; + // Some versions of SUSE and Fedora on ppc64 put 32-bit libs // in what would normally be GCCInstallPath and put the 64-bit // libs in a subdirectory named 64. The simple logic we follow is that @@ -1457,10 +1459,26 @@ static bool findBiarchMultilibs(const Driver &D, // we use that. If not, and if not a biarch triple alias, we look for // crtbegin.o without the subdirectory. - Multilib Default; + StringRef Suff64 = "/64"; + // Solaris uses platform-specific suffixes instead of /64. + if (TargetTriple.getOS() == llvm::Triple::Solaris) { + switch (TargetTriple.getArch()) { + case llvm::Triple::x86: + case llvm::Triple::x86_64: + Suff64 = "/amd64"; + break; + case llvm::Triple::sparc: + case llvm::Triple::sparcv9: + Suff64 = "/sparcv9"; + break; + default: + break; + } + } + Multilib Alt64 = Multilib() - .gccSuffix("/64") - .includeSuffix("/64") + .gccSuffix(Suff64) + .includeSuffix(Suff64) .flag("-m32") .flag("+m64") .flag("-mx32"); @@ -1657,21 +1675,17 @@ void Generic_GCC::GCCInstallationDetector::init( // If we have a SysRoot, try that first. if (!D.SysRoot.empty()) { Prefixes.push_back(D.SysRoot); - Prefixes.push_back(D.SysRoot + "/usr"); + AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot); } // Then look for gcc installed alongside clang. Prefixes.push_back(D.InstalledDir + "/.."); - // Then look for distribution supplied gcc installations. + // Next, look for prefix(es) that correspond to distribution-supplied gcc + // installations. if (D.SysRoot.empty()) { - // Look for RHEL devtoolsets. - Prefixes.push_back("/opt/rh/devtoolset-6/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-4/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-3/root/usr"); - Prefixes.push_back("/opt/rh/devtoolset-2/root/usr"); - // And finally in /usr. - Prefixes.push_back("/usr"); + // Typically /usr. + AddDefaultGCCPrefixes(TargetTriple, Prefixes, D.SysRoot); } } @@ -1742,6 +1756,51 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { return false; } +void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes( + const llvm::Triple &TargetTriple, SmallVectorImpl<std::string> &Prefixes, + StringRef SysRoot) { + if (TargetTriple.getOS() == llvm::Triple::Solaris) { + // Solaris is a special case. + // The GCC installation is under + // /usr/gcc/<major>.<minor>/lib/gcc/<triple>/<major>.<minor>.<patch>/ + // 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::error_code EC; + for (vfs::directory_iterator LI = D.getVFS().dir_begin(PrefixDir, EC), LE; + !EC && LI != LE; LI = LI.increment(EC)) { + StringRef VersionText = llvm::sys::path::filename(LI->getName()); + GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); + + // Filter out obviously bad entries. + if (CandidateVersion.Major == -1 || CandidateVersion.isOlderThan(4, 1, 1)) + continue; + + std::string CandidatePrefix = PrefixDir + "/" + VersionText.str(); + std::string CandidateLibPath = CandidatePrefix + "/lib/gcc"; + if (!D.getVFS().exists(CandidateLibPath)) + continue; + + Prefixes.push_back(CandidatePrefix); + } + return; + } + + // Non-Solaris is much simpler - most systems just go with "/usr". + if (SysRoot.empty()) { + // Yet, still look for RHEL devtoolsets + // (should it be done Linux-only??) + Prefixes.push_back("/opt/rh/devtoolset-6/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-4/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-3/root/usr"); + Prefixes.push_back("/opt/rh/devtoolset-2/root/usr"); + Prefixes.push_back("/usr"); + } else { + Prefixes.push_back(SysRoot.str() + "/usr"); + } +} + /*static*/ void Generic_GCC::GCCInstallationDetector::CollectLibDirsAndTriples( const llvm::Triple &TargetTriple, const llvm::Triple &BiarchTriple, SmallVectorImpl<StringRef> &LibDirs, @@ -1843,17 +1902,49 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { "s390x-linux-gnu", "s390x-unknown-linux-gnu", "s390x-ibm-linux-gnu", "s390x-suse-linux", "s390x-redhat-linux"}; - // Solaris. - static const char *const SolarisSPARCLibDirs[] = {"/gcc"}; - static const char *const SolarisSPARCTriples[] = {"sparc-sun-solaris2.11", - "i386-pc-solaris2.11"}; using std::begin; using std::end; if (TargetTriple.getOS() == llvm::Triple::Solaris) { - LibDirs.append(begin(SolarisSPARCLibDirs), end(SolarisSPARCLibDirs)); - TripleAliases.append(begin(SolarisSPARCTriples), end(SolarisSPARCTriples)); + static const char *const SolarisLibDirs[] = {"/lib"}; + static const char *const SolarisSparcV8Triples[] = { + "sparc-sun-solaris2.11", "sparc-sun-solaris2.12"}; + static const char *const SolarisSparcV9Triples[] = { + "sparcv9-sun-solaris2.11", "sparcv9-sun-solaris2.12"}; + static const char *const SolarisX86Triples[] = {"i386-pc-solaris2.11", + "i386-pc-solaris2.12"}; + static const char *const SolarisX86_64Triples[] = {"x86_64-pc-solaris2.11", + "x86_64-pc-solaris2.12"}; + LibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs)); + BiarchLibDirs.append(begin(SolarisLibDirs), end(SolarisLibDirs)); + switch (TargetTriple.getArch()) { + case llvm::Triple::x86: + TripleAliases.append(begin(SolarisX86Triples), end(SolarisX86Triples)); + BiarchTripleAliases.append(begin(SolarisX86_64Triples), + end(SolarisX86_64Triples)); + break; + case llvm::Triple::x86_64: + TripleAliases.append(begin(SolarisX86_64Triples), + end(SolarisX86_64Triples)); + BiarchTripleAliases.append(begin(SolarisX86Triples), + end(SolarisX86Triples)); + break; + case llvm::Triple::sparc: + TripleAliases.append(begin(SolarisSparcV8Triples), + end(SolarisSparcV8Triples)); + BiarchTripleAliases.append(begin(SolarisSparcV9Triples), + end(SolarisSparcV9Triples)); + break; + case llvm::Triple::sparcv9: + TripleAliases.append(begin(SolarisSparcV9Triples), + end(SolarisSparcV9Triples)); + BiarchTripleAliases.append(begin(SolarisSparcV8Triples), + end(SolarisSparcV8Triples)); + break; + default: + break; + } return; } @@ -2014,56 +2105,6 @@ bool Generic_GCC::GCCInstallationDetector::getBiarchSibling(Multilib &M) const { BiarchTripleAliases.push_back(BiarchTriple.str()); } -void Generic_GCC::GCCInstallationDetector::scanLibDirForGCCTripleSolaris( - const llvm::Triple &TargetArch, const llvm::opt::ArgList &Args, - const std::string &LibDir, StringRef CandidateTriple, - bool NeedsBiarchSuffix) { - // Solaris is a special case. The GCC installation is under - // /usr/gcc/<major>.<minor>/lib/gcc/<triple>/<major>.<minor>.<patch>/, so we - // need to iterate twice. - std::error_code EC; - for (vfs::directory_iterator LI = D.getVFS().dir_begin(LibDir, EC), LE; - !EC && LI != LE; LI = LI.increment(EC)) { - StringRef VersionText = llvm::sys::path::filename(LI->getName()); - GCCVersion CandidateVersion = GCCVersion::Parse(VersionText); - - if (CandidateVersion.Major != -1) // Filter obviously bad entries. - if (!CandidateGCCInstallPaths.insert(LI->getName()).second) - continue; // Saw this path before; no need to look at it again. - if (CandidateVersion.isOlderThan(4, 1, 1)) - continue; - if (CandidateVersion <= Version) - continue; - - GCCInstallPath = - LibDir + "/" + VersionText.str() + "/lib/gcc/" + CandidateTriple.str(); - if (!D.getVFS().exists(GCCInstallPath)) - continue; - - // If we make it here there has to be at least one GCC version, let's just - // use the latest one. - std::error_code EEC; - for (vfs::directory_iterator - LLI = D.getVFS().dir_begin(GCCInstallPath, EEC), - LLE; - !EEC && LLI != LLE; LLI = LLI.increment(EEC)) { - - StringRef SubVersionText = llvm::sys::path::filename(LLI->getName()); - GCCVersion CandidateSubVersion = GCCVersion::Parse(SubVersionText); - - if (CandidateSubVersion > Version) - Version = CandidateSubVersion; - } - - GCCTriple.setTriple(CandidateTriple); - - GCCInstallPath += "/" + Version.Text; - GCCParentLibPath = GCCInstallPath + "/../../../../"; - - IsValid = true; - } -} - bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs( const llvm::Triple &TargetTriple, const ArgList &Args, StringRef Path, bool NeedsBiarchSuffix) { @@ -2097,12 +2138,6 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( const llvm::Triple &TargetTriple, const ArgList &Args, const std::string &LibDir, StringRef CandidateTriple, bool NeedsBiarchSuffix) { - if (TargetTriple.getOS() == llvm::Triple::Solaris) { - scanLibDirForGCCTripleSolaris(TargetTriple, Args, LibDir, CandidateTriple, - NeedsBiarchSuffix); - return; - } - llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); // Locations relative to the system lib directory where GCC's triple-specific // directories might reside. @@ -2115,31 +2150,33 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( // Whether this library suffix is relevant for the triple. bool Active; } Suffixes[] = { - // This is the normal place. - {"gcc/" + CandidateTriple.str(), "../..", true}, - - // Debian puts cross-compilers in gcc-cross. - {"gcc-cross/" + CandidateTriple.str(), "../..", true}, - - // The Freescale PPC SDK has the gcc libraries in - // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well. Only do - // this on Freescale triples, though, since some systems put a *lot* of - // files in that location, not just GCC installation data. - {CandidateTriple.str(), "..", - TargetTriple.getVendor() == llvm::Triple::Freescale}, - - // Natively multiarch systems sometimes put the GCC triple-specific - // directory within their multiarch lib directory, resulting in the - // triple appearing twice. - {CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), "../../..", true}, - - // Deal with cases (on Ubuntu) where the system architecture could be i386 - // but the GCC target architecture could be (say) i686. - // FIXME: It may be worthwhile to generalize this and look for a second - // triple. - {"i386-linux-gnu/gcc/" + CandidateTriple.str(), "../../..", - TargetArch == llvm::Triple::x86} - }; + // This is the normal place. + {"gcc/" + CandidateTriple.str(), "../..", true}, + + // Debian puts cross-compilers in gcc-cross. + {"gcc-cross/" + CandidateTriple.str(), "../..", + TargetTriple.getOS() != llvm::Triple::Solaris}, + + // The Freescale PPC SDK has the gcc libraries in + // <sysroot>/usr/lib/<triple>/x.y.z so have a look there as well. Only do + // this on Freescale triples, though, since some systems put a *lot* of + // files in that location, not just GCC installation data. + {CandidateTriple.str(), "..", + TargetTriple.getVendor() == llvm::Triple::Freescale}, + + // Natively multiarch systems sometimes put the GCC triple-specific + // directory within their multiarch lib directory, resulting in the + // triple appearing twice. + {CandidateTriple.str() + "/gcc/" + CandidateTriple.str(), "../../..", + TargetTriple.getOS() != llvm::Triple::Solaris}, + + // Deal with cases (on Ubuntu) where the system architecture could be i386 + // but the GCC target architecture could be (say) i686. + // FIXME: It may be worthwhile to generalize this and look for a second + // triple. + {"i386-linux-gnu/gcc/" + CandidateTriple.str(), "../../..", + (TargetArch == llvm::Triple::x86 && + TargetTriple.getOS() != llvm::Triple::Solaris)}}; for (auto &Suffix : Suffixes) { if (!Suffix.Active) |