Skip to content

Commit 621fed5

Browse files
committed
Fuse the two halves of the GCC installation detection. This is
significantly cleaner (IMO) and more principled. We now walk down each layer of the directory hierarchy searching for the GCC install. This change does in fact introduce a significant behavior change in theory, although in practice I don't know of any distro that will be impacted by it negatively, and Debian may (untested) get slightly better through it. Specifically, the logic now looks exhaustively for patterns such as: /usr/lib/<triple>/gcc/<triple> Previously, this would only be selected if there was *also* a '/usr/lib/gcc/<triple>' directory, or if '<triple>' were the excat DefaultHostTriple in the driver. There is a 4-deep nested loop here, but it doesn't do terribly many filesystem operations, as we skip at each layer of that layer's directory doesn't exist. There remains a significant FIXME in this logic: it would be much better to first build up a set of candidate components for each of the four layers with a bottom-up pruning such as this, but then select the final installation using a top-down algorithm in order to find the newest GCC installation available, regardless of which particular path leads to it. llvm-svn: 141071
1 parent 10996ef commit 621fed5

File tree

1 file changed

+74
-54
lines changed

1 file changed

+74
-54
lines changed

clang/lib/Driver/ToolChains.cpp

Lines changed: 74 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1536,17 +1536,19 @@ class GCCInstallationDetector {
15361536
}
15371537

15381538
llvm::Triple::ArchType HostArch = llvm::Triple(GccTriple).getArch();
1539-
// The directories which may contain x86-64 triple GCC installations.
1539+
// The library directories which may contain GCC installations.
15401540
SmallVector<StringRef, 2> CandidateLibDirs;
1541-
// The compatible GCC triples for an x86-64 Linux Clang.
1541+
// The compatible GCC triples for this particular architecture.
15421542
SmallVector<StringRef, 10> CandidateTriples;
15431543
if (HostArch == llvm::Triple::arm || HostArch == llvm::Triple::thumb) {
1544-
static const char *const LibDirs[] = { "/usr/lib/gcc" };
1544+
static const char *const LibDirs[] = { "/lib/gcc" };
15451545
static const char *const Triples[] = { "arm-linux-gnueabi" };
15461546
CandidateLibDirs.append(LibDirs, LibDirs + llvm::array_lengthof(LibDirs));
15471547
CandidateTriples.append(Triples, Triples + llvm::array_lengthof(Triples));
15481548
} else if (HostArch == llvm::Triple::x86_64) {
1549-
static const char *const LibDirs[] = { "/usr/lib64/gcc", "/usr/lib/gcc" };
1549+
static const char *const LibDirs[] = {
1550+
"/lib64/gcc", "/lib/gcc", "/lib64", "/lib"
1551+
};
15501552
static const char *const Triples[] = {
15511553
"x86_64-linux-gnu",
15521554
"x86_64-unknown-linux-gnu",
@@ -1561,7 +1563,9 @@ class GCCInstallationDetector {
15611563
CandidateLibDirs.append(LibDirs, LibDirs + llvm::array_lengthof(LibDirs));
15621564
CandidateTriples.append(Triples, Triples + llvm::array_lengthof(Triples));
15631565
} else if (HostArch == llvm::Triple::x86) {
1564-
static const char *const LibDirs[] = { "/usr/lib32/gcc", "/usr/lib/gcc" };
1566+
static const char *const LibDirs[] = {
1567+
"/lib32/gcc", "/lib/gcc", "/lib32", "/lib"
1568+
};
15651569
static const char *const Triples[] = {
15661570
"i686-linux-gnu",
15671571
"i386-linux-gnu",
@@ -1574,35 +1578,27 @@ class GCCInstallationDetector {
15741578
CandidateLibDirs.append(LibDirs, LibDirs + llvm::array_lengthof(LibDirs));
15751579
CandidateTriples.append(Triples, Triples + llvm::array_lengthof(Triples));
15761580
} else if (HostArch == llvm::Triple::ppc) {
1577-
static const char *const LibDirs[] = { "/usr/lib32/gcc", "/usr/lib/gcc" };
1581+
static const char *const LibDirs[] = {
1582+
"/lib32/gcc", "/lib/gcc", "/lib32", "/lib"
1583+
};
15781584
static const char *const Triples[] = {
15791585
"powerpc-linux-gnu",
15801586
"powerpc-unknown-linux-gnu"
15811587
};
15821588
CandidateLibDirs.append(LibDirs, LibDirs + llvm::array_lengthof(LibDirs));
15831589
CandidateTriples.append(Triples, Triples + llvm::array_lengthof(Triples));
15841590
} else if (HostArch == llvm::Triple::ppc64) {
1585-
static const char *const LibDirs[] = { "/usr/lib64/gcc", "/usr/lib/gcc" };
1591+
static const char *const LibDirs[] = {
1592+
"/lib64/gcc", "/lib/gcc", "/lib64", "/lib"
1593+
};
15861594
static const char *const Triples[] = { "powerpc64-unknown-linux-gnu" };
15871595
CandidateLibDirs.append(LibDirs, LibDirs + llvm::array_lengthof(LibDirs));
15881596
CandidateTriples.append(Triples, Triples + llvm::array_lengthof(Triples));
15891597
}
15901598

1591-
// First finds the 'prefix' which exists beneath the system root. Second,
1592-
// finds the first triple which exists beneath that prefix.
1593-
StringRef DetectedGccPrefix, DetectedGccTriple;
1594-
for (unsigned i = 0, ie = CandidateLibDirs.size(); i < ie; ++i) {
1595-
if (!PathExists(CandidateLibDirs[i]))
1596-
continue;
1597-
1598-
for (unsigned j = 0, je = CandidateTriples.size(); j < je; ++j) {
1599-
if (PathExists(CandidateLibDirs[i].str() + "/" +
1600-
CandidateTriples[j].str())) {
1601-
DetectedGccPrefix = CandidateLibDirs[i];
1602-
DetectedGccTriple = CandidateTriples[j];
1603-
}
1604-
}
1605-
}
1599+
// Always include the default host triple as the final fallback if no
1600+
// specific triple is detected.
1601+
CandidateTriples.push_back(D.DefaultHostTriple);
16061602

16071603
static const char* GccVersions[] = {
16081604
"4.6.1", "4.6.0", "4.6",
@@ -1611,40 +1607,64 @@ class GCCInstallationDetector {
16111607
"4.3.4", "4.3.3", "4.3.2", "4.3",
16121608
"4.2.4", "4.2.3", "4.2.2", "4.2.1", "4.2",
16131609
"4.1.1"};
1614-
SmallVector<std::string, 8> Paths(D.PrefixDirs.begin(),
1615-
D.PrefixDirs.end());
1616-
Paths.push_back(D.SysRoot + "/usr/");
1617-
const std::string Triples[] = {DetectedGccTriple.str(), D.DefaultHostTriple};
1618-
IsValid = true; // In case we're able to find a GCC install.
1619-
for (SmallVector<std::string, 8>::const_iterator I = Paths.begin(),
1620-
E = Paths.end();
1621-
I != E; ++I) {
1622-
for (unsigned i = 0; i < sizeof(GccVersions)/sizeof(char*); ++i) {
1623-
for (unsigned j = 0; j < sizeof(Triples)/sizeof(Triples[0]); ++j) {
1624-
GccTriple = Triples[j];
1625-
std::string Suffix = Triples[j] + "/" + GccVersions[i];
1626-
GccInstallPath = *I + "lib/gcc/" + Suffix;
1627-
GccParentLibPath = GccInstallPath + "/../../..";
1628-
if (PathExists(GccInstallPath + "/crtbegin.o"))
1629-
return;
1630-
GccInstallPath = *I + "lib64/gcc/" + Suffix;
1631-
GccParentLibPath = GccInstallPath + "/../../..";
1632-
if (PathExists(GccInstallPath + "/crtbegin.o"))
1633-
return;
1634-
GccInstallPath = *I + "lib/" + GccTriple + "/gcc/" + Suffix;
1635-
GccParentLibPath = GccInstallPath + "/../../../..";
1636-
if (PathExists(GccInstallPath + "/crtbegin.o"))
1637-
return;
1638-
1639-
if (GccTriple != "i386-linux-gnu")
1610+
1611+
// Set this as valid so we can early exit from the loops if we find
1612+
// a viable installation.
1613+
IsValid = true;
1614+
1615+
SmallVector<std::string, 8> Prefixes(D.PrefixDirs.begin(),
1616+
D.PrefixDirs.end());
1617+
Prefixes.push_back(D.SysRoot + "/usr");
1618+
// FIXME: This entire nested loop structure is broken. The structure is
1619+
// well suited to quickly pruning impossible (non-existent) sub-trees, but
1620+
// doesn't find all viable GCC installations and choose the best one. We
1621+
// should invert this, and prune the impossible subtrees bottom-up, but
1622+
// then select the best GCC installation top-down so that we prefer the
1623+
// newest GCC, the most accurate triple, and only at the end select the lib
1624+
// and prefix directories containing that installation.
1625+
for (SmallVectorImpl<std::string>::const_iterator PI = Prefixes.begin(),
1626+
PE = Prefixes.end();
1627+
PI != PE; ++PI) {
1628+
if (!PathExists(*PI))
1629+
continue;
1630+
1631+
// First finds the 'prefix' which exists beneath the system root. Second,
1632+
// finds the first triple which exists beneath that prefix.
1633+
StringRef DetectedGccPrefix, DetectedGccTriple;
1634+
for (unsigned i = 0, ie = CandidateLibDirs.size(); i < ie; ++i) {
1635+
const std::string LibDir = *PI + CandidateLibDirs[i].str();
1636+
if (!PathExists(LibDir))
1637+
continue;
1638+
1639+
for (unsigned j = 0, je = CandidateTriples.size(); j < je; ++j) {
1640+
GccTriple = CandidateTriples[j];
1641+
const std::string TripleDir = LibDir + "/" + GccTriple;
1642+
if (!PathExists(TripleDir))
16401643
continue;
16411644

1642-
// Ubuntu 11.04 uses an unusual path.
1643-
GccInstallPath = *I + "lib/i386-linux-gnu/gcc/i686-linux-gnu/" +
1644-
GccVersions[i];
1645-
GccParentLibPath = GccInstallPath + "/../../../..";
1646-
if (PathExists(GccInstallPath + "/crtbegin.o"))
1647-
return;
1645+
for (unsigned k = 0; k < llvm::array_lengthof(GccVersions); ++k) {
1646+
GccInstallPath = TripleDir + "/" + GccVersions[k];
1647+
GccParentLibPath = GccInstallPath + "/../../..";
1648+
if (PathExists(GccInstallPath + "/crtbegin.o"))
1649+
return;
1650+
1651+
// Try an install directory with an extra triple in it.
1652+
GccInstallPath =
1653+
TripleDir + "/gcc/" + GccTriple + "/" + GccVersions[k];
1654+
GccParentLibPath = GccInstallPath + "/../../../..";
1655+
if (PathExists(GccInstallPath + "/crtbegin.o"))
1656+
return;
1657+
1658+
if (GccTriple != "i386-linux-gnu")
1659+
continue;
1660+
1661+
// Ubuntu 11.04 uses an unusual path.
1662+
GccInstallPath =
1663+
TripleDir + "/gcc/i686-linux-gnu/" + GccVersions[k];
1664+
GccParentLibPath = GccInstallPath + "/../../../..";
1665+
if (PathExists(GccInstallPath + "/crtbegin.o"))
1666+
return;
1667+
}
16481668
}
16491669
}
16501670
}

0 commit comments

Comments
 (0)