Skip to content

Commit 46550dc

Browse files
authored
Include transitive out_dirs in linking action (#3579)
If a build script compiles a file which is needed at linking time, and adds a linker flag to add it to the search path, we need the out_dir to be present in the link action in order for the search path flag to actually take effect. This was the original behaviour way back in 3a569b8 but got removed in 9426a38 which was intending to only restrict where flags were propagated but also stopped propagating out_dir files. This is required because cargo uses the path to the out_dir as a well-known-path that doesn't move between builds, so link flags from a build script which get transitively propagated up to a link action happen to point at the right location on disk. We need to propagate this out_dir because the known location on disk is probably in a sandbox, so we need to explicitly materialise the files into the sandbox.
1 parent 41405f1 commit 46550dc

File tree

4 files changed

+56
-1
lines changed

4 files changed

+56
-1
lines changed

rust/private/rustc.bzl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1891,6 +1891,7 @@ def _create_extra_input_args(build_info, dep_info, include_link_flags = True):
18911891
build_env_file = None
18921892
build_flags_files = []
18931893

1894+
# We include the direct dep build_info because crates which use cargo build scripts may need to e.g. include_str! a generated file.
18941895
if build_info:
18951896
if build_info.out_dir:
18961897
out_dir = build_info.out_dir.path
@@ -1904,6 +1905,12 @@ def _create_extra_input_args(build_info, dep_info, include_link_flags = True):
19041905

19051906
input_depsets.append(build_info.compile_data)
19061907

1908+
# We include transitive dep build_infos because cargo build scripts may generate files which get linked into the final binary.
1909+
# This should probably only actually be exposed to actions which link.
1910+
for dep_build_info in dep_info.transitive_build_infos.to_list():
1911+
if dep_build_info.out_dir:
1912+
input_files.append(dep_build_info.out_dir)
1913+
19071914
out_dir_compile_inputs = depset(
19081915
input_files,
19091916
transitive = [dep_info.link_search_path_files, dep_info.transitive_data] + input_depsets,

test/unit/common.bzl

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,24 @@ def _startswith(list, prefix):
7070
return False
7171
return True
7272

73+
def assert_list_contains(env, list, expected_element):
74+
"""Assert that list contains the expected element.
75+
76+
Args:
77+
env: env from analysistest.begin(ctx).
78+
list: list supposed to contain expected_element.
79+
expected_element: element to be found inside list.
80+
"""
81+
if expected_element in list:
82+
return
83+
unittest.fail(
84+
env,
85+
"Expected the to find '{expected_element}' within '{list}'".format(
86+
expected_element = expected_element,
87+
list = list,
88+
),
89+
)
90+
7391
def assert_list_contains_adjacent_elements(env, list_under_test, adjacent_elements):
7492
"""Assert that list_under_test contains given adjacent flags.
7593
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn main() {
2+
println!("dummy file");
3+
}

test/unit/transitive_link_search_paths/transitive_link_search_paths_test.bzl

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@
22

33
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
44
load("//cargo:defs.bzl", "cargo_build_script")
5-
load("//rust:defs.bzl", "rust_common", "rust_library", "rust_proc_macro")
5+
load("//rust:defs.bzl", "rust_binary", "rust_common", "rust_library", "rust_proc_macro")
6+
load("//test/unit:common.bzl", "assert_action_mnemonic", "assert_list_contains")
67

78
def _transitive_link_search_paths_test_impl(ctx):
89
env = analysistest.begin(ctx)
@@ -18,6 +19,19 @@ def _transitive_link_search_paths_test_impl(ctx):
1819

1920
transitive_link_search_paths_test = analysistest.make(_transitive_link_search_paths_test_impl)
2021

22+
def _transitive_out_dir_test_impl(ctx):
23+
env = analysistest.begin(ctx)
24+
tut = analysistest.target_under_test(env)
25+
action = tut.actions[0]
26+
assert_action_mnemonic(env, action, "Rustc")
27+
inputs = action.inputs.to_list()
28+
input_basenames = [f.basename for f in inputs]
29+
assert_list_contains(env, input_basenames, "dep_build_script.out_dir")
30+
31+
return analysistest.end(env)
32+
33+
transitive_out_dir_test = analysistest.make(_transitive_out_dir_test_impl)
34+
2135
def _transitive_link_search_paths_test():
2236
cargo_build_script(
2337
name = "proc_macro_build_script",
@@ -46,11 +60,23 @@ def _transitive_link_search_paths_test():
4660
deps = [":dep_build_script"],
4761
)
4862

63+
rust_binary(
64+
name = "bin",
65+
srcs = ["bin.rs"],
66+
edition = "2018",
67+
deps = [":dep"],
68+
)
69+
4970
transitive_link_search_paths_test(
5071
name = "transitive_link_search_paths_test",
5172
target_under_test = ":dep",
5273
)
5374

75+
transitive_out_dir_test(
76+
name = "transitive_out_dir_test",
77+
target_under_test = ":bin",
78+
)
79+
5480
def transitive_link_search_paths_test_suite(name):
5581
"""Entry-point macro called from the BUILD file.
5682
@@ -63,5 +89,6 @@ def transitive_link_search_paths_test_suite(name):
6389
name = name,
6490
tests = [
6591
":transitive_link_search_paths_test",
92+
":transitive_out_dir_test",
6693
],
6794
)

0 commit comments

Comments
 (0)