Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support -Cpanic=abort #1899

Open
wants to merge 22 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .bazelci/presubmit.yml
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,15 @@ tasks:
- "//..."
build_flags:
- "--@rules_rust//rust/settings:experimental_use_cc_common_link=True"
ubuntu2004_panic_abort:
name: -Cabort=panic
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
name: -Cabort=panic
name: -Cpanic=abort

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

platform: ubuntu2004
build_targets: *default_linux_targets
test_targets: *default_linux_targets
build_flags:
- "--@rules_rust//:panic_style=abort"
test_flags:
- "--@rules_rust//:panic_style=abort"
android_examples_ubuntu2004:
name: Android Examples
platform: ubuntu2004
Expand Down
9 changes: 8 additions & 1 deletion BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
load("@bazel_skylib//:bzl_library.bzl", "bzl_library")
load("//rust:defs.bzl", "capture_clippy_output", "clippy_flags", "error_format", "extra_exec_rustc_flag", "extra_exec_rustc_flags", "extra_rustc_flag", "extra_rustc_flags", "is_proc_macro_dep", "is_proc_macro_dep_enabled", "per_crate_rustc_flag")
load("//rust:defs.bzl", "capture_clippy_output", "clippy_flags", "error_format", "extra_exec_rustc_flag", "extra_exec_rustc_flags", "extra_rustc_flag", "extra_rustc_flags", "is_proc_macro_dep", "is_proc_macro_dep_enabled", "panic_style", "per_crate_rustc_flag")

exports_files(["LICENSE"])

Expand All @@ -18,6 +18,13 @@ error_format(
visibility = ["//visibility:public"],
)

# This setting may be changed from the command line to panic immediately upon abort.
panic_style(
name = "panic_style",
build_setting_default = "",
visibility = ["//visibility:public"],
)

# This setting may be used to pass extra options to clippy from the command line.
# It applies across all targets.
clippy_flags(
Expand Down
1 change: 1 addition & 0 deletions docs/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ PAGES = dict([
"rust_test",
"rust_test_suite",
"error_format",
"panic_style",
"extra_rustc_flag",
"extra_rustc_flags",
"capture_clippy_output",
Expand Down
19 changes: 19 additions & 0 deletions docs/defs.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* [rust_test](#rust_test)
* [rust_test_suite](#rust_test_suite)
* [error_format](#error_format)
* [panic_style](#panic_style)
* [extra_rustc_flag](#extra_rustc_flag)
* [extra_rustc_flags](#extra_rustc_flags)
* [capture_clippy_output](#capture_clippy_output)
Expand Down Expand Up @@ -85,6 +86,24 @@ Add additional rustc_flags from the command line with `--@rules_rust//:extra_rus
| <a id="extra_rustc_flags-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |


<a id="panic_style"></a>

## panic_style

<pre>
panic_style(<a href="#panic_style-name">name</a>)
</pre>

Change the [-Cpanic](https://doc.rust-lang.org/rustc/codegen-options/index.html#panic) flag from the command line with `--@rules_rust//:panic_style`. See rustc documentation for valid values. Automatically set to `unwind` for proc macros and tests, or the per-target default.

**ATTRIBUTES**


| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="panic_style-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |


<a id="rust_binary"></a>

## rust_binary
Expand Down
19 changes: 19 additions & 0 deletions docs/flatten.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* [extra_rustc_flags](#extra_rustc_flags)
* [fail_when_enabled](#fail_when_enabled)
* [incompatible_flag](#incompatible_flag)
* [panic_style](#panic_style)
* [rules_rust_dependencies](#rules_rust_dependencies)
* [rust_analyzer_aspect](#rust_analyzer_aspect)
* [rust_analyzer_toolchain](#rust_analyzer_toolchain)
Expand Down Expand Up @@ -199,6 +200,24 @@ A rule defining an incompatible flag.
| <a id="incompatible_flag-issue"></a>issue | The link to the github issue associated with this flag | String | required | |


<a id="panic_style"></a>

## panic_style

<pre>
panic_style(<a href="#panic_style-name">name</a>)
</pre>

Change the [-Cpanic](https://doc.rust-lang.org/rustc/codegen-options/index.html#panic) flag from the command line with `--@rules_rust//:panic_style`. See rustc documentation for valid values. Automatically set to `unwind` for proc macros and tests, or the per-target default.

**ATTRIBUTES**


| Name | Description | Type | Mandatory | Default |
| :------------- | :------------- | :------------- | :------------- | :------------- |
| <a id="panic_style-name"></a>name | A unique name for this target. | <a href="https://bazel.build/concepts/labels#target-names">Name</a> | required | |


<a id="rust_analyzer_toolchain"></a>

## rust_analyzer_toolchain
Expand Down
2 changes: 2 additions & 0 deletions docs/symbols.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ load(
_error_format = "error_format",
_extra_rustc_flag = "extra_rustc_flag",
_extra_rustc_flags = "extra_rustc_flags",
_panic_style = "panic_style",
_rust_analyzer_aspect = "rust_analyzer_aspect",
_rust_binary = "rust_binary",
_rust_clippy = "rust_clippy",
Expand Down Expand Up @@ -175,6 +176,7 @@ rustfmt_test = _rustfmt_test
rustfmt_toolchain = _rustfmt_toolchain

error_format = _error_format
panic_style = _panic_style
extra_rustc_flag = _extra_rustc_flag
extra_rustc_flags = _extra_rustc_flags
incompatible_flag = _incompatible_flag
Expand Down
4 changes: 4 additions & 0 deletions rust/defs.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ load(
_extra_rustc_flags = "extra_rustc_flags",
_is_proc_macro_dep = "is_proc_macro_dep",
_is_proc_macro_dep_enabled = "is_proc_macro_dep_enabled",
_panic_style = "panic_style",
_per_crate_rustc_flag = "per_crate_rustc_flag",
)
load(
Expand Down Expand Up @@ -107,6 +108,9 @@ capture_clippy_output = _capture_clippy_output
error_format = _error_format
# See @rules_rust//rust/private:rustc.bzl for a complete description.

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

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

Expand Down
12 changes: 11 additions & 1 deletion rust/private/rust.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ load(
"determine_output_hash",
"expand_dict_value_locations",
"find_toolchain",
"force_panic_unwind_transition",
"get_import_macro_deps",
"transform_deps",
)
Expand Down Expand Up @@ -682,6 +683,9 @@ _common_attrs = {
"_is_proc_macro_dep_enabled": attr.label(
default = Label("//:is_proc_macro_dep_enabled"),
),
"_panic_style": attr.label(
default = Label("//:panic_style"),
),
"_per_crate_rustc_flag": attr.label(
default = Label("//:experimental_per_crate_rustc_flag"),
),
Expand Down Expand Up @@ -910,6 +914,7 @@ _proc_macro_dep_transition = transition(
rust_proc_macro = rule(
implementation = _rust_proc_macro_impl,
provides = _common_providers,
cfg = force_panic_unwind_transition,
# Start by copying the common attributes, then override the `deps` attribute
# to apply `_proc_macro_dep_transition`. To add this transition we additionally
# need to declare `_allowlist_function_transition`, see
Expand Down Expand Up @@ -1132,7 +1137,11 @@ rust_test = rule(
implementation = _rust_test_impl,
provides = _common_providers,
attrs = dict(_common_attrs.items() +
_rust_test_attrs.items()),
_rust_test_attrs.items() + {
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
}.items()),
executable = True,
fragments = ["cpp"],
host_fragments = ["cpp"],
Expand All @@ -1141,6 +1150,7 @@ rust_test = rule(
str(Label("//rust:toolchain_type")),
"@bazel_tools//tools/cpp:toolchain_type",
],
cfg = force_panic_unwind_transition,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this not also be solved by having this flag appear in the rust_toolchain instead of for each test and proc-macro? Also, why is this not for binaries as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It needs to apply only to tests (the overall goal of this PR is build binaries without this transition). #[should_panic] doesn't work with -Cpanic=abort, so Cargo automatically builds tests with -Cpanic=unwind, which is the behavior I'm copying here.

https://doc.rust-lang.org/cargo/reference/profiles.html#panic documents this:

Tests, benchmarks, build scripts, and proc macros ignore the panic setting. The rustc test harness currently requires unwind behavior. See the panic-abort-tests unstable flag which enables abort behavior.

Additionally, when using the abort strategy and building a test, all of the dependencies will also be forced to build with the unwind strategy.

incompatible_use_toolchain_transition = True,
doc = dedent("""\
Builds a Rust test crate.
Expand Down
70 changes: 66 additions & 4 deletions rust/private/rustc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ ErrorFormatInfo = provider(
fields = {"error_format": "(string) [" + ", ".join(_error_format_values) + "]"},
)

_panic_style_values = ["unwind", "abort", ""]

PanicStyleInfo = provider(
doc = "Set the panic style",
fields = {"panic_style": "(string) [" + ", ".join(_panic_style_values) + "]"},
)

ExtraRustcFlagsInfo = provider(
doc = "Pass each value as an additional flag to non-exec rustc invocations",
fields = {"extra_rustc_flags": "List[string] Extra flags to pass to rustc in non-exec configuration"},
Expand Down Expand Up @@ -611,7 +618,7 @@ def collect_inputs(
force_depend_on_objects (bool, optional): Forces dependencies of this rule to be objects rather than
metadata, even for libraries. This is used in rustdoc tests.
experimental_use_cc_common_link (bool, optional): Whether rules_rust uses cc_common.link to link
rust binaries.
rust binaries.

Returns:
tuple: A tuple: A tuple of the following items:
Expand Down Expand Up @@ -884,6 +891,8 @@ def construct_arguments(

rustc_flags.add("--error-format=" + error_format)

rustc_flags.add("-Cpanic=" + _get_panic_style(ctx, toolchain))

# Mangle symbols to disambiguate crates with the same name. This could
# happen only for non-final artifacts where we compute an output_hash,
# e.g., rust_library.
Expand Down Expand Up @@ -1029,6 +1038,30 @@ def construct_arguments(

return args, env

def _get_panic_style(ctx, toolchain):
panic_style = "unwind"

# Most targets default to unwind, but a few default to abort. Can't find a list in the
# documentation, this list is extracted from `library/panic_unwind/src/lib.rs` as of 1.68.1.
target_triple = toolchain.target_triple
if target_triple.arch.startswith("wasm") or target_triple.arch == "avr" or target_triple.system in ("none", "uefi", "espidf"):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we move this logic over to toolchain.bzl, and use a toolchain.default_panic_style here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

panic_style = "abort"

if hasattr(ctx.attr, "_panic_style"):
flag_value = ctx.attr._panic_style[PanicStyleInfo].panic_style
if flag_value:
panic_style = flag_value
return panic_style

def _get_libstd_and_allocator_ccinfo(ctx, toolchain):
panic_style = _get_panic_style(ctx, toolchain)
if panic_style == "unwind":
return toolchain.unwind_libstd_and_allocator_ccinfo
elif panic_style == "abort":
return toolchain.abort_libstd_and_allocator_ccinfo
else:
fail("Unrecognized panic style: " + panic_style)

def rustc_compile_action(
ctx,
attr,
Expand Down Expand Up @@ -1267,7 +1300,7 @@ def rustc_compile_action(
)

# Collect the linking contexts of the standard library and dependencies.
linking_contexts = [toolchain.libstd_and_allocator_ccinfo.linking_context, toolchain.stdlib_linkflags.linking_context]
linking_contexts = [_get_libstd_and_allocator_ccinfo(ctx, toolchain).linking_context, toolchain.stdlib_linkflags.linking_context]

for dep in crate_info.deps.to_list():
if dep.cc_info:
Expand Down Expand Up @@ -1486,9 +1519,10 @@ def establish_cc_info(ctx, attr, crate_info, toolchain, cc_toolchain, feature_co
else:
cc_infos.append(dep.cc_info)

if crate_info.type in ("rlib", "lib") and toolchain.libstd_and_allocator_ccinfo:
libstd_and_allocator_ccinfo = _get_libstd_and_allocator_ccinfo(ctx, toolchain)
if crate_info.type in ("rlib", "lib") and libstd_and_allocator_ccinfo:
# TODO: if we already have an rlib in our deps, we could skip this
cc_infos.append(toolchain.libstd_and_allocator_ccinfo)
cc_infos.append(libstd_and_allocator_ccinfo)

return [cc_common.merge_cc_infos(cc_infos = cc_infos)]

Expand Down Expand Up @@ -1907,6 +1941,34 @@ error_format = rule(
build_setting = config.string(flag = True),
)

def _panic_style_impl(ctx):
"""Implementation of the `panic_style` rule

Args:
ctx (ctx): The rule's context object

Returns:
list: A list containing the PanicStyleInfo provider
"""
raw = ctx.build_setting_value
if raw not in _panic_style_values:
fail("{} expected a value in `{}` but got `{}`".format(
ctx.label,
_panic_style_values,
raw,
))
return [PanicStyleInfo(panic_style = raw)]

panic_style = rule(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We already have a string_flag build setting: https://bazel.build/extending/config#predefined-settings

Is there a reason why this is a custom rule instead of a string_flag?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I hadn't seen that, that is nicer. Done

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although that does mean it disappears from the docs.

doc = (
"Change the [-Cpanic](https://doc.rust-lang.org/rustc/codegen-options/index.html#panic) " +
"flag from the command line with `--@rules_rust//:panic_style`. See rustc documentation for valid values. " +
"Automatically set to `unwind` for proc macros and tests, or the per-target default."
),
implementation = _panic_style_impl,
build_setting = config.string(flag = True),
)

def _extra_rustc_flags_impl(ctx):
return ExtraRustcFlagsInfo(extra_rustc_flags = ctx.build_setting_value)

Expand Down
6 changes: 5 additions & 1 deletion rust/private/rustdoc_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
load("//rust/private:common.bzl", "rust_common")
load("//rust/private:providers.bzl", "CrateInfo")
load("//rust/private:rustdoc.bzl", "rustdoc_compile_action")
load("//rust/private:utils.bzl", "dedent", "find_toolchain", "transform_deps")
load("//rust/private:utils.bzl", "dedent", "find_toolchain", "force_panic_unwind_transition", "transform_deps")

def _construct_writer_arguments(ctx, test_runner, opt_test_params, action, crate_info):
"""Construct arguments and environment variables specific to `rustdoc_test_writer`.
Expand Down Expand Up @@ -207,6 +207,9 @@ rust_doc_test = rule(
"""),
providers = [CrateInfo, CcInfo],
),
"_allowlist_function_transition": attr.label(
default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
),
"_cc_toolchain": attr.label(
doc = (
"In order to use find_cc_toolchain, your rule has to depend " +
Expand All @@ -229,6 +232,7 @@ rust_doc_test = rule(
),
},
test = True,
cfg = force_panic_unwind_transition,
fragments = ["cpp"],
host_fragments = ["cpp"],
toolchains = [
Expand Down
9 changes: 9 additions & 0 deletions rust/private/utils.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -724,3 +724,12 @@ def _shortest_src_with_basename(srcs, basename):
if not shortest or len(f.dirname) < len(shortest.dirname):
shortest = f
return shortest

def _force_panic_unwind_transition_impl(_settings, _attr):
return {"//:panic_style": "unwind"}

force_panic_unwind_transition = transition(
implementation = _force_panic_unwind_transition_impl,
inputs = [],
outputs = ["//:panic_style"],
)
Loading