Skip to content

Commit 05d26c0

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

4 files changed

Lines changed: 72 additions & 50 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: 14 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,13 @@ 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+
return None
62+
5063
def _get_lib_name(ctx, name):
5164
if ctx.target_platform_has_constraint(ctx.attr._windows_constraint[platform_common.ConstraintValueInfo]):
5265
return name

test/unit/native_deps/native_deps_test.bzl

Lines changed: 30 additions & 44 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)
@@ -94,78 +108,46 @@ def _cdylib_has_native_libs_test_impl(ctx):
94108
env = analysistest.begin(ctx)
95109
tut = analysistest.target_under_test(env)
96110
action = tut.actions[0]
97-
toolchain = _get_toolchain(ctx)
98111
compilation_mode = ctx.var["COMPILATION_MODE"]
99112
pic_suffix = _get_pic_suffix(ctx, compilation_mode)
100113
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
101114
assert_argv_contains(env, action, "--crate-type=cdylib")
102115
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)
116+
assert_argv_contains(env, action, _native_link_arg(ctx, action, pic_suffix))
111117
assert_argv_contains_prefix(env, action, "--codegen=linker=")
112118
return analysistest.end(env)
113119

114120
def _staticlib_has_native_libs_test_impl(ctx):
115121
env = analysistest.begin(ctx)
116122
tut = analysistest.target_under_test(env)
117123
action = tut.actions[0]
118-
toolchain = _get_toolchain(ctx)
119124
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
120125
assert_argv_contains(env, action, "--crate-type=staticlib")
121126
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)
127+
assert_argv_contains(env, action, _native_link_arg(ctx, action))
130128
assert_argv_contains_prefix(env, action, "--codegen=linker=")
131129
return analysistest.end(env)
132130

133131
def _proc_macro_has_native_libs_test_impl(ctx):
134132
env = analysistest.begin(ctx)
135133
tut = analysistest.target_under_test(env)
136134
action = tut.actions[0]
137-
toolchain = _get_toolchain(ctx)
138135
compilation_mode = ctx.var["COMPILATION_MODE"]
139136
pic_suffix = _get_pic_suffix(ctx, compilation_mode)
140137
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
141138
assert_argv_contains(env, action, "--crate-type=proc-macro")
142139
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)
140+
assert_argv_contains(env, action, _native_link_arg(ctx, action, pic_suffix))
151141
assert_argv_contains_prefix(env, action, "--codegen=linker=")
152142
return analysistest.end(env)
153143

154144
def _bin_has_native_libs_test_impl(ctx):
155145
env = analysistest.begin(ctx)
156146
tut = analysistest.target_under_test(env)
157147
action = tut.actions[0]
158-
toolchain = _get_toolchain(ctx)
159148
assert_argv_contains_prefix_suffix(env, action, "-Lnative=", "/native_deps")
160149
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)
150+
assert_argv_contains(env, action, _native_link_arg(ctx, action))
169151
assert_argv_contains_prefix(env, action, "--codegen=linker=")
170152
return analysistest.end(env)
171153

@@ -197,21 +179,22 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
197179

198180
# Validate bin_dir structure (ignoring ST-{hash} suffix from config transitions)
199181
_assert_bin_dir_structure(env, ctx, bin_dir, toolchain)
182+
native_link_arg = _native_link_arg(ctx, action, stripped = True)
200183

201184
if toolchain.target_os in ["macos", "darwin"]:
202185
if use_cc_linker:
203186
# When using CC linker, args are passed with -Wl, prefix as separate arguments
204187
want = [
205188
"-lstatic=native_dep",
206-
"-lnative_dep",
189+
native_link_arg,
207190
"-Wl,-force_load",
208191
"-Wl,{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
209192
]
210193
else:
211194
# When using rust-lld directly, args are passed without prefix as separate arguments
212195
want = [
213196
"-lstatic=native_dep",
214-
"-lnative_dep",
197+
native_link_arg,
215198
"-force_load",
216199
"{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
217200
]
@@ -242,22 +225,23 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
242225
elif toolchain.target_arch == "s390x":
243226
want = [
244227
"-lstatic=native_dep",
228+
native_link_arg,
245229
"link-arg=-Wl,--whole-archive",
246230
"link-arg={}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
247231
"link-arg=-Wl,--no-whole-archive",
248232
]
249233
elif use_cc_linker:
250234
want = [
251235
"-lstatic=native_dep",
252-
"-lnative_dep",
236+
native_link_arg,
253237
"-Wl,--whole-archive",
254238
"{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
255239
"-Wl,--no-whole-archive",
256240
]
257241
else:
258242
want = [
259243
"-lstatic=native_dep",
260-
"-lnative_dep",
244+
native_link_arg,
261245
"--whole-archive",
262246
"{}/test/unit/native_deps/libalwayslink.lo".format(bin_dir),
263247
"--no-whole-archive",
@@ -280,21 +264,22 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
280264

281265
compilation_mode = ctx.var["COMPILATION_MODE"]
282266
pic_suffix = _get_pic_suffix(ctx, compilation_mode)
267+
native_link_arg = _native_link_arg(ctx, action, pic_suffix, stripped = True)
283268

284269
if toolchain.target_os in ["macos", "darwin"]:
285270
if use_cc_linker:
286271
# When using CC linker, args are passed with -Wl, prefix as separate arguments
287272
want = [
288273
"-lstatic=native_dep{}".format(pic_suffix),
289-
"-lnative_dep{}".format(pic_suffix),
274+
native_link_arg,
290275
"-Wl,-force_load",
291276
"-Wl,{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
292277
]
293278
else:
294279
# When using rust-lld directly, args are passed without prefix as separate arguments
295280
want = [
296281
"-lstatic=native_dep{}".format(pic_suffix),
297-
"-lnative_dep{}".format(pic_suffix),
282+
native_link_arg,
298283
"-force_load",
299284
"{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
300285
]
@@ -324,6 +309,7 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
324309
elif toolchain.target_arch == "s390x":
325310
want = [
326311
"-lstatic=native_dep{}".format(pic_suffix),
312+
native_link_arg,
327313
"link-arg=-Wl,--whole-archive",
328314
"link-arg={}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
329315
"link-arg=-Wl,--no-whole-archive",
@@ -332,7 +318,7 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
332318
# CC linker uses -Wl, prefix but arguments are separate
333319
want = [
334320
"-lstatic=native_dep{}".format(pic_suffix),
335-
"-lnative_dep{}".format(pic_suffix),
321+
native_link_arg,
336322
"-Wl,--whole-archive",
337323
"{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
338324
"-Wl,--no-whole-archive",
@@ -341,7 +327,7 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
341327
# rust-lld doesn't use -Wl, prefix, so flags and path are separate
342328
want = [
343329
"-lstatic=native_dep{}".format(pic_suffix),
344-
"-lnative_dep{}".format(pic_suffix),
330+
native_link_arg,
345331
"--whole-archive",
346332
"{}/test/unit/native_deps/libalwayslink{}.lo".format(bin_dir, pic_suffix),
347333
"--no-whole-archive",

test/unit/proc_macro/leaks_deps/proc_macro_does_not_leak_deps.bzl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,11 @@ def _proc_macro_does_not_leak_deps_impl(ctx):
3535
else:
3636
native_deps = [arg for arg in rustc_action.argv if arg == "-Clink-arg=-lnative.lib"]
3737
else:
38-
native_deps = [arg for arg in rustc_action.argv if arg == "-Clink-arg=-lnative"]
38+
native_deps = [
39+
arg
40+
for arg in rustc_action.argv
41+
if arg.startswith("-Clink-arg=") and arg.endswith("/test/unit/proc_macro/leaks_deps/native/libnative.a")
42+
]
3943
asserts.equals(env, 1, len(native_deps))
4044

4145
return analysistest.end(env)

0 commit comments

Comments
 (0)