diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 38971288e38f4..eb32f4b920b55 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -1955,7 +1955,8 @@ void Generic_GCC::GCCInstallationDetector::init( // Loop over the various components which exist and select the best GCC // installation available. GCC installs are ranked by version number. - Version = GCCVersion::Parse("0.0.0"); + const GCCVersion VersionZero = GCCVersion::Parse("0.0.0"); + Version = VersionZero; for (const std::string &Prefix : Prefixes) { auto &VFS = D.getVFS(); if (!VFS.exists(Prefix)) @@ -1988,6 +1989,10 @@ void Generic_GCC::GCCInstallationDetector::init( ScanLibDirForGCCTriple(TargetTriple, Args, LibDir, Candidate, true, GCCDirExists, GCCCrossDirExists); } + + // Skip other prefixes once a GCC installation is found. + if (Version > VersionZero) + break; } } diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index eba09d2970ccc..1aa9557374381 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -507,28 +507,6 @@ // CHECK-64-TO-32-SYSROOT: "-L[[SYSROOT]]/lib" // CHECK-64-TO-32-SYSROOT: "-L[[SYSROOT]]/usr/lib" // -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: --target=i386-unknown-linux -rtlib=platform -m32 \ -// RUN: -ccc-install-dir %S/Inputs/fake_install_tree/bin \ -// RUN: --gcc-toolchain="" \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: | FileCheck --check-prefix=CHECK-INSTALL-DIR-32 %s -// CHECK-INSTALL-DIR-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" -// CHECK-INSTALL-DIR-32: "{{.*}}/Inputs/fake_install_tree/bin/../lib/gcc/i386-unknown-linux/4.7.0{{/|\\\\}}crtbegin.o" -// CHECK-INSTALL-DIR-32: "-L{{.*}}/Inputs/fake_install_tree/bin/../lib/gcc/i386-unknown-linux/4.7.0" -// -// Check that with 64-bit builds, we don't actually use the install directory -// as its version of GCC is lower than our sysrooted version. -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: --target=x86_64-unknown-linux -rtlib=platform -m64 \ -// RUN: -ccc-install-dir %S/Inputs/fake_install_tree/bin \ -// RUN: --gcc-toolchain="" \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: | FileCheck --check-prefix=CHECK-INSTALL-DIR-64 %s -// CHECK-INSTALL-DIR-64: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" -// CHECK-INSTALL-DIR-64: "{{.*}}/usr/lib/gcc/x86_64-unknown-linux/4.6.0{{/|\\\\}}crtbegin.o" -// CHECK-INSTALL-DIR-64: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-unknown-linux/4.6.0" -// // Check that we support unusual patch version formats, including missing that // component. // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ @@ -538,45 +516,8 @@ // RUN: --sysroot=%S/Inputs/basic_linux_tree \ // RUN: | FileCheck --check-prefix=CHECK-GCC-VERSION1 %s // CHECK-GCC-VERSION1: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" -// CHECK-GCC-VERSION1: "{{.*}}/Inputs/gcc_version_parsing1/bin/../lib/gcc/i386-unknown-linux/4.7{{/|\\\\}}crtbegin.o" -// CHECK-GCC-VERSION1: "-L{{.*}}/Inputs/gcc_version_parsing1/bin/../lib/gcc/i386-unknown-linux/4.7" -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: --target=i386-unknown-linux -rtlib=platform -m32 \ -// RUN: -ccc-install-dir %S/Inputs/gcc_version_parsing2/bin \ -// RUN: --gcc-toolchain="" \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: | FileCheck --check-prefix=CHECK-GCC-VERSION2 %s -// CHECK-GCC-VERSION2: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" -// CHECK-GCC-VERSION2: "{{.*}}/Inputs/gcc_version_parsing2/bin/../lib/gcc/i386-unknown-linux/4.7.x{{/|\\\\}}crtbegin.o" -// CHECK-GCC-VERSION2: "-L{{.*}}/Inputs/gcc_version_parsing2/bin/../lib/gcc/i386-unknown-linux/4.7.x" -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: --target=i386-unknown-linux -rtlib=platform -m32 \ -// RUN: -ccc-install-dir %S/Inputs/gcc_version_parsing3/bin \ -// RUN: --gcc-toolchain="" \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: | FileCheck --check-prefix=CHECK-GCC-VERSION3 %s -// CHECK-GCC-VERSION3: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" -// CHECK-GCC-VERSION3: "{{.*}}/Inputs/gcc_version_parsing3/bin/../lib/gcc/i386-unknown-linux/4.7.99-rc5{{/|\\\\}}crtbegin.o" -// CHECK-GCC-VERSION3: "-L{{.*}}/Inputs/gcc_version_parsing3/bin/../lib/gcc/i386-unknown-linux/4.7.99-rc5" -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: --target=i386-unknown-linux -rtlib=platform -m32 \ -// RUN: -ccc-install-dir %S/Inputs/gcc_version_parsing4/bin \ -// RUN: --gcc-toolchain="" \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: | FileCheck --check-prefix=CHECK-GCC-VERSION4 %s -// CHECK-GCC-VERSION4: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" -// CHECK-GCC-VERSION4: "{{.*}}/Inputs/gcc_version_parsing4/bin/../lib/gcc/i386-unknown-linux/4.7.99{{/|\\\\}}crtbegin.o" -// CHECK-GCC-VERSION4: "-L{{.*}}/Inputs/gcc_version_parsing4/bin/../lib/gcc/i386-unknown-linux/4.7.99" -// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ -// RUN: --target=i386-unknown-linux -rtlib=platform -m32 \ -// RUN: -ccc-install-dir %S/Inputs/gcc_version_parsing5/bin \ -// RUN: --gcc-toolchain="" \ -// RUN: --sysroot=%S/Inputs/basic_linux_tree \ -// RUN: | FileCheck --check-prefix=CHECK-GCC-VERSION5 %s -// CHECK-GCC-VERSION5: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" -// CHECK-GCC-VERSION5: "{{.*}}/Inputs/gcc_version_parsing5/bin/../lib/gcc/i386-unknown-linux/5{{/|\\\\}}crtbegin.o" -// CHECK-GCC-VERSION5: "-L{{.*}}/Inputs/gcc_version_parsing5/bin/../lib/gcc/i386-unknown-linux/5" -// +// CHECK-GCC-VERSION1: "{{.*}}/Inputs/basic_linux_tree/usr/lib/gcc/i386-unknown-linux/4.6.0{{/|\\\\}}crtbegin.o" + // Test a simulated installation of libc++ on Linux, both through sysroot and // the installation path of Clang. // RUN: %clangxx -no-canonical-prefixes -x c++ %s -### -o %t.o 2>&1 \ diff --git a/clang/unittests/Driver/ToolChainTest.cpp b/clang/unittests/Driver/ToolChainTest.cpp index 35060563ab97c..87f476c98dc94 100644 --- a/clang/unittests/Driver/ToolChainTest.cpp +++ b/clang/unittests/Driver/ToolChainTest.cpp @@ -31,11 +31,8 @@ TEST(ToolChainTest, VFSGCCInstallation) { IntrusiveRefCntPtr DiagID(new DiagnosticIDs()); struct TestDiagnosticConsumer : public DiagnosticConsumer {}; - DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); IntrusiveRefCntPtr InMemoryFileSystem( new llvm::vfs::InMemoryFileSystem); - Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags, - "clang LLVM compiler", InMemoryFileSystem); const char *EmptyFiles[] = { "foo.cpp", @@ -53,31 +50,78 @@ TEST(ToolChainTest, VFSGCCInstallation) { "/usr/include/arm-linux-gnueabi/.keep", "/usr/include/arm-linux-gnueabihf/.keep", "/lib/arm-linux-gnueabi/.keep", - "/lib/arm-linux-gnueabihf/.keep"}; + "/lib/arm-linux-gnueabihf/.keep", + + "/sysroot/usr/lib/gcc/arm-linux-gnueabi/4.5.1/crtbegin.o", + "/sysroot/usr/lib/gcc/arm-linux-gnueabi/4.5.1/crtend.o", + "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3/crtbegin.o", + "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3/crtend.o", + "/sysroot/usr/lib/arm-linux-gnueabi/crt1.o", + "/sysroot/usr/lib/arm-linux-gnueabi/crti.o", + "/sysroot/usr/lib/arm-linux-gnueabi/crtn.o", + "/sysroot/usr/lib/arm-linux-gnueabihf/crt1.o", + "/sysroot/usr/lib/arm-linux-gnueabihf/crti.o", + "/sysroot/usr/lib/arm-linux-gnueabihf/crtn.o", + "/sysroot/usr/include/arm-linux-gnueabi/.keep", + "/sysroot/usr/include/arm-linux-gnueabihf/.keep", + "/sysroot/lib/arm-linux-gnueabi/.keep", + "/sysroot/lib/arm-linux-gnueabihf/.keep", + }; for (const char *Path : EmptyFiles) InMemoryFileSystem->addFile(Path, 0, llvm::MemoryBuffer::getMemBuffer("\n")); - std::unique_ptr C(TheDriver.BuildCompilation( - {"-fsyntax-only", "--gcc-toolchain=", "--sysroot=", "foo.cpp"})); - EXPECT_TRUE(C); - - std::string S; { - llvm::raw_string_ostream OS(S); - C->getDefaultToolChain().printVerboseInfo(OS); + DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); + Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags, + "clang LLVM compiler", InMemoryFileSystem); + std::unique_ptr C(TheDriver.BuildCompilation( + {"-fsyntax-only", "--gcc-toolchain=", "--sysroot=", "foo.cpp"})); + ASSERT_TRUE(C); + std::string S; + { + llvm::raw_string_ostream OS(S); + C->getDefaultToolChain().printVerboseInfo(OS); + } +#if _WIN32 + std::replace(S.begin(), S.end(), '\\', '/'); +#endif + EXPECT_EQ( + "Found candidate GCC installation: " + "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n" + "Selected GCC installation: /usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n" + "Candidate multilib: .;@m32\n" + "Selected multilib: .;@m32\n", + S); } + + { + DiagnosticsEngine Diags(DiagID, &*DiagOpts, new TestDiagnosticConsumer); + Driver TheDriver("/bin/clang", "arm-linux-gnueabihf", Diags, + "clang LLVM compiler", InMemoryFileSystem); + std::unique_ptr C(TheDriver.BuildCompilation( + {"-fsyntax-only", "--gcc-toolchain=", "--sysroot=/sysroot", + "foo.cpp"})); + ASSERT_TRUE(C); + std::string S; + { + llvm::raw_string_ostream OS(S); + C->getDefaultToolChain().printVerboseInfo(OS); + } #if _WIN32 - std::replace(S.begin(), S.end(), '\\', '/'); + std::replace(S.begin(), S.end(), '\\', '/'); #endif - EXPECT_EQ( - "Found candidate GCC installation: " - "/usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n" - "Selected GCC installation: /usr/lib/gcc/arm-linux-gnueabihf/4.6.3\n" - "Candidate multilib: .;@m32\n" - "Selected multilib: .;@m32\n", - S); + // Test that 4.5.3 from --sysroot is not overridden by 4.6.3 (larger + // version) from /usr. + EXPECT_EQ("Found candidate GCC installation: " + "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3\n" + "Selected GCC installation: " + "/sysroot/usr/lib/gcc/arm-linux-gnueabihf/4.5.3\n" + "Candidate multilib: .;@m32\n" + "Selected multilib: .;@m32\n", + S); + } } TEST(ToolChainTest, VFSGCCInstallationRelativeDir) {