Skip to content

Commit 9f97720

Browse files
committed
[clang][driver] Dynamically select gcc-toolset/devtoolset
Instead of adding all devtoolset and gcc-toolset prefixes to the list of prefixes, just scan the /opt/rh/ directory for the one with the highest version number and only add that one. Differential Revision: https://reviews.llvm.org/D125862
1 parent b34fb27 commit 9f97720

File tree

2 files changed

+116
-11
lines changed

2 files changed

+116
-11
lines changed

clang/lib/Driver/ToolChains/Gnu.cpp

+25-11
Original file line numberDiff line numberDiff line change
@@ -2130,17 +2130,31 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
21302130
// and gcc-toolsets.
21312131
if (SysRoot.empty() && TargetTriple.getOS() == llvm::Triple::Linux &&
21322132
D.getVFS().exists("/opt/rh")) {
2133-
Prefixes.push_back("/opt/rh/gcc-toolset-11/root/usr");
2134-
Prefixes.push_back("/opt/rh/gcc-toolset-10/root/usr");
2135-
Prefixes.push_back("/opt/rh/devtoolset-11/root/usr");
2136-
Prefixes.push_back("/opt/rh/devtoolset-10/root/usr");
2137-
Prefixes.push_back("/opt/rh/devtoolset-9/root/usr");
2138-
Prefixes.push_back("/opt/rh/devtoolset-8/root/usr");
2139-
Prefixes.push_back("/opt/rh/devtoolset-7/root/usr");
2140-
Prefixes.push_back("/opt/rh/devtoolset-6/root/usr");
2141-
Prefixes.push_back("/opt/rh/devtoolset-4/root/usr");
2142-
Prefixes.push_back("/opt/rh/devtoolset-3/root/usr");
2143-
Prefixes.push_back("/opt/rh/devtoolset-2/root/usr");
2133+
// Find the directory in /opt/rh/ starting with gcc-toolset-* or
2134+
// devtoolset-* with the highest version number and add that
2135+
// one to our prefixes.
2136+
std::string ChosenToolsetDir;
2137+
unsigned ChosenToolsetVersion = 0;
2138+
std::error_code EC;
2139+
for (llvm::vfs::directory_iterator LI = D.getVFS().dir_begin("/opt/rh", EC),
2140+
LE;
2141+
!EC && LI != LE; LI = LI.increment(EC)) {
2142+
StringRef ToolsetDir = llvm::sys::path::filename(LI->path());
2143+
unsigned ToolsetVersion;
2144+
if ((!ToolsetDir.startswith("gcc-toolset-") &&
2145+
!ToolsetDir.startswith("devtoolset-")) ||
2146+
ToolsetDir.substr(ToolsetDir.rfind('-') + 1)
2147+
.getAsInteger(10, ToolsetVersion))
2148+
continue;
2149+
2150+
if (ToolsetVersion > ChosenToolsetVersion) {
2151+
ChosenToolsetVersion = ToolsetVersion;
2152+
ChosenToolsetDir = "/opt/rh/" + ToolsetDir.str();
2153+
}
2154+
}
2155+
2156+
if (ChosenToolsetVersion > 0)
2157+
Prefixes.push_back(ChosenToolsetDir);
21442158
}
21452159

21462160
// Fall back to /usr which is used by most non-Solaris systems.

clang/unittests/Driver/ToolChainTest.cpp

+91
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "clang/Driver/Driver.h"
1919
#include "llvm/ADT/ArrayRef.h"
2020
#include "llvm/MC/TargetRegistry.h"
21+
#include "llvm/Support/Host.h"
2122
#include "llvm/Support/TargetSelect.h"
2223
#include "llvm/Support/VirtualFileSystem.h"
2324
#include "llvm/Support/raw_ostream.h"
@@ -561,4 +562,94 @@ TEST(DxcModeTest, ValidatorVersionValidation) {
561562
DiagConsumer->clear();
562563
}
563564

565+
TEST(ToolChainTest, Toolsets) {
566+
// Ignore this test on Windows hosts.
567+
llvm::Triple Host(llvm::sys::getProcessTriple());
568+
if (Host.isOSWindows())
569+
GTEST_SKIP();
570+
571+
IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions();
572+
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
573+
574+
// Check (newer) GCC toolset installation.
575+
{
576+
IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
577+
new llvm::vfs::InMemoryFileSystem);
578+
579+
// These should be ignored.
580+
InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-2", 0,
581+
llvm::MemoryBuffer::getMemBuffer("\n"));
582+
InMemoryFileSystem->addFile("/opt/rh/gcc-toolset-", 0,
583+
llvm::MemoryBuffer::getMemBuffer("\n"));
584+
InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--", 0,
585+
llvm::MemoryBuffer::getMemBuffer("\n"));
586+
InMemoryFileSystem->addFile("/opt/rh/gcc-toolset--1", 0,
587+
llvm::MemoryBuffer::getMemBuffer("\n"));
588+
589+
// File needed for GCC installation detection.
590+
InMemoryFileSystem->addFile(
591+
"/opt/rh/gcc-toolset-12/lib/gcc/x86_64-redhat-linux/11/crtbegin.o", 0,
592+
llvm::MemoryBuffer::getMemBuffer("\n"));
593+
594+
DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer);
595+
Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags,
596+
"clang LLVM compiler", InMemoryFileSystem);
597+
std::unique_ptr<Compilation> C(
598+
TheDriver.BuildCompilation({"--gcc-toolchain="}));
599+
ASSERT_TRUE(C);
600+
std::string S;
601+
{
602+
llvm::raw_string_ostream OS(S);
603+
C->getDefaultToolChain().printVerboseInfo(OS);
604+
}
605+
EXPECT_EQ("Found candidate GCC installation: "
606+
"/opt/rh/gcc-toolset-12/lib/gcc/x86_64-redhat-linux/11\n"
607+
"Selected GCC installation: "
608+
"/opt/rh/gcc-toolset-12/lib/gcc/x86_64-redhat-linux/11\n"
609+
"Candidate multilib: .;@m64\n"
610+
"Selected multilib: .;@m64\n",
611+
S);
612+
}
613+
614+
// And older devtoolset.
615+
{
616+
IntrusiveRefCntPtr<llvm::vfs::InMemoryFileSystem> InMemoryFileSystem(
617+
new llvm::vfs::InMemoryFileSystem);
618+
619+
// These should be ignored.
620+
InMemoryFileSystem->addFile("/opt/rh/devtoolset-2", 0,
621+
llvm::MemoryBuffer::getMemBuffer("\n"));
622+
InMemoryFileSystem->addFile("/opt/rh/devtoolset-", 0,
623+
llvm::MemoryBuffer::getMemBuffer("\n"));
624+
InMemoryFileSystem->addFile("/opt/rh/devtoolset--", 0,
625+
llvm::MemoryBuffer::getMemBuffer("\n"));
626+
InMemoryFileSystem->addFile("/opt/rh/devtoolset--1", 0,
627+
llvm::MemoryBuffer::getMemBuffer("\n"));
628+
629+
// File needed for GCC installation detection.
630+
InMemoryFileSystem->addFile(
631+
"/opt/rh/devtoolset-12/lib/gcc/x86_64-redhat-linux/11/crtbegin.o", 0,
632+
llvm::MemoryBuffer::getMemBuffer("\n"));
633+
634+
DiagnosticsEngine Diags(DiagID, &*DiagOpts, new SimpleDiagnosticConsumer);
635+
Driver TheDriver("/bin/clang", "x86_64-redhat-linux", Diags,
636+
"clang LLVM compiler", InMemoryFileSystem);
637+
std::unique_ptr<Compilation> C(
638+
TheDriver.BuildCompilation({"--gcc-toolchain="}));
639+
ASSERT_TRUE(C);
640+
std::string S;
641+
{
642+
llvm::raw_string_ostream OS(S);
643+
C->getDefaultToolChain().printVerboseInfo(OS);
644+
}
645+
EXPECT_EQ("Found candidate GCC installation: "
646+
"/opt/rh/devtoolset-12/lib/gcc/x86_64-redhat-linux/11\n"
647+
"Selected GCC installation: "
648+
"/opt/rh/devtoolset-12/lib/gcc/x86_64-redhat-linux/11\n"
649+
"Candidate multilib: .;@m64\n"
650+
"Selected multilib: .;@m64\n",
651+
S);
652+
}
653+
}
654+
564655
} // end anonymous namespace.

0 commit comments

Comments
 (0)