Skip to content

Commit bad49c4

Browse files
authored
Build rust_test targets using a crate name different from the underlying lib (#2828)
This is a rollforward of #2803, but behind the `incompatible_change_rust_test_compilation_output_directory` incompatible flag. This PR also makes `rust_test` put its compilation outputs in the same directory as the `rust_library` rule (i.e. not in a `test-{hash}` subdirectory anymore). After this change both the `rust_library` and `rust_test` rules will put all its compilation outputs in the same directory, but there won't be any name collisions in non-sandboxed environments (see #1427 for more context). Issue with context: #2827
1 parent 5063cd8 commit bad49c4

File tree

8 files changed

+142
-26
lines changed

8 files changed

+142
-26
lines changed

docs/src/flatten.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1050,9 +1050,7 @@ rust_test(
10501050
)
10511051
```
10521052

1053-
Run the test with `bazel test //hello_lib:hello_lib_test`. The crate
1054-
will be built using the same crate name as the underlying ":hello_lib"
1055-
crate.
1053+
Run the test with `bazel test //hello_lib:hello_lib_test`.
10561054

10571055
### Example: `test` directory
10581056

docs/src/rust.md

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -567,9 +567,7 @@ rust_test(
567567
)
568568
```
569569

570-
Run the test with `bazel test //hello_lib:hello_lib_test`. The crate
571-
will be built using the same crate name as the underlying ":hello_lib"
572-
crate.
570+
Run the test with `bazel test //hello_lib:hello_lib_test`.
573571

574572
### Example: `test` directory
575573

rust/private/rust.bzl

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -309,14 +309,21 @@ def _rust_test_impl(ctx):
309309
# Target is building the crate in `test` config
310310
crate = ctx.attr.crate[rust_common.crate_info] if rust_common.crate_info in ctx.attr.crate else ctx.attr.crate[rust_common.test_crate_info].crate
311311

312-
output_hash = determine_output_hash(crate.root, ctx.label)
313-
output = ctx.actions.declare_file(
314-
"test-%s/%s%s" % (
315-
output_hash,
316-
ctx.label.name,
317-
toolchain.binary_ext,
318-
),
319-
)
312+
if toolchain._incompatible_change_rust_test_compilation_output_directory:
313+
crate_name = compute_crate_name(ctx.workspace_name, ctx.label, toolchain, ctx.attr.crate_name)
314+
output = ctx.actions.declare_file(
315+
ctx.label.name + toolchain.binary_ext,
316+
)
317+
else:
318+
crate_name = crate.name
319+
output_hash = determine_output_hash(crate.root, ctx.label)
320+
output = ctx.actions.declare_file(
321+
"test-%s/%s%s" % (
322+
output_hash,
323+
ctx.label.name,
324+
toolchain.binary_ext,
325+
),
326+
)
320327

321328
srcs, crate_root = transform_sources(ctx, ctx.files.srcs, getattr(ctx.file, "crate_root", None))
322329

@@ -342,7 +349,7 @@ def _rust_test_impl(ctx):
342349

343350
# Build the test binary using the dependency's srcs.
344351
crate_info_dict = dict(
345-
name = crate.name,
352+
name = crate_name,
346353
type = crate_type,
347354
root = crate.root,
348355
srcs = depset(srcs, transitive = [crate.srcs]),
@@ -368,14 +375,19 @@ def _rust_test_impl(ctx):
368375
crate_root = crate_root_src(ctx.attr.name, ctx.attr.crate_name, ctx.files.srcs, crate_root_type)
369376
srcs, crate_root = transform_sources(ctx, ctx.files.srcs, crate_root)
370377

371-
output_hash = determine_output_hash(crate_root, ctx.label)
372-
output = ctx.actions.declare_file(
373-
"test-%s/%s%s" % (
374-
output_hash,
375-
ctx.label.name,
376-
toolchain.binary_ext,
377-
),
378-
)
378+
if toolchain._incompatible_change_rust_test_compilation_output_directory:
379+
output = ctx.actions.declare_file(
380+
ctx.label.name + toolchain.binary_ext,
381+
)
382+
else:
383+
output_hash = determine_output_hash(crate_root, ctx.label)
384+
output = ctx.actions.declare_file(
385+
"test-%s/%s%s" % (
386+
output_hash,
387+
ctx.label.name,
388+
toolchain.binary_ext,
389+
),
390+
)
379391

380392
data_paths = depset(direct = getattr(ctx.attr, "data", [])).to_list()
381393
rustc_env = expand_dict_value_locations(
@@ -1348,9 +1360,7 @@ rust_test = rule(
13481360
)
13491361
```
13501362
1351-
Run the test with `bazel test //hello_lib:hello_lib_test`. The crate
1352-
will be built using the same crate name as the underlying ":hello_lib"
1353-
crate.
1363+
Run the test with `bazel test //hello_lib:hello_lib_test`.
13541364
13551365
### Example: `test` directory
13561366

rust/settings/BUILD.bazel

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
22
load("@bazel_skylib//rules:common_settings.bzl", "bool_flag", "string_flag")
33
load("//rust/private:unpretty.bzl", "rust_unpretty_flag")
4+
load(":incompatible.bzl", "incompatible_flag")
45

56
package(default_visibility = ["//visibility:public"])
67

@@ -90,6 +91,13 @@ bool_flag(
9091
build_setting_default = True,
9192
)
9293

94+
# A flag to put rust_test compilation outputs in the same directory as the rust_library compilation outputs.
95+
incompatible_flag(
96+
name = "incompatible_change_rust_test_compilation_output_directory",
97+
build_setting_default = False,
98+
issue = "https://github.com/bazelbuild/rules_rust/issues/2827",
99+
)
100+
93101
# A flag to control whether to link libstd dynamically.
94102
bool_flag(
95103
name = "experimental_link_std_dylib",

rust/toolchain.bzl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ load(
1818
"is_std_dylib",
1919
"make_static_lib_symlink",
2020
)
21+
load("//rust/settings:incompatible.bzl", "IncompatibleFlagInfo")
2122

2223
rust_analyzer_toolchain = _rust_analyzer_toolchain
2324
rustfmt_toolchain = _rustfmt_toolchain
@@ -696,6 +697,7 @@ def _rust_toolchain_impl(ctx):
696697
_experimental_use_cc_common_link = _experimental_use_cc_common_link(ctx),
697698
_experimental_use_global_allocator = experimental_use_global_allocator,
698699
_experimental_use_coverage_metadata_files = ctx.attr._experimental_use_coverage_metadata_files[BuildSettingInfo].value,
700+
_incompatible_change_rust_test_compilation_output_directory = ctx.attr._incompatible_change_rust_test_compilation_output_directory[IncompatibleFlagInfo].enabled,
699701
_toolchain_generated_sysroot = ctx.attr._toolchain_generated_sysroot[BuildSettingInfo].value,
700702
_no_std = no_std,
701703
)
@@ -881,6 +883,9 @@ rust_toolchain = rule(
881883
"This flag is only relevant when used together with --@rules_rust//rust/settings:experimental_use_global_allocator."
882884
),
883885
),
886+
"_incompatible_change_rust_test_compilation_output_directory": attr.label(
887+
default = Label("//rust/settings:incompatible_change_rust_test_compilation_output_directory"),
888+
),
884889
"_no_std": attr.label(
885890
default = Label("//:no_std"),
886891
),
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
load(":rust_test_outputs.bzl", "rust_test_outputs_test_suite")
2+
3+
############################ UNIT TESTS #############################
4+
rust_test_outputs_test_suite(name = "rust_test_outputs_test_suite")
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub fn main() {}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
"""Tests for rust_test outputs directory."""
2+
3+
load("@bazel_skylib//lib:paths.bzl", "paths")
4+
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
5+
load("//rust:defs.bzl", "rust_binary", "rust_common", "rust_library", "rust_test")
6+
7+
def _rust_test_outputs_test(ctx):
8+
env = analysistest.begin(ctx)
9+
tut = analysistest.target_under_test(env)
10+
11+
output = tut[rust_common.crate_info].output
12+
13+
# Check compilation output is in directory with same name as package
14+
test_target_label = ctx.attr.target_under_test[0].label
15+
asserts.true(env, output.dirname.split("/")[-1] == test_target_label.package.split("/")[-1])
16+
17+
# Check compilation output has same name as crate name, ignoring possible binary extension
18+
output_filename_without_ext = paths.split_extension(output.basename)[0]
19+
asserts.true(env, output_filename_without_ext == tut[rust_common.crate_info].name)
20+
21+
return analysistest.end(env)
22+
23+
rust_test_outputs_test = analysistest.make(
24+
_rust_test_outputs_test,
25+
config_settings = {
26+
str(Label("//rust/settings:incompatible_change_rust_test_compilation_output_directory")): True,
27+
},
28+
)
29+
30+
def _rust_test_outputs_targets():
31+
rust_binary(
32+
name = "bin_outputs",
33+
srcs = ["foo.rs"],
34+
edition = "2018",
35+
)
36+
37+
rust_library(
38+
name = "lib_outputs",
39+
srcs = ["foo.rs"],
40+
edition = "2018",
41+
)
42+
43+
rust_test(
44+
name = "test_outputs_with_srcs",
45+
srcs = ["foo.rs"],
46+
edition = "2018",
47+
)
48+
49+
rust_test_outputs_test(
50+
name = "rust_test_outputs_using_srcs_attr",
51+
target_under_test = ":test_outputs_with_srcs",
52+
)
53+
54+
rust_test(
55+
name = "test_outputs_with_crate_from_bin",
56+
crate = "bin_outputs",
57+
edition = "2018",
58+
)
59+
60+
rust_test_outputs_test(
61+
name = "rust_test_outputs_using_crate_attr_from_bin",
62+
target_under_test = ":test_outputs_with_crate_from_bin",
63+
)
64+
65+
rust_test(
66+
name = "test_outputs_with_crate_from_lib",
67+
crate = "lib_outputs",
68+
edition = "2018",
69+
)
70+
71+
rust_test_outputs_test(
72+
name = "rust_test_outputs_using_crate_attr_from_lib",
73+
target_under_test = ":test_outputs_with_crate_from_lib",
74+
)
75+
76+
def rust_test_outputs_test_suite(name):
77+
"""Entry-point macro called from the BUILD file.
78+
79+
Args:
80+
name: Name of the macro.
81+
"""
82+
83+
_rust_test_outputs_targets()
84+
85+
native.test_suite(
86+
name = name,
87+
tests = [
88+
":rust_test_outputs_using_srcs_attr",
89+
":rust_test_outputs_using_crate_attr_from_bin",
90+
":rust_test_outputs_using_crate_attr_from_lib",
91+
],
92+
)

0 commit comments

Comments
 (0)