Index: include/clang/Driver/ToolChain.h =================================================================== --- include/clang/Driver/ToolChain.h +++ include/clang/Driver/ToolChain.h @@ -299,6 +299,11 @@ const char *getCompilerRTArgString(const llvm::opt::ArgList &Args, StringRef Component, bool Shared = false) const; + + // Returns /lib//. This is used by runtimes (such + // as OpenMP) to find arch-specific libraries. + const std::string getArchSpecificLibPath() const; + /// needsProfileRT - returns true if instrumentation profile is on. static bool needsProfileRT(const llvm::opt::ArgList &Args); Index: lib/Driver/ToolChain.cpp =================================================================== --- lib/Driver/ToolChain.cpp +++ lib/Driver/ToolChain.cpp @@ -10,6 +10,7 @@ #include "clang/Driver/ToolChain.h" #include "Tools.h" #include "clang/Basic/ObjCRuntime.h" +#include "clang/Basic/VirtualFileSystem.h" #include "clang/Config/config.h" #include "clang/Driver/Action.h" #include "clang/Driver/Driver.h" @@ -74,6 +75,10 @@ if (!isThreadModelSupported(A->getValue())) D.Diag(diag::err_drv_invalid_thread_model_for_target) << A->getValue() << A->getAsString(Args); + + std::string CandidateLibPath = getArchSpecificLibPath(); + if (getVFS().exists(CandidateLibPath)) + getFilePaths().push_back(CandidateLibPath); } ToolChain::~ToolChain() { @@ -320,6 +325,14 @@ return Args.MakeArgString(getCompilerRT(Args, Component, Shared)); } +const std::string ToolChain::getArchSpecificLibPath() const { + SmallString<128> Path(getDriver().ResourceDir); + StringRef OSLibName = getTriple().isOSFreeBSD() ? "freebsd" : getOS(); + llvm::sys::path::append(Path, "lib", OSLibName, + llvm::Triple::getArchTypeName(getArch())); + return Path.str(); +} + bool ToolChain::needsProfileRT(const ArgList &Args) { if (Args.hasFlag(options::OPT_fprofile_arcs, options::OPT_fno_profile_arcs, false) || Index: lib/Driver/Tools.cpp =================================================================== --- lib/Driver/Tools.cpp +++ lib/Driver/Tools.cpp @@ -14,6 +14,7 @@ #include "clang/Basic/LangOptions.h" #include "clang/Basic/ObjCRuntime.h" #include "clang/Basic/Version.h" +#include "clang/Basic/VirtualFileSystem.h" #include "clang/Config/config.h" #include "clang/Driver/Action.h" #include "clang/Driver/Compilation.h" @@ -276,8 +277,18 @@ // LIBRARY_PATH - included following the user specified library paths. // and only supported on native toolchains. - if (!TC.isCrossCompiling()) + if (!TC.isCrossCompiling()) { addDirectoryList(Args, CmdArgs, "-L", "LIBRARY_PATH"); + + // If we are not cross-compling, add '-rpath' with architecture-specific + // library path so libraries lined from this path can be automatically + // found. + std::string CandidateRPath = TC.getArchSpecificLibPath(); + if (D.getVFS().exists(CandidateRPath)) { + CmdArgs.push_back("-rpath"); + CmdArgs.push_back(Args.MakeArgString(CandidateRPath.c_str())); + } + } } /// Add OpenMP linker script arguments at the end of the argument list so that Index: test/Driver/arch-specific-libdir-rpath.c =================================================================== --- /dev/null +++ test/Driver/arch-specific-libdir-rpath.c @@ -0,0 +1,20 @@ +// Test that the driver adds an arch-specific subdirectory in +// {RESOURCE_DIR}/lib/linux to the linker search path and to '-rpath' for native +// compilations. +// +// -rpath only gets added during native compilation. To keep the test simple, +// just test for x86_64-linux native compilation. +// REQUIRES: x86_64-linux +// +// RUN: %clang %s -### 2>&1 \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-ARCHDIR %s +// +// RUN: %clang %s -### 2>&1 \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: | FileCheck --check-prefix=CHECK-NO-ARCHDIR %s +// +// +// CHECK-ARCHDIR: -L{{.*}}/Inputs/resource_dir_with_arch_subdir/lib/linux{{.*}} "-rpath" {{.*}}/Inputs/resource_dir_with_arch_subdir/lib/linux +// CHECK-NO-ARCHDIR-NOT: -L{{.*}}Inputs/resource_dir +// CHECK-NO-ARCHDIR-NOT: "-rpath" {{.*}}/Inputs/resource_dir Index: test/Driver/arch-specific-libdir.c =================================================================== --- /dev/null +++ test/Driver/arch-specific-libdir.c @@ -0,0 +1,52 @@ +// Test that the driver adds an arch-specific subdirectory in +// {RESOURCE_DIR}/lib/linux to the search path. +// +// RUN: %clang %s -### 2>&1 -target i386-unknown-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-ARCHDIR-i386 %s +// +// RUN: %clang %s -### 2>&1 -target i386-unknown-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: | FileCheck --check-prefix=CHECK-NO-ARCHDIR %s +// +// RUN: %clang %s -### 2>&1 -target i686-unknown-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-ARCHDIR-i386 %s +// +// RUN: %clang %s -### 2>&1 -target i686-unknown-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: | FileCheck --check-prefix=CHECK-NO-ARCHDIR %s +// +// RUN: %clang %s -### 2>&1 -target x86_64-unknown-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-ARCHDIR-x86_64 %s +// +// RUN: %clang %s -### 2>&1 -target x86_64-unknown-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: | FileCheck --check-prefix=CHECK-NO-ARCHDIR %s +// +// RUN: %clang %s -### 2>&1 -target arm-unknown-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-ARCHDIR-arm %s +// +// RUN: %clang %s -### 2>&1 -target arm-unknown-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: | FileCheck --check-prefix=CHECK-NO-ARCHDIR %s +// +// RUN: %clang %s -### 2>&1 -target aarch64-unknown-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \ +// RUN: | FileCheck --check-prefix=CHECK-ARCHDIR-aarch64 %s +// +// RUN: %clang %s -### 2>&1 -target aarch64-unknown-linux \ +// RUN: -resource-dir=%S/Inputs/resource_dir \ +// RUN: | FileCheck --check-prefix=CHECK-NO-ARCHDIR %s +// +// +// CHECK-ARCHDIR-i386: -L{{.*}}/Inputs/resource_dir_with_arch_subdir/lib/linux/i386 +// CHECK-ARCHDIR-x86_64: -L{{.*}}/Inputs/resource_dir_with_arch_subdir/lib/linux/x86_64 +// CHECK-ARCHDIR-arm: -L{{.*}}/Inputs/resource_dir_with_arch_subdir/lib/linux/arm +// CHECK-ARCHDIR-aarch64: -L{{.*}}/Inputs/resource_dir_with_arch_subdir/lib/linux/aarch64 +// +// Have a stricter check for no-archdir - that the driver doesn't add any +// subdirectory from the provided resource directory. +// CHECK-NO-ARCHDIR-NOT: -L{{.*}}Inputs/resource_dir Index: test/lit.cfg =================================================================== --- test/lit.cfg +++ test/lit.cfg @@ -392,6 +392,10 @@ if config.host_triple == config.target_triple: config.available_features.add("native") +# Test Driver/arch-specific-libdir-rpath.c is restricted to x86_64-linux +if re.match(r'^x86_64.*-linux', config.target_triple): + config.available_features.add("x86_64-linux") + # Case-insensitive file system def is_filesystem_case_insensitive(): handle, path = tempfile.mkstemp(prefix='case-test', dir=config.test_exec_root)