diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -452,11 +452,11 @@ StringRef Component, FileType Type = ToolChain::FT_Static) const; - // Returns target specific runtime path if it exists. - virtual std::string getRuntimePath() const; + // Returns target specific runtime paths. + path_list getRuntimePaths() const; - // Returns target specific standard library path if it exists. - virtual std::string getStdlibPath() const; + // Returns target specific standard library paths. + path_list getStdlibPaths() const; // Returns /lib//. This is used by runtimes (such // as OpenMP) to find arch-specific libraries. diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp --- a/clang/lib/Driver/Driver.cpp +++ b/clang/lib/Driver/Driver.cpp @@ -1869,9 +1869,16 @@ } if (C.getArgs().hasArg(options::OPT_print_runtime_dir)) { - std::string CandidateRuntimePath = TC.getRuntimePath(); - if (getVFS().exists(CandidateRuntimePath)) - llvm::outs() << CandidateRuntimePath << '\n'; + std::string RuntimePath; + // Get the first existing path, if any. + for (auto Path : TC.getRuntimePaths()) { + if (getVFS().exists(Path)) { + RuntimePath = Path; + break; + } + } + if (!RuntimePath.empty()) + llvm::outs() << RuntimePath << '\n'; else llvm::outs() << TC.getCompilerRTPath() << '\n'; return false; diff --git a/clang/lib/Driver/ToolChain.cpp b/clang/lib/Driver/ToolChain.cpp --- a/clang/lib/Driver/ToolChain.cpp +++ b/clang/lib/Driver/ToolChain.cpp @@ -75,17 +75,16 @@ const ArgList &Args) : D(D), Triple(T), Args(Args), CachedRTTIArg(GetRTTIArgument(Args)), CachedRTTIMode(CalculateRTTIMode(Args, Triple, CachedRTTIArg)) { - std::string RuntimePath = getRuntimePath(); - if (getVFS().exists(RuntimePath)) - getLibraryPaths().push_back(RuntimePath); - - std::string StdlibPath = getStdlibPath(); - if (getVFS().exists(StdlibPath)) - getFilePaths().push_back(StdlibPath); + auto addIfExists = [this](path_list &List, const std::string &Path) { + if (getVFS().exists(Path)) + List.push_back(Path); + }; - std::string CandidateLibPath = getArchSpecificLibPath(); - if (getVFS().exists(CandidateLibPath)) - getFilePaths().push_back(CandidateLibPath); + for (const auto &Path : getRuntimePaths()) + addIfExists(getLibraryPaths(), Path); + for (const auto &Path : getStdlibPaths()) + addIfExists(getFilePaths(), Path); + addIfExists(getFilePaths(), getArchSpecificLibPath()); } void ToolChain::setTripleEnvironment(llvm::Triple::EnvironmentType Env) { @@ -485,16 +484,35 @@ return Args.MakeArgString(getCompilerRT(Args, Component, Type)); } -std::string ToolChain::getRuntimePath() const { - SmallString<128> P(D.ResourceDir); - llvm::sys::path::append(P, "lib", getTripleString()); - return std::string(P.str()); +ToolChain::path_list ToolChain::getRuntimePaths() const { + path_list Paths; + auto addPathForTriple = [this, &Paths](const llvm::Triple &Triple) { + SmallString<128> P(D.ResourceDir); + llvm::sys::path::append(P, "lib", Triple.str()); + Paths.push_back(std::string(P.str())); + }; + + addPathForTriple(getTriple()); + + // Android targets may include an API level at the end. We still want to fall + // back on a path without the API level. + if (getTriple().isAndroid() && + getTriple().getEnvironmentName() != "android") { + llvm::Triple TripleWithoutLevel = getTriple(); + TripleWithoutLevel.setEnvironmentName("android"); + addPathForTriple(TripleWithoutLevel); + } + + return Paths; } -std::string ToolChain::getStdlibPath() const { +ToolChain::path_list ToolChain::getStdlibPaths() const { + path_list Paths; SmallString<128> P(D.Dir); llvm::sys::path::append(P, "..", "lib", getTripleString()); - return std::string(P.str()); + Paths.push_back(std::string(P.str())); + + return Paths; } std::string ToolChain::getArchSpecificLibPath() const { diff --git a/clang/lib/Driver/ToolChains/Fuchsia.cpp b/clang/lib/Driver/ToolChains/Fuchsia.cpp --- a/clang/lib/Driver/ToolChains/Fuchsia.cpp +++ b/clang/lib/Driver/ToolChains/Fuchsia.cpp @@ -191,9 +191,11 @@ auto FilePaths = [&](const Multilib &M) -> std::vector { std::vector FP; - SmallString<128> P(getStdlibPath()); - llvm::sys::path::append(P, M.gccSuffix()); - FP.push_back(std::string(P.str())); + for (const std::string &Path : getStdlibPaths()) { + SmallString<128> P(Path); + llvm::sys::path::append(P, M.gccSuffix()); + FP.push_back(std::string(P.str())); + } return FP; }; diff --git a/clang/lib/Driver/ToolChains/VEToolchain.cpp b/clang/lib/Driver/ToolChains/VEToolchain.cpp --- a/clang/lib/Driver/ToolChains/VEToolchain.cpp +++ b/clang/lib/Driver/ToolChains/VEToolchain.cpp @@ -48,7 +48,8 @@ // ${BINPATH}/../lib/ve-unknown-linux-gnu, (== getStdlibPath) // ${RESOURCEDIR}/lib/linux/ve, (== getArchSpecificLibPath) // ${SYSROOT}/opt/nec/ve/lib, - getFilePaths().push_back(getStdlibPath()); + for (auto &Path : getStdlibPaths()) + getFilePaths().push_back(std::move(Path)); getFilePaths().push_back(getArchSpecificLibPath()); getFilePaths().push_back(computeSysRoot() + "/opt/nec/ve/lib"); } diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android/libclang_rt.builtins.a b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android/libclang_rt.builtins.a new file mode 100644 diff --git a/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android21/libclang_rt.builtins.a b/clang/test/Driver/Inputs/resource_dir_with_per_target_subdir/lib/aarch64-unknown-linux-android21/libclang_rt.builtins.a new file mode 100644 diff --git a/clang/test/Driver/linux-per-target-runtime-dir.c b/clang/test/Driver/linux-per-target-runtime-dir.c --- a/clang/test/Driver/linux-per-target-runtime-dir.c +++ b/clang/test/Driver/linux-per-target-runtime-dir.c @@ -25,3 +25,21 @@ // RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ // RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-X8664 %s // CHECK-FILE-NAME-X8664: lib{{/|\\}}x86_64-unknown-linux-gnu{{/|\\}}libclang_rt.builtins.a + +// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \ +// RUN: --target=aarch64-unknown-linux-android21 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID21 %s +// CHECK-FILE-NAME-ANDROID21: lib{{/|\\}}aarch64-unknown-linux-android21{{/|\\}}libclang_rt.builtins.a + +// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \ +// RUN: --target=aarch64-unknown-linux-android23 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID23 %s +// CHECK-FILE-NAME-ANDROID23: lib{{/|\\}}aarch64-unknown-linux-android{{/|\\}}libclang_rt.builtins.a + +// RUN: %clang -rtlib=compiler-rt -print-file-name=libclang_rt.builtins.a 2>&1 \ +// RUN: --target=aarch64-unknown-linux-android \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_per_target_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-FILE-NAME-ANDROID %s +// CHECK-FILE-NAME-ANDROID: lib{{/|\\}}aarch64-unknown-linux-android{{/|\\}}libclang_rt.builtins.a