Index: lib/Driver/ToolChains.h =================================================================== --- lib/Driver/ToolChains.h +++ lib/Driver/ToolChains.h @@ -196,6 +196,11 @@ SmallVectorImpl &BiarchLibDirs, SmallVectorImpl &BiarchTripleAliases); + bool ScanGCCForMultilibs(const llvm::Triple &TargetTriple, + const llvm::opt::ArgList &Args, + StringRef Path, + bool NeedsBiarchSuffix = false); + void ScanLibDirForGCCTriple(const llvm::Triple &TargetArch, const llvm::opt::ArgList &Args, const std::string &LibDir, @@ -207,6 +212,11 @@ const std::string &LibDir, StringRef CandidateTriple, bool NeedsBiarchSuffix = false); + + bool ScanGentooGccConfig(const llvm::Triple &TargetTriple, + const llvm::opt::ArgList &Args, + StringRef CandidateTriple, + bool NeedsBiarchSuffix = false); }; protected: Index: lib/Driver/ToolChains.cpp =================================================================== --- lib/Driver/ToolChains.cpp +++ lib/Driver/ToolChains.cpp @@ -1456,35 +1456,17 @@ // in /usr. This avoids accidentally enforcing the system GCC version // when using a custom toolchain. if (GCCToolchainDir == "" || GCCToolchainDir == D.SysRoot + "/usr") { + for (StringRef CandidateTriple : ExtraTripleAliases) { + if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple)) + return; + } for (StringRef CandidateTriple : CandidateTripleAliases) { - llvm::ErrorOr> File = - D.getVFS().getBufferForFile(D.SysRoot + "/etc/env.d/gcc/config-" + - CandidateTriple.str()); - if (File) { - SmallVector Lines; - File.get()->getBuffer().split(Lines, "\n"); - for (StringRef Line : Lines) { - // CURRENT=triple-version - if (Line.consume_front("CURRENT=")) { - const std::pair ActiveVersion = - Line.rsplit('-'); - // Note: Strictly speaking, we should be reading - // /etc/env.d/gcc/${CURRENT} now. However, the file doesn't - // contain anything new or especially useful to us. - const std::string GentooPath = D.SysRoot + "/usr/lib/gcc/" + - ActiveVersion.first.str() + "/" + - ActiveVersion.second.str(); - if (D.getVFS().exists(GentooPath + "/crtbegin.o")) { - Version = GCCVersion::Parse(ActiveVersion.second); - GCCInstallPath = GentooPath; - GCCParentLibPath = GentooPath + "/../../.."; - GCCTriple.setTriple(ActiveVersion.first); - IsValid = true; - return; - } - } - } - } + if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple)) + return; + } + for (StringRef CandidateTriple : CandidateBiarchTripleAliases) { + if (ScanGentooGccConfig(TargetTriple, Args, CandidateTriple, true)) + return; } } @@ -2715,6 +2697,33 @@ } } +bool Generic_GCC::GCCInstallationDetector::ScanGCCForMultilibs( + const llvm::Triple &TargetTriple, const ArgList &Args, + StringRef Path, bool NeedsBiarchSuffix) { + llvm::Triple::ArchType TargetArch = TargetTriple.getArch(); + DetectedMultilibs Detected; + + // Android standalone toolchain could have multilibs for ARM and Thumb. + // Debian mips multilibs behave more like the rest of the biarch ones, + // so handle them there + if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) { + // It should also work without multilibs in a simplified toolchain. + findAndroidArmMultilibs(D, TargetTriple, Path, Args, Detected); + } else if (isMipsArch(TargetArch)) { + if (!findMIPSMultilibs(D, TargetTriple, Path, Args, Detected)) + return false; + } else if (!findBiarchMultilibs(D, TargetTriple, Path, Args, + NeedsBiarchSuffix, Detected)) { + return false; + } + + Multilibs = Detected.Multilibs; + SelectedMultilib = Detected.SelectedMultilib; + BiarchSibling = Detected.BiarchSibling; + + return true; +} + void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( const llvm::Triple &TargetTriple, const ArgList &Args, const std::string &LibDir, StringRef CandidateTriple, @@ -2770,25 +2779,10 @@ if (CandidateVersion <= Version) continue; - DetectedMultilibs Detected; - - // Android standalone toolchain could have multilibs for ARM and Thumb. - // Debian mips multilibs behave more like the rest of the biarch ones, - // so handle them there - if (isArmOrThumbArch(TargetArch) && TargetTriple.isAndroid()) { - // It should also work without multilibs in a simplified toolchain. - findAndroidArmMultilibs(D, TargetTriple, LI->getName(), Args, Detected); - } else if (isMipsArch(TargetArch)) { - if (!findMIPSMultilibs(D, TargetTriple, LI->getName(), Args, Detected)) - continue; - } else if (!findBiarchMultilibs(D, TargetTriple, LI->getName(), Args, - NeedsBiarchSuffix, Detected)) { + if (!ScanGCCForMultilibs(TargetTriple, Args, LI->getName(), + NeedsBiarchSuffix)) continue; - } - Multilibs = Detected.Multilibs; - SelectedMultilib = Detected.SelectedMultilib; - BiarchSibling = Detected.BiarchSibling; Version = CandidateVersion; GCCTriple.setTriple(CandidateTriple); // FIXME: We hack together the directory name here instead of @@ -2802,6 +2796,45 @@ } } +bool Generic_GCC::GCCInstallationDetector::ScanGentooGccConfig( + const llvm::Triple &TargetTriple, const ArgList &Args, + StringRef CandidateTriple, bool NeedsBiarchSuffix) { + llvm::ErrorOr> File = + D.getVFS().getBufferForFile(D.SysRoot + "/etc/env.d/gcc/config-" + + CandidateTriple.str()); + if (File) { + SmallVector Lines; + File.get()->getBuffer().split(Lines, "\n"); + for (StringRef Line : Lines) { + // CURRENT=triple-version + if (Line.consume_front("CURRENT=")) { + const std::pair ActiveVersion = + Line.rsplit('-'); + // Note: Strictly speaking, we should be reading + // /etc/env.d/gcc/${CURRENT} now. However, the file doesn't + // contain anything new or especially useful to us. + const std::string GentooPath = D.SysRoot + "/usr/lib/gcc/" + + ActiveVersion.first.str() + "/" + + ActiveVersion.second.str(); + if (D.getVFS().exists(GentooPath + "/crtbegin.o")) { + if (!ScanGCCForMultilibs(TargetTriple, Args, GentooPath, + NeedsBiarchSuffix)) + return false; + + Version = GCCVersion::Parse(ActiveVersion.second); + GCCInstallPath = GentooPath; + GCCParentLibPath = GentooPath + "/../../.."; + GCCTriple.setTriple(ActiveVersion.first); + IsValid = true; + return true; + } + } + } + } + + return false; +} + Generic_GCC::Generic_GCC(const Driver &D, const llvm::Triple &Triple, const ArgList &Args) : ToolChain(D, Triple, Args), GCCInstallation(D), Index: test/Driver/linux-header-search.cpp =================================================================== --- test/Driver/linux-header-search.cpp +++ test/Driver/linux-header-search.cpp @@ -310,6 +310,39 @@ // RUN: --gcc-toolchain="" \ // RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3 %s // +// Test that gcc-config support does not break multilib. +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ +// RUN: -target x86_64-unknown-linux-gnux32 -stdlib=libstdc++ \ +// RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ +// RUN: --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3-X32 %s +// CHECK-GENTOO-4-9-3-X32: "{{.*}}clang{{.*}}" "-cc1" +// CHECK-GENTOO-4-9-3-X32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-GENTOO-4-9-3-X32: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-GENTOO-4-9-3-X32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3" +// CHECK-GENTOO-4-9-3-X32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/x86_64-pc-linux-gnu/x32" +// CHECK-GENTOO-4-9-3-X32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/backward" +// CHECK-GENTOO-4-9-3-X32: "-internal-isystem" "[[SYSROOT]]/usr/local/include" +// CHECK-GENTOO-4-9-3-X32: "-internal-isystem" "[[RESOURCE_DIR]]{{/|\\\\}}include" +// CHECK-GENTOO-4-9-3-X32: "-internal-externc-isystem" "[[SYSROOT]]/include" +// CHECK-GENTOO-4-9-3-X32: "-internal-externc-isystem" "[[SYSROOT]]/usr/include" +// +// RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ +// RUN: -target i386-unknown-linux-gnu -stdlib=libstdc++ \ +// RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ +// RUN: --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=CHECK-GENTOO-4-9-3-32 %s +// CHECK-GENTOO-4-9-3-32: "{{.*}}clang{{.*}}" "-cc1" +// CHECK-GENTOO-4-9-3-32: "-resource-dir" "[[RESOURCE_DIR:[^"]+]]" +// CHECK-GENTOO-4-9-3-32: "-isysroot" "[[SYSROOT:[^"]+]]" +// CHECK-GENTOO-4-9-3-32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3" +// CHECK-GENTOO-4-9-3-32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/x86_64-pc-linux-gnu/32" +// CHECK-GENTOO-4-9-3-32: "-internal-isystem" "[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/include/g++-v4.9.3/backward" +// CHECK-GENTOO-4-9-3-32: "-internal-isystem" "[[SYSROOT]]/usr/local/include" +// CHECK-GENTOO-4-9-3-32: "-internal-isystem" "[[RESOURCE_DIR]]{{/|\\\\}}include" +// CHECK-GENTOO-4-9-3-32: "-internal-externc-isystem" "[[SYSROOT]]/include" +// CHECK-GENTOO-4-9-3-32: "-internal-externc-isystem" "[[SYSROOT]]/usr/include" +// // Check header search on Debian 6 / MIPS64 // RUN: %clang -no-canonical-prefixes %s -### -fsyntax-only 2>&1 \ // RUN: -target mips64-unknown-linux-gnuabi64 -stdlib=libstdc++ \ Index: test/Driver/linux-ld.c =================================================================== --- test/Driver/linux-ld.c +++ test/Driver/linux-ld.c @@ -1662,3 +1662,56 @@ // CHECK-MUSL-ARMEBHF: "-dynamic-linker" "/lib/ld-musl-armebhf.so.1" // CHECK-MUSL-AARCH64: "-dynamic-linker" "/lib/ld-musl-aarch64.so.1" // CHECK-MUSL-AARCH64_BE: "-dynamic-linker" "/lib/ld-musl-aarch64_be.so.1" + +// Check whether multilib gcc install works fine on Gentoo with gcc-config +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-unknown-linux-gnu -rtlib=platform \ +// RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ +// RUN: --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO %s +// CHECK-LD-GENTOO-NOT: warning: +// CHECK-LD-GENTOO: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-LD-GENTOO: "--eh-frame-hdr" +// CHECK-LD-GENTOO: "-m" "elf_x86_64" +// CHECK-LD-GENTOO: "-dynamic-linker" +// CHECK-LD-GENTOO: "{{.*}}/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/crtbegin.o" +// CHECK-LD-GENTOO: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3" +// CHECK-LD-GENTOO: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../../../x86_64-pc-linux-gnu/lib" +// CHECK-LD-GENTOO: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../.." +// CHECK-LD-GENTOO: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" +// CHECK-LD-GENTOO: "-lc" +// CHECK-LD-GENTOO: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=i686-unknown-linux-gnu -rtlib=platform \ +// RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ +// RUN: --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO-32 %s +// CHECK-LD-GENTOO-32-NOT: warning: +// CHECK-LD-GENTOO-32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-LD-GENTOO-32: "--eh-frame-hdr" +// CHECK-LD-GENTOO-32: "-m" "elf_i386" +// CHECK-LD-GENTOO-32: "-dynamic-linker" +// CHECK-LD-GENTOO-32: "{{.*}}/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/32/crtbegin.o" +// CHECK-LD-GENTOO-32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/32" +// CHECK-LD-GENTOO-32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../../../x86_64-pc-linux-gnu/lib" +// CHECK-LD-GENTOO-32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../.." +// CHECK-LD-GENTOO-32: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" +// CHECK-LD-GENTOO-32: "-lc" +// CHECK-LD-GENTOO-32: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: --target=x86_64-unknown-linux-gnux32 -rtlib=platform \ +// RUN: --sysroot=%S/Inputs/gentoo_linux_gcc_multi_version_tree \ +// RUN: --gcc-toolchain="" \ +// RUN: | FileCheck --check-prefix=CHECK-LD-GENTOO-X32 %s +// CHECK-LD-GENTOO-X32-NOT: warning: +// CHECK-LD-GENTOO-X32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-LD-GENTOO-X32: "--eh-frame-hdr" +// CHECK-LD-GENTOO-X32: "-m" "elf32_x86_64" +// CHECK-LD-GENTOO-X32: "-dynamic-linker" +// CHECK-LD-GENTOO-X32: "{{.*}}/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/x32/crtbegin.o" +// CHECK-LD-GENTOO-X32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/x32" +// CHECK-LD-GENTOO-X32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../../../x86_64-pc-linux-gnu/lib" +// CHECK-LD-GENTOO-X32: "-L[[SYSROOT]]/usr/lib/gcc/x86_64-pc-linux-gnu/4.9.3/../../.." +// CHECK-LD-GENTOO-X32: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed" +// CHECK-LD-GENTOO-X32: "-lc" +// CHECK-LD-GENTOO-X32: "-lgcc" "--as-needed" "-lgcc_s" "--no-as-needed"