forked from OSchip/llvm-project
Add arch-specific directory to search path
Summary: This change adds an arch-specific subdirectory in <ResourceDir>/lib/<OS> to the linker search path. This path also gets added as '-rpath' for native compilation if a runtime is linked in as a shared object. This allows arch-specific libraries to be installed alongside clang. Reviewers: danalbert, cbergstrom, javed.absar Subscribers: srhines Differential Revision: https://reviews.llvm.org/D30015 llvm-svn: 296927
This commit is contained in:
parent
1c9d800fbc
commit
65a16dd858
|
@ -299,6 +299,11 @@ public:
|
|||
const char *getCompilerRTArgString(const llvm::opt::ArgList &Args,
|
||||
StringRef Component,
|
||||
bool Shared = false) const;
|
||||
|
||||
// Returns <ResourceDir>/lib/<OSName>/<arch>. This is used by runtimes (such
|
||||
// as OpenMP) to find arch-specific libraries.
|
||||
std::string getArchSpecificLibPath() const;
|
||||
|
||||
/// needsProfileRT - returns true if instrumentation profile is on.
|
||||
static bool needsProfileRT(const llvm::opt::ArgList &Args);
|
||||
|
||||
|
|
|
@ -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 @@ ToolChain::ToolChain(const Driver &D, const llvm::Triple &T,
|
|||
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 @@ const char *ToolChain::getCompilerRTArgString(const llvm::opt::ArgList &Args,
|
|||
return Args.MakeArgString(getCompilerRT(Args, Component, Shared));
|
||||
}
|
||||
|
||||
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) ||
|
||||
|
|
|
@ -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"
|
||||
|
@ -238,8 +239,9 @@ static void AddLinkerInputs(const ToolChain &TC, const InputInfoList &Inputs,
|
|||
|
||||
// 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");
|
||||
}
|
||||
}
|
||||
|
||||
/// Add OpenMP linker script arguments at the end of the argument list so that
|
||||
|
@ -2000,6 +2002,19 @@ static void CollectArgsForIntegratedAssembler(Compilation &C,
|
|||
}
|
||||
}
|
||||
|
||||
static void addArchSpecificRPath(const ToolChain &TC, const ArgList &Args,
|
||||
ArgStringList &CmdArgs) {
|
||||
// In the cross-compilation case, arch-specific library path is likely
|
||||
// unavailable at runtime.
|
||||
if (TC.isCrossCompiling()) return;
|
||||
|
||||
std::string CandidateRPath = TC.getArchSpecificLibPath();
|
||||
if (TC.getVFS().exists(CandidateRPath)) {
|
||||
CmdArgs.push_back("-rpath");
|
||||
CmdArgs.push_back(Args.MakeArgString(CandidateRPath.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
static void addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
|
||||
const ArgList &Args) {
|
||||
if (!Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ,
|
||||
|
@ -2020,6 +2035,8 @@ static void addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
|
|||
// Already diagnosed.
|
||||
break;
|
||||
}
|
||||
|
||||
addArchSpecificRPath(TC, Args, CmdArgs);
|
||||
}
|
||||
|
||||
static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
|
||||
|
@ -2030,6 +2047,10 @@ static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args,
|
|||
if (IsWhole) CmdArgs.push_back("-whole-archive");
|
||||
CmdArgs.push_back(TC.getCompilerRTArgString(Args, Sanitizer, IsShared));
|
||||
if (IsWhole) CmdArgs.push_back("-no-whole-archive");
|
||||
|
||||
if (IsShared) {
|
||||
addArchSpecificRPath(TC, Args, CmdArgs);
|
||||
}
|
||||
}
|
||||
|
||||
// Tries to use a file with the list of dynamic symbols that need to be exported
|
||||
|
@ -9002,6 +9023,8 @@ void gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
|
|||
}
|
||||
if (JA.isHostOffloading(Action::OFK_OpenMP))
|
||||
CmdArgs.push_back("-lomptarget");
|
||||
|
||||
addArchSpecificRPath(ToolChain, Args, CmdArgs);
|
||||
}
|
||||
|
||||
AddRunTimeLibs(ToolChain, D, CmdArgs, Args);
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
// 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
|
||||
//
|
||||
// Add LIBPATH but no RPATH for -fsanitizer=address w/o -shared-libasan
|
||||
// RUN: %clang %s -### 2>&1 -fsanitize=undefined \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,LIBPATH,NO-RPATH %s
|
||||
//
|
||||
// Add LIBPATH, RPATH for -fsanitize=address -shared-libasan
|
||||
// RUN: %clang %s -### 2>&1 -target x86_64-linux \
|
||||
// RUN: -fsanitize=address -shared-libasan \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,LIBPATH,RPATH %s
|
||||
//
|
||||
// Add LIBPATH, RPATH with -fsanitize=address for Android
|
||||
// RUN: %clang %s -### 2>&1 -target x86_64-linux-android -fsanitize=address \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,LIBPATH,RPATH %s
|
||||
//
|
||||
// Add LIBPATH, RPATH for OpenMP
|
||||
// RUN: %clang %s -### 2>&1 -fopenmp \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,LIBPATH,RPATH %s
|
||||
//
|
||||
// Add LIBPATH but no RPATH for ubsan (or any other sanitizer)
|
||||
// RUN: %clang %s -### 2>&1 -fsanitize=undefined \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,LIBPATH,NO-RPATH %s
|
||||
//
|
||||
// Add LIBPATH but no RPATH if no sanitizer or runtime is specified
|
||||
// RUN: %clang %s -### 2>&1 \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir_with_arch_subdir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,LIBPATH,NO-RPATH %s
|
||||
//
|
||||
// Do not add LIBPATH or RPATH if arch-specific subdir doesn't exist
|
||||
// RUN: %clang %s -### 2>&1 \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,NO-LIBPATH,NO-RPATH %s
|
||||
//
|
||||
//
|
||||
// FILEPATH: "-x" "c" "[[FILE_PATH:.*]]/{{.*}}.c"
|
||||
// LIBPATH: -L[[FILE_PATH]]/Inputs/resource_dir_with_arch_subdir/lib/linux/x86_64
|
||||
// RPATH: "-rpath" "[[FILE_PATH]]/Inputs/resource_dir_with_arch_subdir/lib/linux/x86_64"
|
||||
// NO-LIBPATH-NOT: -L{{.*}}Inputs/resource_dir
|
||||
// NO-RPATH-NOT: "-rpath" {{.*}}/Inputs/resource_dir
|
|
@ -0,0 +1,53 @@
|
|||
// 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-prefixes=FILEPATH,ARCHDIR-i386 %s
|
||||
//
|
||||
// RUN: %clang %s -### 2>&1 -target i386-unknown-linux \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,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-prefixes=FILEPATH,ARCHDIR-i386 %s
|
||||
//
|
||||
// RUN: %clang %s -### 2>&1 -target i686-unknown-linux \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,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-prefixes=FILEPATH,ARCHDIR-x86_64 %s
|
||||
//
|
||||
// RUN: %clang %s -### 2>&1 -target x86_64-unknown-linux \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,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-prefixes=FILEPATH,ARCHDIR-arm %s
|
||||
//
|
||||
// RUN: %clang %s -### 2>&1 -target arm-unknown-linux \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,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-prefixes=FILEPATH,ARCHDIR-aarch64 %s
|
||||
//
|
||||
// RUN: %clang %s -### 2>&1 -target aarch64-unknown-linux \
|
||||
// RUN: -resource-dir=%S/Inputs/resource_dir \
|
||||
// RUN: | FileCheck --check-prefixes=FILEPATH,NO-ARCHDIR %s
|
||||
//
|
||||
//
|
||||
// FILEPATH: "-x" "c" "[[FILE_PATH:.*]]/{{.*}}.c"
|
||||
// ARCHDIR-i386: -L[[FILE_PATH]]/Inputs/resource_dir_with_arch_subdir/lib/linux/i386
|
||||
// ARCHDIR-x86_64: -L[[FILE_PATH]]/Inputs/resource_dir_with_arch_subdir/lib/linux/x86_64
|
||||
// ARCHDIR-arm: -L[[FILE_PATH]]/Inputs/resource_dir_with_arch_subdir/lib/linux/arm
|
||||
// ARCHDIR-aarch64: -L[[FILE_PATH]]/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.
|
||||
// NO-ARCHDIR-NOT: -L[[FILE_PATH]]/Inputs/resource_dir
|
|
@ -397,6 +397,10 @@ if platform.system() not in ['Darwin', 'Fuchsia']:
|
|||
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)
|
||||
|
|
Loading…
Reference in New Issue