Skip to content

Commit aaf599b

Browse files
committed
Add setting always_enable_metadata_output_groups
Right now, only library targets provide metadata-related output groups. This makes sense for compilation purposes, but building the metadata is also useful for other things; namely, building *only* the metadata is the fastest way to get diagnostic information for your workspace like `cargo check` does. This PR adds a new setting, `always_enable_metadata_output_groups`, that enables both the `build_metadata` and `rustc_rmeta_output` output groups for non-library targets (such as binaries and tests). That means that the presence of metadata in `CrateInfo` can no longer be used to determine pipelind compilation support, so a new attribute, `metadata_supports_pipelining`, is added for that purpose. As an example of the performance increase, compare a `bazel build` on a binary w/o `--output_groups=rustc_rmeta_output`: INFO: Elapsed time: 2.247s, Critical Path: 2.11s to with it: INFO: Elapsed time: 1.034s, Critical Path: 0.90s
1 parent 62d7317 commit aaf599b

File tree

16 files changed

+336
-16
lines changed

16 files changed

+336
-16
lines changed

extensions/prost/private/prost.bzl

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,12 @@ load("@rules_rust//rust/private:rust_analyzer.bzl", "write_rust_analyzer_spec_fi
1818
load("@rules_rust//rust/private:rustc.bzl", "rustc_compile_action")
1919

2020
# buildifier: disable=bzl-visibility
21-
load("@rules_rust//rust/private:utils.bzl", "can_build_metadata")
21+
load(
22+
"@rules_rust//rust/private:utils.bzl",
23+
"can_build_metadata",
24+
"can_use_metadata_for_pipelining",
25+
"generate_output_diagnostics",
26+
)
2227
load("//:providers.bzl", "ProstProtoInfo")
2328
load(":prost_transform.bzl", "ProstTransformInfo")
2429

@@ -181,6 +186,8 @@ def _compile_rust(
181186

182187
lib = ctx.actions.declare_file(lib_name)
183188
rmeta = None
189+
rustc_rmeta_output = None
190+
metadata_supports_pipelining = False
184191

185192
if can_build_metadata(toolchain, ctx, "rlib"):
186193
rmeta_name = "{prefix}{name}-{lib_hash}{extension}".format(
@@ -190,6 +197,8 @@ def _compile_rust(
190197
extension = ".rmeta",
191198
)
192199
rmeta = ctx.actions.declare_file(rmeta_name)
200+
rustc_rmeta_output = generate_output_diagnostics(ctx, rmeta)
201+
metadata_supports_pipelining = can_use_metadata_for_pipelining(toolchain, "rlib")
193202

194203
providers = rustc_compile_action(
195204
ctx = ctx,
@@ -205,6 +214,8 @@ def _compile_rust(
205214
aliases = {},
206215
output = lib,
207216
metadata = rmeta,
217+
metadata_supports_pipelining = metadata_supports_pipelining,
218+
rustc_rmeta_output = rustc_rmeta_output,
208219
edition = edition,
209220
is_test = False,
210221
rustc_env = {},

extensions/protobuf/proto.bzl

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,16 @@ load("@rules_proto//proto:defs.bzl", "ProtoInfo")
2020
load("@rules_rust//rust/private:rustc.bzl", "rustc_compile_action")
2121

2222
# buildifier: disable=bzl-visibility
23-
load("@rules_rust//rust/private:utils.bzl", "can_build_metadata", "compute_crate_name", "determine_output_hash", "find_toolchain", "transform_deps")
23+
load(
24+
"@rules_rust//rust/private:utils.bzl",
25+
"can_build_metadata",
26+
"can_use_metadata_for_pipelining",
27+
"compute_crate_name",
28+
"determine_output_hash",
29+
"find_toolchain",
30+
"generate_output_diagnostics",
31+
"transform_deps",
32+
)
2433
load(
2534
"//:toolchain.bzl",
2635
_generate_proto = "rust_generate_proto",
@@ -194,12 +203,16 @@ def _rust_proto_compile(protos, descriptor_sets, imports, crate_name, ctx, is_gr
194203
output_hash,
195204
))
196205
rust_metadata = None
206+
rustc_rmeta_output = None
207+
metadata_supports_pipelining = False
197208
if can_build_metadata(toolchain, ctx, "rlib"):
198209
rust_metadata = ctx.actions.declare_file("%s/lib%s-%s.rmeta" % (
199210
output_dir,
200211
crate_name,
201212
output_hash,
202213
))
214+
rustc_rmeta_output = generate_output_diagnostics(ctx, rust_metadata)
215+
metadata_supports_pipelining = can_use_metadata_for_pipelining(toolchain, "rlib")
203216

204217
# Gather all dependencies for compilation
205218
compile_action_deps = depset(
@@ -223,6 +236,8 @@ def _rust_proto_compile(protos, descriptor_sets, imports, crate_name, ctx, is_gr
223236
aliases = {},
224237
output = rust_lib,
225238
metadata = rust_metadata,
239+
metadata_supports_pipelining = metadata_supports_pipelining,
240+
rustc_rmeta_output = rustc_rmeta_output,
226241
edition = proto_toolchain.edition,
227242
rustc_env = {},
228243
is_test = False,
@@ -311,6 +326,9 @@ rust_proto_library = rule(
311326
file of arguments to rustc: `@$(location //package:target)`.
312327
""",
313328
),
329+
"_always_enable_metadata_output_groups": attr.label(
330+
default = Label("//rust/settings:always_enable_metadata_output_groups"),
331+
),
314332
"_optional_output_wrapper": attr.label(
315333
executable = True,
316334
cfg = "exec",

rust/private/common.bzl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,8 @@ def _create_crate_info(**kwargs):
5151
kwargs.update({"wrapped_crate_type": None})
5252
if not "metadata" in kwargs:
5353
kwargs.update({"metadata": None})
54+
if not "metadata_supports_pipelining" in kwargs:
55+
kwargs.update({"metadata_supports_pipelining": False})
5456
if not "rustc_rmeta_output" in kwargs:
5557
kwargs.update({"rustc_rmeta_output": None})
5658
if not "rustc_output" in kwargs:

rust/private/providers.bzl

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ CrateInfo = provider(
2525
"edition": "str: The edition of this crate.",
2626
"is_test": "bool: If the crate is being compiled in a test context",
2727
"metadata": "File: The output from rustc from producing the output file. It is optional.",
28+
"metadata_supports_pipelining": "bool: If the metadata in 'metadata' (if present) is " +
29+
"usable for pipelined compilation.",
2830
"name": "str: The name of this crate.",
2931
"output": "File: The output File that will be produced, depends on crate type.",
3032
"owner": "Label: The label of the target that produced this CrateInfo",
@@ -98,6 +100,17 @@ DepVariantInfo = provider(
98100
},
99101
)
100102

103+
AlwaysEnableMetadataOutputGroupsInfo = provider(
104+
doc = (
105+
"Enable the 'metadata' and 'rustc_rmeta_output' groups for all targets, " +
106+
"even if not a library or if pipelining is disabled"
107+
),
108+
fields = {
109+
"always_enable_metadata_output_groups": ("bool: Whether or not to always enable " +
110+
"metadata-related output groups"),
111+
},
112+
)
113+
101114
RustcOutputDiagnosticsInfo = provider(
102115
doc = (
103116
"Save json diagnostics from rustc. Json diagnostics are able to be " +

rust/private/rust.bzl

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ load("//rust/private:rustc.bzl", "rustc_compile_action")
2828
load(
2929
"//rust/private:utils.bzl",
3030
"can_build_metadata",
31+
"can_use_metadata_for_pipelining",
3132
"compute_crate_name",
3233
"crate_root_src",
3334
"dedent",
@@ -177,12 +178,22 @@ def _rust_library_common(ctx, crate_type):
177178
rust_lib = ctx.actions.declare_file(rust_lib_name)
178179
rust_metadata = None
179180
rustc_rmeta_output = None
180-
if can_build_metadata(toolchain, ctx, crate_type) and not ctx.attr.disable_pipelining:
181+
metadata_supports_pipelining = False
182+
if can_build_metadata(
183+
toolchain,
184+
ctx,
185+
crate_type,
186+
disable_pipelining = getattr(ctx.attr, "disable_pipelining", False),
187+
):
181188
rust_metadata = ctx.actions.declare_file(
182189
paths.replace_extension(rust_lib_name, ".rmeta"),
183190
sibling = rust_lib,
184191
)
185192
rustc_rmeta_output = generate_output_diagnostics(ctx, rust_metadata)
193+
metadata_supports_pipelining = (
194+
can_use_metadata_for_pipelining(toolchain, crate_type) and
195+
not ctx.attr.disable_pipelining
196+
)
186197

187198
deps = transform_deps(ctx.attr.deps)
188199
proc_macro_deps = transform_deps(ctx.attr.proc_macro_deps + get_import_macro_deps(ctx))
@@ -203,6 +214,7 @@ def _rust_library_common(ctx, crate_type):
203214
output = rust_lib,
204215
rustc_output = generate_output_diagnostics(ctx, rust_lib),
205216
metadata = rust_metadata,
217+
metadata_supports_pipelining = metadata_supports_pipelining,
206218
rustc_rmeta_output = rustc_rmeta_output,
207219
edition = get_edition(ctx.attr, toolchain, ctx.label),
208220
rustc_env = ctx.attr.rustc_env,
@@ -242,6 +254,15 @@ def _rust_binary_impl(ctx):
242254
crate_root = crate_root_src(ctx.attr.name, ctx.attr.crate_name, ctx.files.srcs, ctx.attr.crate_type)
243255
srcs, compile_data, crate_root = transform_sources(ctx, ctx.files.srcs, ctx.files.compile_data, crate_root)
244256

257+
rust_metadata = None
258+
rustc_rmeta_output = None
259+
if can_build_metadata(toolchain, ctx, ctx.attr.crate_type):
260+
rust_metadata = ctx.actions.declare_file(
261+
paths.replace_extension("lib" + crate_name, ".rmeta"),
262+
sibling = output,
263+
)
264+
rustc_rmeta_output = generate_output_diagnostics(ctx, rust_metadata)
265+
245266
providers = rustc_compile_action(
246267
ctx = ctx,
247268
attr = ctx.attr,
@@ -256,6 +277,8 @@ def _rust_binary_impl(ctx):
256277
aliases = ctx.attr.aliases,
257278
output = output,
258279
rustc_output = generate_output_diagnostics(ctx, output),
280+
metadata = rust_metadata,
281+
rustc_rmeta_output = rustc_rmeta_output,
259282
edition = get_edition(ctx.attr, toolchain, ctx.label),
260283
rustc_env = ctx.attr.rustc_env,
261284
rustc_env_files = ctx.files.rustc_env_files,
@@ -337,6 +360,15 @@ def _rust_test_impl(ctx):
337360
),
338361
)
339362

363+
rust_metadata = None
364+
rustc_rmeta_output = None
365+
if can_build_metadata(toolchain, ctx, crate_type):
366+
rust_metadata = ctx.actions.declare_file(
367+
paths.replace_extension("lib" + crate_name, ".rmeta"),
368+
sibling = output,
369+
)
370+
rustc_rmeta_output = generate_output_diagnostics(ctx, rust_metadata)
371+
340372
# Need to consider all src files together when transforming
341373
srcs = depset(ctx.files.srcs, transitive = [crate.srcs]).to_list()
342374
compile_data = depset(ctx.files.compile_data, transitive = [crate.compile_data]).to_list()
@@ -371,6 +403,8 @@ def _rust_test_impl(ctx):
371403
aliases = aliases,
372404
output = output,
373405
rustc_output = generate_output_diagnostics(ctx, output),
406+
metadata = rust_metadata,
407+
rustc_rmeta_output = rustc_rmeta_output,
374408
edition = crate.edition,
375409
rustc_env = rustc_env,
376410
rustc_env_files = rustc_env_files,
@@ -381,6 +415,8 @@ def _rust_test_impl(ctx):
381415
owner = ctx.label,
382416
)
383417
else:
418+
crate_name = compute_crate_name(ctx.workspace_name, ctx.label, toolchain, ctx.attr.crate_name)
419+
384420
crate_root = getattr(ctx.file, "crate_root", None)
385421

386422
if not crate_root:
@@ -402,6 +438,15 @@ def _rust_test_impl(ctx):
402438
),
403439
)
404440

441+
rust_metadata = None
442+
rustc_rmeta_output = None
443+
if can_build_metadata(toolchain, ctx, crate_type):
444+
rust_metadata = ctx.actions.declare_file(
445+
paths.replace_extension("lib" + crate_name, ".rmeta"),
446+
sibling = output,
447+
)
448+
rustc_rmeta_output = generate_output_diagnostics(ctx, rust_metadata)
449+
405450
data_paths = depset(direct = getattr(ctx.attr, "data", [])).to_list()
406451
rustc_env = expand_dict_value_locations(
407452
ctx,
@@ -412,7 +457,7 @@ def _rust_test_impl(ctx):
412457

413458
# Target is a standalone crate. Build the test binary as its own crate.
414459
crate_info_dict = dict(
415-
name = compute_crate_name(ctx.workspace_name, ctx.label, toolchain, ctx.attr.crate_name),
460+
name = crate_name,
416461
type = crate_type,
417462
root = crate_root,
418463
srcs = depset(srcs),
@@ -421,6 +466,8 @@ def _rust_test_impl(ctx):
421466
aliases = ctx.attr.aliases,
422467
output = output,
423468
rustc_output = generate_output_diagnostics(ctx, output),
469+
metadata = rust_metadata,
470+
rustc_rmeta_output = rustc_rmeta_output,
424471
edition = get_edition(ctx.attr, toolchain, ctx.label),
425472
rustc_env = rustc_env,
426473
rustc_env_files = ctx.files.rustc_env_files,
@@ -534,6 +581,9 @@ def _stamp_attribute(default_value):
534581

535582
# Internal attributes core to Rustc actions.
536583
RUSTC_ATTRS = {
584+
"_always_enable_metadata_output_groups": attr.label(
585+
default = Label("//rust/settings:always_enable_metadata_output_groups"),
586+
),
537587
"_error_format": attr.label(
538588
default = Label("//rust/settings:error_format"),
539589
),

rust/private/rustc.bzl

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,15 @@ load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
2727
load(":common.bzl", "rust_common")
2828
load(":compat.bzl", "abs")
2929
load(":lto.bzl", "construct_lto_arguments")
30-
load(":providers.bzl", "AllocatorLibrariesImplInfo", "AllocatorLibrariesInfo", "LintsInfo", "RustcOutputDiagnosticsInfo", _BuildInfo = "BuildInfo")
30+
load(
31+
":providers.bzl",
32+
"AllocatorLibrariesImplInfo",
33+
"AllocatorLibrariesInfo",
34+
"AlwaysEnableMetadataOutputGroupsInfo",
35+
"LintsInfo",
36+
"RustcOutputDiagnosticsInfo",
37+
_BuildInfo = "BuildInfo",
38+
)
3139
load(":rustc_resource_set.bzl", "get_rustc_resource_set", "is_codegen_units_enabled")
3240
load(":stamp.bzl", "is_stamping_enabled")
3341
load(
@@ -296,7 +304,7 @@ def collect_deps(
296304
# If it doesn't (for example a custom library that exports crate_info),
297305
# we depend on crate_info.output.
298306
depend_on = crate_info.metadata
299-
if not crate_info.metadata:
307+
if not crate_info.metadata or not crate_info.metadata_supports_pipelining:
300308
depend_on = crate_info.output
301309

302310
# If this dependency is a proc_macro, it still can be used for lib crates
@@ -1986,7 +1994,7 @@ def _crate_to_link_flag_metadata(crate):
19861994
crate_info = crate
19871995

19881996
lib_or_meta = crate_info.metadata
1989-
if not crate_info.metadata:
1997+
if not crate_info.metadata or not crate_info.metadata_supports_pipelining:
19901998
lib_or_meta = crate_info.output
19911999
return ["--extern={}={}".format(name, lib_or_meta.path)]
19922000

@@ -2301,6 +2309,30 @@ def get_error_format(attr, attr_name):
23012309
return getattr(attr, attr_name)[ErrorFormatInfo].error_format
23022310
return "human"
23032311

2312+
def _always_enable_metadata_output_groups_impl(ctx):
2313+
"""Implementation of the `always_enable_metadata_output_groups` rule
2314+
2315+
Args:
2316+
ctx (ctx): The rule's context object
2317+
2318+
Returns:
2319+
list: A list containing the AlwaysEnableMetadataOutputGroupsInfo provider
2320+
"""
2321+
return [AlwaysEnableMetadataOutputGroupsInfo(
2322+
always_enable_metadata_output_groups = ctx.build_setting_value,
2323+
)]
2324+
2325+
always_enable_metadata_output_groups = rule(
2326+
doc = (
2327+
"Setting this flag from the command line with `--@rules_rust//rust/settings:always_enable_metadata_output_groups` " +
2328+
"will cause all rules to generate the `metadata` and `rustc_rmeta_output` output groups, " +
2329+
"rather than the default behavior of only generated them for libraries when pipelined " +
2330+
"compilation is enabled."
2331+
),
2332+
implementation = _always_enable_metadata_output_groups_impl,
2333+
build_setting = config.bool(flag = True),
2334+
)
2335+
23042336
def _rustc_output_diagnostics_impl(ctx):
23052337
"""Implementation of the `rustc_output_diagnostics` rule
23062338
@@ -2318,8 +2350,8 @@ rustc_output_diagnostics = rule(
23182350
doc = (
23192351
"Setting this flag from the command line with `--@rules_rust//rust/settings:rustc_output_diagnostics` " +
23202352
"makes rules_rust save rustc json output(suitable for consumption by rust-analyzer) in a file. " +
2321-
"These are accessible via the " +
2322-
"`rustc_rmeta_output`(for pipelined compilation) and `rustc_output` output groups. " +
2353+
"These are accessible via the `rustc_rmeta_output` (for pipelined compilation or if " +
2354+
"`always_enable_metadata_output_groups` is enabled) and `rustc_output` output groups. " +
23232355
"You can find these using `bazel cquery`"
23242356
),
23252357
implementation = _rustc_output_diagnostics_impl,

0 commit comments

Comments
 (0)