Skip to content

Commit c64042d

Browse files
committed
WIP
1 parent 9b3e4a2 commit c64042d

File tree

3 files changed

+87
-33
lines changed

3 files changed

+87
-33
lines changed

cargo/private/cargo_build_script.bzl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ def _cargo_build_script_impl(ctx):
414414
# Pull in env vars which may be required for the cc_toolchain to work (e.g. on OSX, the SDK version).
415415
# We hope that the linker env is sufficient for the whole cc_toolchain.
416416
cc_toolchain, feature_configuration = find_cc_toolchain(ctx)
417-
linker, link_args, linker_env = get_linker_and_args(ctx, "bin", toolchain, cc_toolchain, feature_configuration, None)
417+
linker, _, link_args, linker_env = get_linker_and_args(ctx, "bin", toolchain, cc_toolchain, feature_configuration, None)
418418
env.update(**linker_env)
419419
env["LD"] = linker
420420
env["LDFLAGS"] = " ".join(_pwd_flags(link_args))

rust/private/rustc.bzl

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -422,12 +422,14 @@ def get_linker_and_args(ctx, crate_type, toolchain, cc_toolchain, feature_config
422422
Returns:
423423
tuple: A tuple of the following items:
424424
- (str): The tool path for given action.
425+
- (bool): Whether or not the linker is a direct driver (e.g. `ld`) vs a wrapper (e.g. `gcc`).
425426
- (sequence): A flattened command line flags for given action.
426427
- (dict): Environment variables to be set for given action.
427428
"""
428429
user_link_flags = get_cc_user_link_flags(ctx)
429430

430431
ld = None
432+
ld_is_direct_driver = False
431433
link_args = []
432434
link_env = {}
433435

@@ -471,9 +473,11 @@ def get_linker_and_args(ctx, crate_type, toolchain, cc_toolchain, feature_config
471473
feature_configuration = feature_configuration,
472474
action_name = action_name,
473475
)
476+
ld_is_direct_driver = False
474477

475478
if not ld and toolchain.linker:
476479
ld = toolchain.linker.path
480+
ld_is_direct_driver = toolchain.linker_type == "direct"
477481

478482
if not ld:
479483
fail("No linker available for rustc. Either `rust_toolchain.linker` must be set or a `cc_toolchain` configured for the current configuration.")
@@ -490,7 +494,7 @@ def get_linker_and_args(ctx, crate_type, toolchain, cc_toolchain, feature_config
490494
for element in link_env["LIB"].split(";")
491495
])
492496

493-
return ld, link_args, link_env
497+
return ld, ld_is_direct_driver, link_args, link_env
494498

495499
def _symlink_for_ambiguous_lib(actions, toolchain, crate_info, lib):
496500
"""Constructs a disambiguating symlink for a library dependency.
@@ -1041,6 +1045,10 @@ def construct_arguments(
10411045
_add_lto_flags(ctx, toolchain, rustc_flags, crate_info)
10421046
_add_codegen_units_flags(toolchain, emit, rustc_flags)
10431047

1048+
# Use linker_type to determine whether to use direct or indirect linker invocation
1049+
# If linker_type is not explicitly set, infer from which linker is actually being used
1050+
ld_is_direct_driver = False
1051+
10441052
# Link!
10451053
if ("link" in emit and crate_info.type not in ["rlib", "lib"]) or add_flags_for_binary:
10461054
# Rust's built-in linker can handle linking wasm files. We don't want to attempt to use the cc
@@ -1053,7 +1061,7 @@ def construct_arguments(
10531061
else:
10541062
rpaths = depset()
10551063

1056-
ld, link_args, link_env = get_linker_and_args(
1064+
ld, ld_is_direct_driver, link_args, link_env = get_linker_and_args(
10571065
ctx,
10581066
crate_info.type,
10591067
toolchain,
@@ -1080,6 +1088,7 @@ def construct_arguments(
10801088
cc_toolchain,
10811089
feature_configuration,
10821090
compilation_mode,
1091+
ld_is_direct_driver,
10831092
include_link_flags = include_link_flags,
10841093
)
10851094

@@ -2308,6 +2317,7 @@ def _add_native_link_flags(
23082317
cc_toolchain,
23092318
feature_configuration,
23102319
compilation_mode,
2320+
use_direct_link_driver,
23112321
include_link_flags = True):
23122322
"""Adds linker flags for all dependencies of the current target.
23132323
@@ -2321,29 +2331,14 @@ def _add_native_link_flags(
23212331
cc_toolchain (CcToolchainInfo): The current `cc_toolchain`
23222332
feature_configuration (FeatureConfiguration): feature configuration to use with cc_toolchain
23232333
compilation_mode (bool): The compilation mode for this build.
2334+
use_direct_link_driver (bool): Whether the linker is a direct driver (e.g. `ld`, `wasm-ld`) vs a wrapper (e.g. `clang`, `gcc`).
23242335
include_link_flags (bool, optional): Whether to include flags like `-l` that instruct the linker to search for a library.
23252336
"""
23262337
if crate_type in ["lib", "rlib"]:
23272338
return
23282339

23292340
use_pic = _should_use_pic(cc_toolchain, feature_configuration, crate_type, compilation_mode)
23302341

2331-
# Use linker_type to determine whether to use direct or indirect linker invocation
2332-
# If linker_type is not explicitly set, infer from which linker is actually being used
2333-
use_direct_link_driver = False
2334-
if toolchain.linker_type:
2335-
# Explicit linker_type takes precedence
2336-
use_direct_link_driver = toolchain.linker_type == "direct"
2337-
elif toolchain.linker_preference == "rust":
2338-
# If rust linker is preferred, use direct invocation
2339-
use_direct_link_driver = True
2340-
elif toolchain.linker_preference == "cc" or (cc_toolchain and toolchain.linker_preference != "rust"):
2341-
# If cc linker is preferred or being used, use indirect invocation
2342-
use_direct_link_driver = False
2343-
elif toolchain.linker:
2344-
# If we have a rust linker available and no cc_toolchain, use direct invocation
2345-
use_direct_link_driver = True
2346-
23472342
make_link_flags, get_lib_name = _get_make_link_flag_funcs(
23482343
target_os = toolchain.target_os,
23492344
target_abi = toolchain.target_abi,

test/unit/native_deps/native_deps_test.bzl

Lines changed: 73 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,54 @@ def _get_bin_dir_from_action(action):
3232
bin_dir = bin_dir.split("/bin/")[0] + "/bin"
3333
return bin_dir
3434

35+
def _get_darwin_component(arg):
36+
"""Extract darwin component from a path.
37+
38+
Args:
39+
arg: Path like "path/to/darwin_x86_64-fastbuild-ST-abc123/package"
40+
41+
Returns:
42+
Darwin component like "darwin" (ignoring arch and compilation mode)
43+
"""
44+
45+
# path/to/darwin_x86_64-fastbuild-ST-abc123/package -> darwin_x86_64-fastbuild-ST-abc123
46+
darwin_component = [x for x in arg.split("/") if x.startswith("darwin")][0]
47+
48+
# darwin_x86_64-fastbuild-ST-abc123 -> darwin
49+
return darwin_component.split("-")[0]
50+
51+
def _assert_bin_dir_structure(env, ctx, bin_dir, toolchain):
52+
"""Validate bin_dir structure, ignoring ST-{hash} suffix from config transitions.
53+
54+
Args:
55+
env: The analysis test environment
56+
ctx: The test context
57+
bin_dir: The bin directory path to validate
58+
toolchain: The toolchain info
59+
"""
60+
compilation_mode = ctx.var["COMPILATION_MODE"]
61+
62+
# bin_dir should be like: bazel-out/{platform}-{mode}[-ST-{hash}]/bin
63+
asserts.true(env, bin_dir.startswith("bazel-out/"), "bin_dir should start with bazel-out/")
64+
asserts.true(env, bin_dir.endswith("/bin"), "bin_dir should end with /bin")
65+
66+
# Validate it contains compilation mode (ignoring potential ST-{hash})
67+
bin_dir_components = bin_dir.split("/")[1] # Get the platform-mode component
68+
asserts.true(
69+
env,
70+
compilation_mode in bin_dir_components,
71+
"bin_dir should contain compilation mode: expected '{}' in '{}'".format(compilation_mode, bin_dir_components),
72+
)
73+
74+
# For Darwin platforms, validate darwin component
75+
if toolchain.target_os in ["macos", "darwin"] and "darwin" in bin_dir:
76+
darwin_component = _get_darwin_component(bin_dir)
77+
asserts.true(
78+
env,
79+
darwin_component.startswith("darwin"),
80+
"darwin component should start with 'darwin', got '{}'".format(darwin_component),
81+
)
82+
3583
def _rlib_has_no_native_libs_test_impl(ctx):
3684
env = analysistest.begin(ctx)
3785
tut = analysistest.target_under_test(env)
@@ -138,7 +186,7 @@ def _extract_linker_args(argv):
138186
)
139187
]
140188

141-
def _bin_has_native_dep_and_alwayslink_test_impl(ctx):
189+
def _bin_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
142190
env = analysistest.begin(ctx)
143191
tut = analysistest.target_under_test(env)
144192
action = tut.actions[0]
@@ -147,8 +195,9 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx):
147195
link_args = _extract_linker_args(action.argv)
148196
bin_dir = _get_bin_dir_from_action(action)
149197

150-
# Use the explicit test attribute to determine expected behavior
151-
use_cc_linker = ctx.attr._use_cc_linker
198+
# Validate bin_dir structure (ignoring ST-{hash} suffix from config transitions)
199+
_assert_bin_dir_structure(env, ctx, bin_dir, toolchain)
200+
152201
if toolchain.target_os in ["macos", "darwin"]:
153202
if use_cc_linker:
154203
# When using CC linker, args are passed with -Wl, prefix as separate arguments
@@ -216,7 +265,7 @@ def _bin_has_native_dep_and_alwayslink_test_impl(ctx):
216265
assert_list_contains_adjacent_elements(env, link_args, want)
217266
return analysistest.end(env)
218267

219-
def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx):
268+
def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, use_cc_linker):
220269
toolchain = _get_toolchain(ctx)
221270

222271
env = analysistest.begin(ctx)
@@ -226,11 +275,12 @@ def _cdylib_has_native_dep_and_alwayslink_test_impl(ctx):
226275
linker_args = _extract_linker_args(action.argv)
227276
bin_dir = _get_bin_dir_from_action(action)
228277

278+
# Validate bin_dir structure (ignoring ST-{hash} suffix from config transitions)
279+
_assert_bin_dir_structure(env, ctx, bin_dir, toolchain)
280+
229281
compilation_mode = ctx.var["COMPILATION_MODE"]
230282
pic_suffix = _get_pic_suffix(ctx, compilation_mode)
231283

232-
# Use the explicit test attribute to determine expected behavior
233-
use_cc_linker = ctx.attr._use_cc_linker
234284
if toolchain.target_os in ["macos", "darwin"]:
235285
if use_cc_linker:
236286
# When using CC linker, args are passed with -Wl, prefix as separate arguments
@@ -319,48 +369,57 @@ bin_has_native_libs_test = analysistest.make(_bin_has_native_libs_test_impl, att
319369
"_linker_preference": attr.label(default = Label("//rust/settings:toolchain_linker_preference")),
320370
"_toolchain": attr.label(default = Label("//rust/toolchain:current_rust_toolchain")),
321371
})
372+
373+
def _bin_has_native_dep_and_alwayslink_rust_linker_test_impl(ctx):
374+
return _bin_has_native_dep_and_alwayslink_test_impl(ctx, False)
375+
322376
bin_has_native_dep_and_alwayslink_rust_linker_test = analysistest.make(
323-
_bin_has_native_dep_and_alwayslink_test_impl,
377+
_bin_has_native_dep_and_alwayslink_rust_linker_test_impl,
324378
attrs = {
325379
"_linker_preference": attr.label(default = Label("//rust/settings:toolchain_linker_preference")),
326380
"_toolchain": attr.label(default = Label("//rust/toolchain:current_rust_toolchain")),
327-
"_use_cc_linker": attr.bool(default = False, doc = "Whether to expect CC linker flags (vs rust-lld)"),
328381
},
329382
config_settings = {
330383
str(Label("//rust/settings:toolchain_linker_preference")): "rust",
331384
},
332385
)
333386

387+
def _bin_has_native_dep_and_alwayslink_cc_linker_test_impl(ctx):
388+
return _bin_has_native_dep_and_alwayslink_test_impl(ctx, True)
389+
334390
bin_has_native_dep_and_alwayslink_cc_linker_test = analysistest.make(
335-
_bin_has_native_dep_and_alwayslink_test_impl,
391+
_bin_has_native_dep_and_alwayslink_cc_linker_test_impl,
336392
attrs = {
337393
"_linker_preference": attr.label(default = Label("//rust/settings:toolchain_linker_preference")),
338394
"_toolchain": attr.label(default = Label("//rust/toolchain:current_rust_toolchain")),
339-
"_use_cc_linker": attr.bool(default = True, doc = "Whether to expect CC linker flags (vs rust-lld)"),
340395
},
341396
config_settings = {
342397
str(Label("//rust/settings:toolchain_linker_preference")): "cc",
343398
},
344399
)
345400

401+
def _cdylib_has_native_dep_and_alwayslink_rust_linker_test_impl(ctx):
402+
return _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, False)
403+
346404
cdylib_has_native_dep_and_alwayslink_rust_linker_test = analysistest.make(
347-
_cdylib_has_native_dep_and_alwayslink_test_impl,
405+
_cdylib_has_native_dep_and_alwayslink_rust_linker_test_impl,
348406
attrs = {
349407
"_linker_preference": attr.label(default = Label("//rust/settings:toolchain_linker_preference")),
350408
"_toolchain": attr.label(default = Label("//rust/toolchain:current_rust_toolchain")),
351-
"_use_cc_linker": attr.bool(default = False, doc = "Whether to expect CC linker flags (vs rust-lld)"),
352409
},
353410
config_settings = {
354411
str(Label("//rust/settings:toolchain_linker_preference")): "rust",
355412
},
356413
)
357414

415+
def _cdylib_has_native_dep_and_alwayslink_cc_linker_test_impl(ctx):
416+
return _cdylib_has_native_dep_and_alwayslink_test_impl(ctx, True)
417+
358418
cdylib_has_native_dep_and_alwayslink_cc_linker_test = analysistest.make(
359-
_cdylib_has_native_dep_and_alwayslink_test_impl,
419+
_cdylib_has_native_dep_and_alwayslink_cc_linker_test_impl,
360420
attrs = {
361421
"_linker_preference": attr.label(default = Label("//rust/settings:toolchain_linker_preference")),
362422
"_toolchain": attr.label(default = Label("//rust/toolchain:current_rust_toolchain")),
363-
"_use_cc_linker": attr.bool(default = True, doc = "Whether to expect CC linker flags (vs rust-lld)"),
364423
},
365424
config_settings = {
366425
str(Label("//rust/settings:toolchain_linker_preference")): "cc",

0 commit comments

Comments
 (0)