Skip to content

Commit a33f9c8

Browse files
authored
[Driver][SYCL] Improve -lname static linking with shared objects (#5790)
By default, the expectation for linking is dynamic. Abide by these rules when processing library files for fat static archives. For example: clang++ -fsycl -lname This should only attempt to unbundle libname.a when there is no libname.so found. Exception being when we are forcing static linking with options such as -static and -Wl,-Bstatic.
1 parent 28ada78 commit a33f9c8

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

clang/lib/Driver/Driver.cpp

+26-3
Original file line numberDiff line numberDiff line change
@@ -3013,10 +3013,19 @@ getLinkerArgs(Compilation &C, DerivedArgList &Args, bool IncludeObj = false) {
30133013
// TODO: The static archive processing for SYCL is done in a different
30143014
// manner than the OpenMP processing. We should try and refactor this
30153015
// to use the OpenMP flow (adding -l<name> to the llvm-link step)
3016-
auto resolveStaticLib = [&](StringRef LibName) -> bool {
3016+
auto resolveStaticLib = [&](StringRef LibName, bool IsStatic) -> bool {
30173017
if (!LibName.startswith("-l"))
30183018
return false;
30193019
for (auto LPath : LibPaths) {
3020+
if (!IsStatic) {
3021+
// Current linking state is dynamic. We will first check for the
3022+
// shared object and not pull in the static library if it is found.
3023+
SmallString<128> SoLibName(LPath);
3024+
llvm::sys::path::append(SoLibName,
3025+
Twine("lib" + LibName.substr(2) + ".so").str());
3026+
if (llvm::sys::fs::exists(SoLibName))
3027+
return false;
3028+
}
30203029
SmallString<128> FullName(LPath);
30213030
llvm::sys::path::append(FullName,
30223031
Twine("lib" + LibName.substr(2) + ".a").str());
@@ -3029,6 +3038,7 @@ getLinkerArgs(Compilation &C, DerivedArgList &Args, bool IncludeObj = false) {
30293038
};
30303039
for (const auto *A : Args) {
30313040
std::string FileName = A->getAsString(Args);
3041+
static bool IsLinkStateStatic(Args.hasArg(options::OPT_static));
30323042
auto addLibArg = [&](StringRef LibName) -> bool {
30333043
if (isStaticArchiveFile(LibName) ||
30343044
(IncludeObj && isObjectFile(LibName.str()))) {
@@ -3088,7 +3098,20 @@ getLinkerArgs(Compilation &C, DerivedArgList &Args, bool IncludeObj = false) {
30883098
LibArgs.push_back(Args.MakeArgString(V));
30893099
return;
30903100
}
3091-
resolveStaticLib(V);
3101+
if (optionMatches("-Bstatic", V.str()) ||
3102+
optionMatches("-dn", V.str()) ||
3103+
optionMatches("-non_shared", V.str()) ||
3104+
optionMatches("-static", V.str())) {
3105+
IsLinkStateStatic = true;
3106+
return;
3107+
}
3108+
if (optionMatches("-Bdynamic", V.str()) ||
3109+
optionMatches("-dy", V.str()) ||
3110+
optionMatches("-call_shared", V.str())) {
3111+
IsLinkStateStatic = false;
3112+
return;
3113+
}
3114+
resolveStaticLib(V, IsLinkStateStatic);
30923115
};
30933116
if (Value[0] == '@') {
30943117
// Found a response file, we want to expand contents to try and
@@ -3128,7 +3151,7 @@ getLinkerArgs(Compilation &C, DerivedArgList &Args, bool IncludeObj = false) {
31283151
continue;
31293152
}
31303153
if (A->getOption().matches(options::OPT_l))
3131-
resolveStaticLib(A->getAsString(Args));
3154+
resolveStaticLib(A->getAsString(Args), IsLinkStateStatic);
31323155
}
31333156
return LibArgs;
31343157
}

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

+9
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,14 @@
3535
// STATIC_LIB: ld{{.*}} "{{.*}}_lib.{{(a|lo)}}" "[[HOSTOBJ]]"
3636

3737
// Test using -l<name> style for passing libraries.
38+
// RUN: mkdir -p %t_dir
39+
// RUN: touch %t_dir/liblin64.so
3840
// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -L%S/Inputs/SYCL -llin64 -### %t_obj.o 2>&1 \
3941
// RUN: | FileCheck %s -check-prefixes=STATIC_L_LIB,STATIC_L_LIB_DEF -DBUNDLE_TRIPLE=sycl-spir64-unknown-unknown
42+
// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -static -L%t_dir -L%S/Inputs/SYCL -llin64 -### %t_obj.o 2>&1 \
43+
// RUN: | FileCheck %s -check-prefixes=STATIC_L_LIB,STATIC_L_LIB_DEF -DBUNDLE_TRIPLE=sycl-spir64-unknown-unknown
44+
// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -Xlinker -Bstatic -L%t_dir -L%S/Inputs/SYCL -llin64 -### %t_obj.o 2>&1 \
45+
// RUN: | FileCheck %s -check-prefixes=STATIC_L_LIB,STATIC_L_LIB_DEF -DBUNDLE_TRIPLE=sycl-spir64-unknown-unknown
4046
// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -fsycl-targets=nvptx64-nvidia-cuda -L%S/Inputs/SYCL -llin64 -### %t_obj.o 2>&1 \
4147
// RUN: | FileCheck %s -check-prefixes=STATIC_L_LIB,STATIC_L_LIB_NVPTX -DBUNDLE_TRIPLE=sycl-nvptx64-nvidia-cuda-sm_50
4248
// STATIC_L_LIB: clang-offload-bundler{{.*}} "-type=o" "-targets={{.*}},[[BUNDLE_TRIPLE]]" "-inputs=[[INPUTO:.+\.o]]" "-outputs=[[HOSTOBJ:.+\.o]],{{.+\.o}}"
@@ -49,6 +55,9 @@
4955
// STATIC_L_LIB: ld{{.*}} "-llin64" "[[HOSTOBJ]]"
5056

5157
// non-fat libraries should not trigger the unbundling step.
58+
// presence of shared object should not trigger unbundling step.
59+
// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -L%t_dir -L%S/Inputs/SYCL -llin64 -### 2>&1 \
60+
// RUN: | FileCheck %s -check-prefixes=NO_STATIC_UNBUNDLE
5261
// RUN: %clangxx -target x86_64-unknown-linux-gnu -fsycl -lc -lm -ldl -### 2>&1 \
5362
// RUN: | FileCheck %s -check-prefixes=NO_STATIC_UNBUNDLE
5463
// NO_STATIC_UNBUNDLE-NOT: clang-offload-bundler{{.*}} "-type=aoo" {{.*}} "-inputs={{.*}}lib{{.*}}.a"

0 commit comments

Comments
 (0)