diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td index 009ac1cfd8dc1b..cb54bae9d32204 100644 --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -768,7 +768,11 @@ def B : JoinedOrSeparate<["-"], "B">, MetaVarName<"">, HelpText<"Search $prefix$file for executables, libraries, and data files. " "If $prefix is a directory, search $prefix/$file">; def gcc_install_dir_EQ : Joined<["--"], "gcc-install-dir=">, - HelpText<"Use GCC installation in the specified directory. The directory ends with path components like 'lib{,32,64}/gcc{,-cross}/$triple/$version'. " + HelpText<"Use GCC installation in the specified directory. The directory ends" + " with path components like 'lib{,32,64}/gcc{,-cross}/$triple/$version'. " + " This option can be specified multiple times in which case clang will" + " start with last option and search until it finds a valid gcc install" + " among the given paths." "Note: executables (e.g. ld) used by the compiler are not overridden by the selected GCC installation">; def gcc_toolchain : Joined<["--"], "gcc-toolchain=">, Flags<[NoXarchOption]>, HelpText<"Specify a directory where Clang can find 'include' and 'lib{,32,64}/gcc{,-cross}/$triple/$version'. " diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp index 3276590729e47e..64645cd03b6f9f 100644 --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -2126,27 +2126,36 @@ void Generic_GCC::GCCInstallationDetector::init( StringRef TripleNoVendorRef(TripleNoVendor); // If --gcc-install-dir= is specified, skip filesystem detection. - if (const Arg *A = - Args.getLastArg(clang::driver::options::OPT_gcc_install_dir_EQ); - A && A->getValue()[0]) { - StringRef InstallDir = A->getValue(); + std::vector FailedGCCInstallDirs; + std::vector GCCInstallDirs = Args.getAllArgValues(clang::driver::options::OPT_gcc_install_dir_EQ); + for (auto it = GCCInstallDirs.rbegin(); it != GCCInstallDirs.rend(); ++it) { + StringRef InstallDir = *it; if (!ScanGCCForMultilibs(TargetTriple, Args, InstallDir, false)) { - D.Diag(diag::err_drv_invalid_gcc_install_dir) << InstallDir; - } else { - (void)InstallDir.consume_back("/"); - StringRef VersionText = llvm::sys::path::filename(InstallDir); - StringRef TripleText = - llvm::sys::path::filename(llvm::sys::path::parent_path(InstallDir)); - - Version = GCCVersion::Parse(VersionText); - GCCTriple.setTriple(TripleText); - GCCInstallPath = std::string(InstallDir); - GCCParentLibPath = GCCInstallPath + "/../../.."; - IsValid = true; + FailedGCCInstallDirs.push_back(std::string(InstallDir)); + continue; } + + (void)InstallDir.consume_back("/"); + StringRef VersionText = llvm::sys::path::filename(InstallDir); + StringRef TripleText = + llvm::sys::path::filename(llvm::sys::path::parent_path(InstallDir)); + + Version = GCCVersion::Parse(VersionText); + GCCTriple.setTriple(TripleText); + GCCInstallPath = std::string(InstallDir); + GCCParentLibPath = GCCInstallPath + "/../../.."; + IsValid = true; return; } + for (auto FailedDir : FailedGCCInstallDirs) { + D.Diag(diag::err_drv_invalid_gcc_install_dir) << FailedDir; + } + + if (!FailedGCCInstallDirs.empty()) + return; + + // Compute the set of prefixes for our search. SmallVector Prefixes; StringRef GCCToolchainDir = getGCCToolchainDir(Args, D.SysRoot); diff --git a/clang/test/Driver/gcc-install-dir.cpp b/clang/test/Driver/gcc-install-dir.cpp index 955f162a2ce3a1..a7a91797811a12 100644 --- a/clang/test/Driver/gcc-install-dir.cpp +++ b/clang/test/Driver/gcc-install-dir.cpp @@ -16,6 +16,12 @@ // RUN: %clangxx %s -### --target=x86_64-unknown-linux-gnu --sysroot=%S/Inputs/debian_multiarch_tree \ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin -resource-dir=%S/Inputs/resource_dir --stdlib=platform --rtlib=platform --unwindlib=platform \ // RUN: --gcc-install-dir=%S/Inputs/debian_multiarch_tree/usr/lib/gcc/x86_64-linux-gnu/10/ 2>&1 | FileCheck %s --check-prefix=DEBIAN_X86_64 +// RUN: %clangxx %s -### --target=x86_64-unknown-linux-gnu --sysroot=%S/Inputs/debian_multiarch_tree \ +// RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin -resource-dir=%S/Inputs/resource_dir --stdlib=platform --rtlib=platform --unwindlib=platform \ +// RUN: --gcc-install-dir=%S/Inputs/debian_multiarch_tree/usr/lib/gcc/x86_64-linux-gnu/10/ --gcc-install-dir=%S/Inputs/debian_multiarch_tree/usr/lib/gcc/x86_64-linux-gnu/1100 2>&1 | FileCheck %s --check-prefix=DEBIAN_X86_64 +// RUN: %clangxx %s -### --target=x86_64-unknown-linux-gnu --sysroot=%S/Inputs/debian_multiarch_tree \ +// RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin -resource-dir=%S/Inputs/resource_dir --stdlib=platform --rtlib=platform --unwindlib=platform \ +// RUN: --gcc-install-dir=%S/Inputs/debian_multiarch_tree/usr/lib/gcc/x86_64-linux-gnu/11/ --gcc-install-dir=%S/Inputs/debian_multiarch_tree/usr/lib/gcc/x86_64-linux-gnu/10 2>&1 | FileCheck %s --check-prefix=DEBIAN_X86_64 // DEBIAN_X86_64: "-internal-isystem" // DEBIAN_X86_64-SAME: {{^}} "[[SYSROOT:[^"]+]]/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10" // DEBIAN_X86_64-SAME: {{^}} "-internal-isystem" "[[SYSROOT:[^"]+]]/usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10" @@ -41,3 +47,10 @@ // RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin -resource-dir=%S/Inputs/resource_dir --stdlib=platform --rtlib=platform \ // RUN: --gcc-install-dir=%S/Inputs/debian_multiarch_tree/usr/lib/gcc/x86_64-linux-gnu 2>&1 | FileCheck %s --check-prefix=INVALID // INVALID: error: '{{.*}}/usr/lib/gcc/x86_64-linux-gnu' does not contain a GCC installation + +// RUN: not %clangxx %s -### --target=x86_64-unknown-linux-gnu --sysroot=%S/Inputs/debian_multiarch_tree \ +// RUN: -ccc-install-dir %S/Inputs/basic_linux_tree/usr/bin -resource-dir=%S/Inputs/resource_dir --stdlib=platform --rtlib=platform \ +// RUN: --gcc-install-dir=%S/Inputs/debian_multiarch_tree/usr/lib/gcc/x86_64-linux-gnu/1100 \ +// RUN: --gcc-install-dir=%S/Inputs/debian_multiarch_tree/usr/lib/gcc/x86_64-linux-gnu/1200 2>&1 | FileCheck %s --check-prefix=INVALID-MULTIPLE +// INVALID-MULTIPLE: error: '{{.*}}/usr/lib/gcc/x86_64-linux-gnu/1200' does not contain a GCC installation +// INVALID-MULTIPLE: error: '{{.*}}/usr/lib/gcc/x86_64-linux-gnu/1100' does not contain a GCC installation