Skip to content

Commit 35e32d8

Browse files
authored
[Driver][SYCL] Initial support for allowing fat static -lname processing (#5413)
When processing for fat static libraries, add searches for -lname type libraries passed on the command line. This also takes advantage of the -Ldir options and LIBRARY_PATH environment variable for locating the libraries. When a library is found (with a .a extension) that is what is used for unbundling and added to the device link. NOTE: This behavior does not match the recent implementation done for OpenMP offloading with fat static libraries. That implementation is directly integrated into the llvm-link call. It would be good to also follow this for consistency, but will require some refactoring to accomplish.
1 parent 6f40376 commit 35e32d8

File tree

2 files changed

+57
-0
lines changed

2 files changed

+57
-0
lines changed

clang/lib/Driver/Driver.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2977,6 +2977,41 @@ static bool optionMatches(const std::string &Option,
29772977
static SmallVector<const char *, 16>
29782978
getLinkerArgs(Compilation &C, DerivedArgList &Args, bool IncludeObj = false) {
29792979
SmallVector<const char *, 16> LibArgs;
2980+
SmallVector<std::string, 8> LibPaths;
2981+
// Add search directories from LIBRARY_PATH env variable
2982+
llvm::Optional<std::string> LibPath =
2983+
llvm::sys::Process::GetEnv("LIBRARY_PATH");
2984+
if (LibPath) {
2985+
SmallVector<StringRef, 8> SplitPaths;
2986+
const char EnvPathSeparatorStr[] = {llvm::sys::EnvPathSeparator, '\0'};
2987+
llvm::SplitString(*LibPath, SplitPaths, EnvPathSeparatorStr);
2988+
for (StringRef Path : SplitPaths)
2989+
LibPaths.emplace_back(Path.trim());
2990+
}
2991+
// Add directories from user-specified -L options
2992+
for (std::string LibDirs : Args.getAllArgValues(options::OPT_L))
2993+
LibPaths.emplace_back(LibDirs);
2994+
2995+
// Do processing for any -l<arg> options passed and see if any static
2996+
// libraries representing the name exists. If so, convert the name and
2997+
// use that inline with the rest of the libraries.
2998+
// TODO: The static archive processing for SYCL is done in a different
2999+
// manner than the OpenMP processing. We should try and refactor this
3000+
// to use the OpenMP flow (adding -l<name> to the llvm-link step)
3001+
auto resolveStaticLib = [&](StringRef LibName) -> bool {
3002+
if (!LibName.startswith("-l"))
3003+
return false;
3004+
for (auto LPath : LibPaths) {
3005+
SmallString<128> FullName(LPath);
3006+
llvm::sys::path::append(FullName,
3007+
Twine("lib" + LibName.substr(2) + ".a").str());
3008+
if (llvm::sys::fs::exists(FullName)) {
3009+
LibArgs.push_back(Args.MakeArgString(FullName));
3010+
return true;
3011+
}
3012+
}
3013+
return false;
3014+
};
29803015
for (const auto *A : Args) {
29813016
std::string FileName = A->getAsString(Args);
29823017
if (A->getOption().getKind() == Option::InputClass) {
@@ -3014,6 +3049,7 @@ getLinkerArgs(Compilation &C, DerivedArgList &Args, bool IncludeObj = false) {
30143049
LibArgs.push_back(Args.MakeArgString(V));
30153050
return;
30163051
}
3052+
resolveStaticLib(V);
30173053
};
30183054
if (Value[0] == '@') {
30193055
// Found a response file, we want to expand contents to try and
@@ -3053,6 +3089,8 @@ getLinkerArgs(Compilation &C, DerivedArgList &Args, bool IncludeObj = false) {
30533089
LibArgs.push_back("--no-whole-archive");
30543090
continue;
30553091
}
3092+
if (A->getOption().matches(options::OPT_l))
3093+
resolveStaticLib(A->getAsString(Args));
30563094
}
30573095
return LibArgs;
30583096
}

clang/test/Driver/sycl-offload-static-lib-2.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,25 @@
3434
// STATIC_LIB_NVPTX: llvm-link{{.*}} "[[OUTFILE]]"
3535
// STATIC_LIB: ld{{.*}} "{{.*}}_lib.{{(a|lo)}}" "[[HOSTOBJ]]"
3636

37+
// Test using -l<name> style for passing libraries.
38+
// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -L%S/Inputs/SYCL -llin64 -### %t_obj.o 2>&1 \
39+
// RUN: | FileCheck %s -check-prefixes=STATIC_L_LIB,STATIC_L_LIB_DEF -DBUNDLE_TRIPLE=sycl-spir64-unknown-unknown
40+
// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=nvptx64-nvidia-cuda -L%S/Inputs/SYCL -llin64 -### %t_obj.o 2>&1 \
41+
// RUN: | FileCheck %s -check-prefixes=STATIC_L_LIB,STATIC_L_LIB_NVPTX -DBUNDLE_TRIPLE=sycl-nvptx64-nvidia-cuda-sm_50
42+
// STATIC_L_LIB: clang-offload-bundler{{.*}} "-type=o" "-targets={{.*}},[[BUNDLE_TRIPLE]]" "-inputs=[[INPUTO:.+\.o]]" "-outputs=[[HOSTOBJ:.+\.o]],{{.+\.o}}"
43+
// STATIC_L_LIB: clang-offload-deps{{.*}} "-targets=[[BUNDLE_TRIPLE]]"
44+
// STATIC_L_LIB_DEF: clang-offload-bundler{{.*}} "-type=aoo" "-targets=[[BUNDLE_TRIPLE]]" "-inputs={{.*}}liblin64.a" "-outputs=[[OUTFILE:.+\.txt]]"
45+
// STATIC_L_LIB_NVPTX: clang-offload-bundler{{.*}} "-type=a" "-targets=[[BUNDLE_TRIPLE]]" "-inputs={{.*}}liblin64.a" "-outputs=[[OUTFILE:.+\.a]]"
46+
// STATIC_L_LIB_DEF: llvm-foreach{{.*}} "--out-ext=txt" "--in-file-list=[[OUTFILE]]" "--in-replace=[[OUTFILE]]" "--out-file-list=[[IROUTFILE:.+\.txt]]" "--out-replace=[[IROUTFILE]]" "--" {{.*}}spirv-to-ir-wrapper{{.*}} "[[OUTFILE]]" "-o" "[[IROUTFILE]]"
47+
// STATIC_L_LIB_DEF: llvm-link{{.*}} "@[[IROUTFILE]]"
48+
// STATIC_L_LIB_NVPTX: llvm-link{{.*}} "[[OUTFILE]]"
49+
// STATIC_L_LIB: ld{{.*}} "-llin64" "[[HOSTOBJ]]"
50+
51+
// non-fat libraries should not trigger the unbundling step.
52+
// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -lc -lm -ldl -### 2>&1 \
53+
// RUN: | FileCheck %s -check-prefixes=NO_STATIC_UNBUNDLE
54+
// NO_STATIC_UNBUNDLE-NOT: clang-offload-bundler{{.*}} "-type=aoo" {{.*}} "-inputs={{.*}}lib{{.*}}.a"
55+
3756
/// ###########################################################################
3857

3958
/// test behaviors of fat static lib with multiple objects

0 commit comments

Comments
 (0)