Skip to content

Commit ff3b783

Browse files
committed
Fix static native library trailing link arg
1 parent f31db8b commit ff3b783

3 files changed

Lines changed: 66 additions & 45 deletions

File tree

rust/private/rustc.bzl

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2293,7 +2293,8 @@ def portable_link_flags(
22932293
ambiguous_libs,
22942294
get_lib_name,
22952295
for_darwin = False,
2296-
flavor_msvc = False):
2296+
flavor_msvc = False,
2297+
link_static_library_by_path = False):
22972298
"""_summary_
22982299
22992300
Args:
@@ -2303,6 +2304,8 @@ def portable_link_flags(
23032304
get_lib_name (_type_): _description_
23042305
for_darwin (bool, optional): _description_. Defaults to False.
23052306
flavor_msvc (bool, optional): _description_. Defaults to False.
2307+
link_static_library_by_path (bool, optional): Use the selected static artifact path for the
2308+
trailing `-Clink-arg` copy instead of `-l<name>`. Defaults to False.
23062309
23072310
Returns:
23082311
_type_: _description_
@@ -2352,9 +2355,12 @@ def portable_link_flags(
23522355
"-Clink-arg={}".format(artifact.basename),
23532356
]
23542357
else:
2358+
# Rustc may restore dynamic linker mode before appending -Clink-arg
2359+
# values, so use the selected archive path where supported.
2360+
late_static_link_arg = artifact.path if link_static_library_by_path else "-l{}".format(get_lib_name(artifact))
23552361
return [
23562362
"-lstatic=%s" % get_lib_name(artifact),
2357-
"-Clink-arg=-l{}".format(get_lib_name(artifact)),
2363+
"-Clink-arg={}".format(late_static_link_arg),
23582364
]
23592365
elif _is_dylib(lib):
23602366
return [
@@ -2409,7 +2415,14 @@ def _make_link_flags_darwin(make_link_flags_args, use_direct_driver):
24092415
("-Clink-arg=%s%s" % (prefix, get_preferred_artifact(lib, use_pic).path)),
24102416
])
24112417
elif include_link_flags:
2412-
ret.extend(portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name_default, for_darwin = True))
2418+
ret.extend(portable_link_flags(
2419+
lib,
2420+
use_pic,
2421+
ambiguous_libs,
2422+
get_lib_name_default,
2423+
for_darwin = True,
2424+
link_static_library_by_path = True,
2425+
))
24132426
_add_user_link_flags(ret, linker_input)
24142427
return ret
24152428

@@ -2425,7 +2438,13 @@ def _make_link_flags_default(make_link_flags_args, use_direct_driver):
24252438
("-Clink-arg=%s--no-whole-archive" % prefix),
24262439
])
24272440
elif include_link_flags:
2428-
ret.extend(portable_link_flags(lib, use_pic, ambiguous_libs, get_lib_name_default))
2441+
ret.extend(portable_link_flags(
2442+
lib,
2443+
use_pic,
2444+
ambiguous_libs,
2445+
get_lib_name_default,
2446+
link_static_library_by_path = True,
2447+
))
24292448
_add_user_link_flags(ret, linker_input)
24302449
return ret
24312450

test/unit/linker_inputs_propagation/linker_inputs_propagation_test.bzl

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,13 @@ def _dependency_linkopts_are_propagated_test_impl(ctx):
3030
# Expect a library's own linkopts to come after the flags we create to link them.
3131
# This is required, because linkopts are ordered and the linker will only apply later ones when resolving symbols required for earlier ones.
3232
# This means that if one of our transitive deps has a linkopt like `-lfoo`, the dep will see the symbols of foo at link time.
33-
_assert_contains_in_order(env, link_action.argv, ["-lstatic=foo_with_linkopts", "-Clink-arg=-lfoo_with_linkopts", "--codegen=link-arg=-L/doesnotexist"])
33+
native_link_arg = _find_arg_with_prefix_and_suffix(
34+
env,
35+
link_action.argv,
36+
"-Clink-arg=",
37+
"/test/linker_inputs_propagation/libfoo_with_linkopts.a",
38+
)
39+
_assert_contains_in_order(env, link_action.argv, ["-lstatic=foo_with_linkopts", native_link_arg, "--codegen=link-arg=-L/doesnotexist"])
3440
return analysistest.end(env)
3541

3642
def _assert_contains_input(env, inputs, name):
@@ -47,6 +53,12 @@ def _assert_contains_in_order(env, haystack, needle):
4753
return
4854
unittest.fail(env, "Expected {} to contain {}".format(haystack, needle))
4955

56+
def _find_arg_with_prefix_and_suffix(env, haystack, prefix, suffix):
57+
for arg in haystack:
58+
if arg.startswith(prefix) and arg.endswith(suffix):
59+
return arg
60+
unittest.fail(env, "Expected {} to contain an argument starting with {} and ending with {}".format(haystack, prefix, suffix))
61+
5062
def _get_lib_name(ctx, name):
5163
if ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]):
5264
return name

test/unit/native_deps/native_deps_test.bzl

Lines changed: 30 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,20 @@ def _assert_bin_dir_structure(env, ctx, bin_dir, toolchain):
8080
"darwin component should start with 'darwin', got '{}'".format(darwin_component),
8181
)
8282

83+
def _native_link_arg(ctx, action, pic_suffix = "", stripped = False):
84+
toolchain = _get_toolchain(ctx)
85+
if toolchain.target_os == "windows":
86+
if toolchain.target_triple.abi == "msvc":
87+
link_arg = "-Clink-arg=native_dep.lib"
88+
else:
89+
link_arg = "-Clink-arg=-lnative_dep.lib"
90+
else:
91+
link_arg = "-Clink-arg={}/test/unit/native_deps/libnative_dep{}.a".format(
92+
_get_bin_dir_from_action(action),
93+
pic_suffix,
94+
)
95+
return link_arg.removeprefix("-Clink-arg=") if stripped else link_arg
96+
8397
def _rlib_has_no_native_libs_test_impl(ctx):
8498
env = analysistest.begin(ctx)
8599
tut = analysistest.target_under_test(env)
@@ -100,14 +114,7 @@ def _cdylib_has_native_libs_test_impl(ctx):
100114
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
101115
assert_argv_contains(env, action, "--crate-type=cdylib")
102116
assert_argv_contains(env, action, "-lstatic=native_dep{}".format(pic_suffix))
103-
if toolchain.target_os == "windows":
104-
if toolchain.target_triple.abi == "msvc":
105-
native_link_arg = "-Clink-arg=native_dep.lib"
106-
else:
107-
native_link_arg = "-Clink-arg=-lnative_dep.lib"
108-
else:
109-
native_link_arg = "-Clink-arg=-lnative_dep{}".format(pic_suffix)
110-
assert_argv_contains(env, action, native_link_arg)
117+
assert_argv_contains(env, action, _native_link_arg(ctx, action, pic_suffix))
111118
assert_argv_contains_prefix(env, action, "--codegen=linker=")
112119
return analysistest.end(env)
113120

@@ -119,14 +126,7 @@ def _staticlib_has_native_libs_test_impl(ctx):
119126
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
120127
assert_argv_contains(env, action, "--crate-type=staticlib")
121128
assert_argv_contains(env, action, "-lstatic=native_dep")
122-
if toolchain.target_os == "windows":
123-
if toolchain.target_triple.abi == "msvc":
124-
native_link_arg = "-Clink-arg=native_dep.lib"
125-
else:
126-
native_link_arg = "-Clink-arg=-lnative_dep.lib"
127-
else:
128-
native_link_arg = "-Clink-arg=-lnative_dep"
129-
assert_argv_contains(env, action, native_link_arg)
129+
assert_argv_contains(env, action, _native_link_arg(ctx, action))
130130
assert_argv_contains_prefix(env, action, "--codegen=linker=")
131131
return analysistest.end(env)
132132

@@ -140,14 +140,7 @@ def _proc_macro_has_native_libs_test_impl(ctx):
140140
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
141141
assert_argv_contains(env, action, "--crate-type=proc-macro")
142142
assert_argv_contains(env, action, "-lstatic=native_dep{}".format(pic_suffix))
143-
if toolchain.target_os == "windows":
144-
if toolchain.target_triple.abi == "msvc":
145-
native_link_arg = "-Clink-arg=native_dep.lib"
146-
else:
147-
native_link_arg = "-Clink-arg=-lnative_dep.lib"
148-
else:
149-
native_link_arg = "-Clink-arg=-lnative_dep{}".format(pic_suffix)
150-
assert_argv_contains(env, action, native_link_arg)
143+
assert_argv_contains(env, action, _native_link_arg(ctx, action, pic_suffix))
151144
assert_argv_contains_prefix(env, action, "--codegen=linker=")
152145
return analysistest.end(env)
153146

@@ -158,14 +151,7 @@ def _bin_has_native_libs_test_impl(ctx):
158151
toolchain = _get_toolchain(ctx)
159152
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
160153
assert_argv_contains(env, action, "-lstatic=native_dep")
161-
if toolchain.target_os == "windows":
162-
if toolchain.target_triple.abi == "msvc":
163-
native_link_arg = "-Clink-arg=native_dep.lib"
164-
else:
165-
native_link_arg = "-Clink-arg=-lnative_dep.lib"
166-
else:
167-
native_link_arg = "-Clink-arg=-lnative_dep"
168-
assert_argv_contains(env, action, native_link_arg)
154+
assert_argv_contains(env, action, _native_link_arg(ctx, action))
169155
assert_argv_contains_prefix(env, action, "--codegen=linker=")
170156
return analysistest.end(env)
171157

@@ -197,21 +183,22 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
197183

198184
# Validate bin_dir structure (ignoring ST-{hash} suffix from config transitions)
199185
_assert_bin_dir_structure(env, ctx, bin_dir, toolchain)
186+
native_link_arg = _native_link_arg(ctx, action, stripped = True)
200187

201188
if toolchain.target_os in ["macos", "darwin"]:
202189
if use_cc_linker:
203190
# When using CC linker, args are passed with -Wl, prefix as separate arguments
204191
want = [
205192
"-lstatic=native_dep",
206-
"-lnative_dep",
193+
native_link_arg,
207194
"-Wl,-force_load",
208195
"-Wl,{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
209196
]
210197
else:
211198
# When using rust-lld directly, args are passed without prefix as separate arguments
212199
want = [
213200
"-lstatic=native_dep",
214-
"-lnative_dep",
201+
native_link_arg,
215202
"-force_load",
216203
"{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
217204
]
@@ -242,22 +229,23 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
242229
elif toolchain.target_arch == "s390x":
243230
want = [
244231
"-lstatic=native_dep",
232+
native_link_arg,
245233
"link-arg=-Wl,--whole-archive",
246234
"link-arg={}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
247235
"link-arg=-Wl,--no-whole-archive",
248236
]
249237
elif use_cc_linker:
250238
want = [
251239
"-lstatic=native_dep",
252-
"-lnative_dep",
240+
native_link_arg,
253241
"-Wl,--whole-archive",
254242
"{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
255243
"-Wl,--no-whole-archive",
256244
]
257245
else:
258246
want = [
259247
"-lstatic=native_dep",
260-
"-lnative_dep",
248+
native_link_arg,
261249
"--whole-archive",
262250
"{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
263251
"--no-whole-archive",
@@ -280,21 +268,22 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
280268

281269
compilation_mode = ctx.var["COMPILATION_MODE"]
282270
pic_suffix = _get_pic_suffix(ctx, compilation_mode)
271+
native_link_arg = _native_link_arg(ctx, action, pic_suffix, stripped = True)
283272

284273
if toolchain.target_os in ["macos", "darwin"]:
285274
if use_cc_linker:
286275
# When using CC linker, args are passed with -Wl, prefix as separate arguments
287276
want = [
288277
"-lstatic=native_dep{}".format(pic_suffix),
289-
"-lnative_dep{}".format(pic_suffix),
278+
native_link_arg,
290279
"-Wl,-force_load",
291280
"-Wl,{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
292281
]
293282
else:
294283
# When using rust-lld directly, args are passed without prefix as separate arguments
295284
want = [
296285
"-lstatic=native_dep{}".format(pic_suffix),
297-
"-lnative_dep{}".format(pic_suffix),
286+
native_link_arg,
298287
"-force_load",
299288
"{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
300289
]
@@ -324,6 +313,7 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
324313
elif toolchain.target_arch == "s390x":
325314
want = [
326315
"-lstatic=native_dep{}".format(pic_suffix),
316+
native_link_arg,
327317
"link-arg=-Wl,--whole-archive",
328318
"link-arg={}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
329319
"link-arg=-Wl,--no-whole-archive",
@@ -332,7 +322,7 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
332322
# CC linker uses -Wl, prefix but arguments are separate
333323
want = [
334324
"-lstatic=native_dep{}".format(pic_suffix),
335-
"-lnative_dep{}".format(pic_suffix),
325+
native_link_arg,
336326
"-Wl,--whole-archive",
337327
"{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
338328
"-Wl,--no-whole-archive",
@@ -341,7 +331,7 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
341331
# rust-lld doesn't use -Wl, prefix, so flags and path are separate
342332
want = [
343333
"-lstatic=native_dep{}".format(pic_suffix),
344-
"-lnative_dep{}".format(pic_suffix),
334+
native_link_arg,
345335
"--whole-archive",
346336
"{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
347337
"--no-whole-archive",

0 commit comments

Comments
 (0)