Skip to content

Commit

Permalink
Added rust_unpretty_aspect and rust_unpretty rules (#2356)
Browse files Browse the repository at this point in the history
Proposal for #1642
Duplicates #1643 (special
thanks to @freeformstu)

### Summary

Rustc can be used to expand all macros so that you can inspect the
generated source files easier.

This feature is enabled via `-Zunpretty={mode}`. The `-Z` flag is only
available in the nightly
version of `rustc` (rust-lang/rust#43364).


### Unprettying

Build and test your targets normally.

```
bazel build //:ok_binary   
INFO: Analyzed target //:ok_binary (0 packages loaded, 0 targets configured).
INFO: Found 1 target...
Target //:ok_binary up-to-date:
  bazel-bin/ok_binary
INFO: Elapsed time: 0.081s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
```

Use the aspect to generate the expanded files in as a one-off build.

(`.bazelrc`)
```
# Enable unpretty for all targets in the workspace
build:unpretty --aspects=@rules_rust//rust:defs.bzl%rust_unpretty_aspect
build:unpretty --output_groups=+rust_unpretty

# `unpretty` requires the nightly toolchain. See tracking issue:
# rust-lang/rust#43364
build:unpretty --@rules_rust//rust/toolchain/channel=nightly
```

```
bazel build --config=unpretty //:ok_binary
INFO: Analyzed target //:ok_binary (1 packages loaded, 2 targets configured).
INFO: Found 1 target...
Aspect @rules_rust//rust/private:unpretty.bzl%rust_unpretty_aspect of //:ok_binary up-to-date:
  bazel-bin/ok_binary.expand.rs
INFO: Elapsed time: 0.149s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
```

Targeting tests is valid as well.

```
bazel build --config=unpretty //:ok_test  
INFO: Analyzed target //:ok_test (0 packages loaded, 2 targets configured).
INFO: Found 1 target...
Aspect @rules_rust//rust/private:unpretty.bzl%rust_expand_aspect of //:ok_test up-to-date:
  bazel-bin/test-397521499/ok_test.expand.rs
INFO: Elapsed time: 0.113s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
```

Finally, manually wire up a `rust_unpretty` target explicitly if you
want a target to build. This rule is unique compared to the aspect in
that it forces a transition to a nightly toolchain so that `-Zunpretty`
can be used.

```starlark
load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_unpretty")

rust_binary(
    name = "ok_binary",
    srcs = ["src/main.rs"],
    edition = "2021",
)

rust_unpretty(
    name = "ok_binary_expand",
    deps = [":ok_binary"],
)
```

```
bazel build //:ok_binary_expand
INFO: Analyzed target //:ok_binary_expand (0 packages loaded, 1 target configured).
INFO: Found 1 target...
Target //:ok_binary_expand up-to-date:
  bazel-bin/ok_binary.expand.rs
INFO: Elapsed time: 0.090s, Critical Path: 0.00s
INFO: 1 process: 1 internal.
INFO: Build completed successfully, 1 total action
```
  • Loading branch information
UebelAndre committed Dec 27, 2023
1 parent 6a93592 commit 828c807
Show file tree
Hide file tree
Showing 12 changed files with 565 additions and 50 deletions.
8 changes: 8 additions & 0 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ single_rust_channel_targets: &single_rust_channel_targets
- "//..."
# These tests are expected to fail as they require both a nightly and stable toolchain.
- "-//test/unit/channel_transitions/..."
- "-//test/unpretty/..."
default_linux_targets: &default_linux_targets
- "--"
- "//..."
Expand Down Expand Up @@ -169,6 +170,13 @@ tasks:
test_targets: *default_windows_targets
soft_fail: yes
bazel: "rolling"
ubuntu2004_unpretty:
name: Unpretty
platform: ubuntu2004
build_targets: *default_linux_targets
test_targets: *default_linux_targets
build_flags:
- "--config=unpretty"
ubuntu2004_bzlmod_only:
name: With bzlmod
platform: ubuntu2004
Expand Down
8 changes: 8 additions & 0 deletions .bazelrc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ build:rustfmt --output_groups=+rustfmt_checks
build:clippy --aspects=//rust:defs.bzl%rust_clippy_aspect
build:clippy --output_groups=+clippy_checks

# Enable unpretty for all targets in the workspace
build:unpretty --aspects=//rust:defs.bzl%rust_unpretty_aspect
build:unpretty --output_groups=+rust_unpretty

# `unpretty` requires the nightly toolchain. See tracking issue:
# https://github.com/rust-lang/rust/issues/43364
build:unpretty --//rust/toolchain/channel=nightly

###############################################################################
## Incompatibility flags
###############################################################################
Expand Down
11 changes: 11 additions & 0 deletions rust/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ load(
_rustfmt_aspect = "rustfmt_aspect",
_rustfmt_test = "rustfmt_test",
)
load(
"//rust/private:unpretty.bzl",
_rust_unpretty = "rust_unpretty",
_rust_unpretty_aspect = "rust_unpretty_aspect",
)

rust_library = _rust_library
# See @rules_rust//rust/private:rust.bzl for a complete description.
Expand Down Expand Up @@ -111,6 +116,12 @@ capture_clippy_output = _capture_clippy_output
rustc_output_diagnostics = _rustc_output_diagnostics
# See @rules_rust//rust/private:rustc.bzl for a complete description.

rust_unpretty_aspect = _rust_unpretty_aspect
# See @rules_rust//rust/private:unpretty.bzl for a complete description.

rust_unpretty = _rust_unpretty
# See @rules_rust//rust/private:unpretty.bzl for a complete description.

error_format = _error_format
# See @rules_rust//rust/private:rustc.bzl for a complete description.

Expand Down
120 changes: 71 additions & 49 deletions rust/private/rust.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,22 @@ def _rust_binary_impl(ctx):

return providers

def get_rust_test_flags(attr):
"""Determine the desired rustc flags for test targets.
Args:
attr (dict): Attributes of a rule
Returns:
List: A list of test flags
"""
if getattr(attr, "use_libtest_harness", True):
rust_flags = ["--test"]
else:
rust_flags = ["--cfg", "test"]

return rust_flags

def _rust_test_impl(ctx):
"""The implementation of the `rust_test` rule.
Expand Down Expand Up @@ -394,7 +410,7 @@ def _rust_test_impl(ctx):
attr = ctx.attr,
toolchain = toolchain,
crate_info_dict = crate_info_dict,
rust_flags = ["--test"] if ctx.attr.use_libtest_harness else ["--cfg", "test"],
rust_flags = get_rust_test_flags(ctx.attr),
skip_expanding_rustc_env = True,
)
data = getattr(ctx.attr, "data", [])
Expand Down Expand Up @@ -487,6 +503,56 @@ def _stamp_attribute(default_value):
values = [1, 0, -1],
)

# Internal attributes core to Rustc actions.
RUSTC_ATTRS = {
"_cc_toolchain": attr.label(
doc = (
"In order to use find_cc_toolchain, your rule has to depend " +
"on C++ toolchain. See `@rules_cc//cc:find_cc_toolchain.bzl` " +
"docs for details."
),
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
),
"_error_format": attr.label(
default = Label("//:error_format"),
),
"_extra_exec_rustc_flag": attr.label(
default = Label("//:extra_exec_rustc_flag"),
),
"_extra_exec_rustc_flags": attr.label(
default = Label("//:extra_exec_rustc_flags"),
),
"_extra_rustc_flag": attr.label(
default = Label("//:extra_rustc_flag"),
),
"_extra_rustc_flags": attr.label(
default = Label("//:extra_rustc_flags"),
),
"_import_macro_dep": attr.label(
default = Label("//util/import"),
cfg = "exec",
),
"_is_proc_macro_dep": attr.label(
default = Label("//rust/private:is_proc_macro_dep"),
),
"_is_proc_macro_dep_enabled": attr.label(
default = Label("//rust/private:is_proc_macro_dep_enabled"),
),
"_per_crate_rustc_flag": attr.label(
default = Label("//:experimental_per_crate_rustc_flag"),
),
"_process_wrapper": attr.label(
doc = "A process wrapper for running rustc on all platforms.",
default = Label("//util/process_wrapper"),
executable = True,
allow_single_file = True,
cfg = "exec",
),
"_rustc_output_diagnostics": attr.label(
default = Label("//:rustc_output_diagnostics"),
),
}

_common_attrs = {
"aliases": attr.label_keyed_string_dict(
doc = dedent("""\
Expand Down Expand Up @@ -618,62 +684,18 @@ _common_attrs = {
"""),
allow_files = [".rs"],
),
"stamp": _stamp_attribute(default_value = 0),
"stamp": _stamp_attribute(
default_value = 0,
),
"version": attr.string(
doc = "A version to inject in the cargo environment variable.",
default = "0.0.0",
),
"_cc_toolchain": attr.label(
doc = (
"In order to use find_cc_toolchain, your rule has to depend " +
"on C++ toolchain. See `@rules_cc//cc:find_cc_toolchain.bzl` " +
"docs for details."
),
default = Label("@bazel_tools//tools/cpp:current_cc_toolchain"),
),
"_error_format": attr.label(
default = Label("//:error_format"),
),
"_extra_exec_rustc_flag": attr.label(
default = Label("//:extra_exec_rustc_flag"),
),
"_extra_exec_rustc_flags": attr.label(
default = Label("//:extra_exec_rustc_flags"),
),
"_extra_rustc_flag": attr.label(
default = Label("//:extra_rustc_flag"),
),
"_extra_rustc_flags": attr.label(
default = Label("//:extra_rustc_flags"),
),
"_import_macro_dep": attr.label(
default = Label("//util/import"),
cfg = "exec",
),
"_is_proc_macro_dep": attr.label(
default = Label("//rust/private:is_proc_macro_dep"),
),
"_is_proc_macro_dep_enabled": attr.label(
default = Label("//rust/private:is_proc_macro_dep_enabled"),
),
"_per_crate_rustc_flag": attr.label(
default = Label("//:experimental_per_crate_rustc_flag"),
),
"_process_wrapper": attr.label(
doc = "A process wrapper for running rustc on all platforms.",
default = Label("//util/process_wrapper"),
executable = True,
allow_single_file = True,
cfg = "exec",
),
"_rustc_output_diagnostics": attr.label(
default = Label("//:rustc_output_diagnostics"),
),
"_stamp_flag": attr.label(
doc = "A setting used to determine whether or not the `--stamp` flag is enabled",
default = Label("//rust/private:stamp"),
),
}
} | RUSTC_ATTRS

_coverage_attrs = {
"_collect_cc_coverage": attr.label(
Expand Down
Loading

0 comments on commit 828c807

Please sign in to comment.