Skip to content

Commit

Permalink
feat: Strip debug info from opt builds (#2513)
Browse files Browse the repository at this point in the history
Attempts to follow the cargo proposal linked below to remove debug info
for release builds. Furthermore this should uphold the expected behavior
of bazel for cc builds which automatically strips debug symbols for
optimized builds.

rust-lang/cargo#4122 (comment)
  • Loading branch information
matte1 committed Apr 2, 2024
1 parent fe2bc68 commit bd1bd10
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 5 deletions.
3 changes: 2 additions & 1 deletion docs/flatten.md
Original file line number Diff line number Diff line change
Expand Up @@ -1180,7 +1180,7 @@ rust_toolchain(<a href="#rust_toolchain-name">name</a>, <a href="#rust_toolchain
<a href="#rust_toolchain-experimental_use_cc_common_link">experimental_use_cc_common_link</a>, <a href="#rust_toolchain-extra_exec_rustc_flags">extra_exec_rustc_flags</a>, <a href="#rust_toolchain-extra_rustc_flags">extra_rustc_flags</a>,
<a href="#rust_toolchain-extra_rustc_flags_for_crate_types">extra_rustc_flags_for_crate_types</a>, <a href="#rust_toolchain-global_allocator_library">global_allocator_library</a>, <a href="#rust_toolchain-llvm_cov">llvm_cov</a>, <a href="#rust_toolchain-llvm_profdata">llvm_profdata</a>,
<a href="#rust_toolchain-llvm_tools">llvm_tools</a>, <a href="#rust_toolchain-opt_level">opt_level</a>, <a href="#rust_toolchain-per_crate_rustc_flags">per_crate_rustc_flags</a>, <a href="#rust_toolchain-rust_doc">rust_doc</a>, <a href="#rust_toolchain-rust_std">rust_std</a>, <a href="#rust_toolchain-rustc">rustc</a>, <a href="#rust_toolchain-rustc_lib">rustc_lib</a>,
<a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>, <a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
<a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>, <a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-strip_level">strip_level</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
</pre>

Declares a Rust toolchain for use.
Expand Down Expand Up @@ -1260,6 +1260,7 @@ See `@rules_rust//rust:repositories.bzl` for examples of defining the `@rust_cpu
| <a id="rust_toolchain-rustfmt"></a>rustfmt | **Deprecated**: Instead see [rustfmt_toolchain](#rustfmt_toolchain) | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
| <a id="rust_toolchain-staticlib_ext"></a>staticlib_ext | The extension for static libraries created from rustc. | String | required | |
| <a id="rust_toolchain-stdlib_linkflags"></a>stdlib_linkflags | Additional linker flags to use when Rust standard library is linked by a C++ linker (rustc will deal with these automatically). Subject to location expansion with respect to the srcs of the <code>rust_std</code> attribute. | List of strings | required | |
| <a id="rust_toolchain-strip_level"></a>strip_level | Rustc strip levels. | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | <code>{"dbg": "none", "fastbuild": "none", "opt": "debuginfo"}</code> |
| <a id="rust_toolchain-target_json"></a>target_json | Override the target_triple with a custom target specification. For more details see: https://doc.rust-lang.org/rustc/targets/custom.html | String | optional | <code>""</code> |
| <a id="rust_toolchain-target_triple"></a>target_triple | The platform triple for the toolchains target environment. For more details see: https://docs.bazel.build/versions/master/skylark/rules.html#configurations | String | optional | <code>""</code> |

Expand Down
3 changes: 2 additions & 1 deletion docs/rust_repositories.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ rust_toolchain(<a href="#rust_toolchain-name">name</a>, <a href="#rust_toolchain
<a href="#rust_toolchain-experimental_use_cc_common_link">experimental_use_cc_common_link</a>, <a href="#rust_toolchain-extra_exec_rustc_flags">extra_exec_rustc_flags</a>, <a href="#rust_toolchain-extra_rustc_flags">extra_rustc_flags</a>,
<a href="#rust_toolchain-extra_rustc_flags_for_crate_types">extra_rustc_flags_for_crate_types</a>, <a href="#rust_toolchain-global_allocator_library">global_allocator_library</a>, <a href="#rust_toolchain-llvm_cov">llvm_cov</a>, <a href="#rust_toolchain-llvm_profdata">llvm_profdata</a>,
<a href="#rust_toolchain-llvm_tools">llvm_tools</a>, <a href="#rust_toolchain-opt_level">opt_level</a>, <a href="#rust_toolchain-per_crate_rustc_flags">per_crate_rustc_flags</a>, <a href="#rust_toolchain-rust_doc">rust_doc</a>, <a href="#rust_toolchain-rust_std">rust_std</a>, <a href="#rust_toolchain-rustc">rustc</a>, <a href="#rust_toolchain-rustc_lib">rustc_lib</a>,
<a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>, <a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
<a href="#rust_toolchain-rustfmt">rustfmt</a>, <a href="#rust_toolchain-staticlib_ext">staticlib_ext</a>, <a href="#rust_toolchain-stdlib_linkflags">stdlib_linkflags</a>, <a href="#rust_toolchain-strip_level">strip_level</a>, <a href="#rust_toolchain-target_json">target_json</a>, <a href="#rust_toolchain-target_triple">target_triple</a>)
</pre>

Declares a Rust toolchain for use.
Expand Down Expand Up @@ -121,6 +121,7 @@ See `@rules_rust//rust:repositories.bzl` for examples of defining the `@rust_cpu
| <a id="rust_toolchain-rustfmt"></a>rustfmt | **Deprecated**: Instead see [rustfmt_toolchain](#rustfmt_toolchain) | <a href="https://bazel.build/concepts/labels">Label</a> | optional | <code>None</code> |
| <a id="rust_toolchain-staticlib_ext"></a>staticlib_ext | The extension for static libraries created from rustc. | String | required | |
| <a id="rust_toolchain-stdlib_linkflags"></a>stdlib_linkflags | Additional linker flags to use when Rust standard library is linked by a C++ linker (rustc will deal with these automatically). Subject to location expansion with respect to the srcs of the <code>rust_std</code> attribute. | List of strings | required | |
| <a id="rust_toolchain-strip_level"></a>strip_level | Rustc strip levels. | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | <code>{"dbg": "none", "fastbuild": "none", "opt": "debuginfo"}</code> |
| <a id="rust_toolchain-target_json"></a>target_json | Override the target_triple with a custom target specification. For more details see: https://doc.rust-lang.org/rustc/targets/custom.html | String | optional | <code>""</code> |
| <a id="rust_toolchain-target_triple"></a>target_triple | The platform triple for the toolchains target environment. For more details see: https://docs.bazel.build/versions/master/skylark/rules.html#configurations | String | optional | <code>""</code> |

Expand Down
2 changes: 2 additions & 0 deletions rust/private/rustc.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -959,6 +959,8 @@ def construct_arguments(
compilation_mode = get_compilation_mode_opts(ctx, toolchain)
rustc_flags.add(compilation_mode.opt_level, format = "--codegen=opt-level=%s")
rustc_flags.add(compilation_mode.debug_info, format = "--codegen=debuginfo=%s")
if toolchain.target_os != "windows":
rustc_flags.add(compilation_mode.strip_level, format = "--codegen=strip=%s")

# For determinism to help with build distribution and such
if remap_path_prefix != None:
Expand Down
16 changes: 13 additions & 3 deletions rust/toolchain.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -490,11 +490,13 @@ def _rust_toolchain_impl(ctx):
list: A list containing the target's toolchain Provider info
"""
compilation_mode_opts = {}
for k, v in ctx.attr.opt_level.items():
for k, opt_level in ctx.attr.opt_level.items():
if not k in ctx.attr.debug_info:
fail("Compilation mode {} is not defined in debug_info but is defined opt_level".format(k))
compilation_mode_opts[k] = struct(debug_info = ctx.attr.debug_info[k], opt_level = v)
for k, v in ctx.attr.debug_info.items():
if not k in ctx.attr.strip_level:
fail("Compilation mode {} is not defined in strip_level but is defined opt_level".format(k))
compilation_mode_opts[k] = struct(debug_info = ctx.attr.debug_info[k], opt_level = opt_level, strip_level = ctx.attr.strip_level[k])
for k in ctx.attr.debug_info.keys():
if not k in ctx.attr.opt_level:
fail("Compilation mode {} is not defined in opt_level but is defined debug_info".format(k))

Expand Down Expand Up @@ -817,6 +819,14 @@ rust_toolchain = rule(
),
mandatory = True,
),
"strip_level": attr.string_dict(
doc = "Rustc strip levels.",
default = {
"dbg": "none",
"fastbuild": "none",
"opt": "debuginfo",
},
),
"target_json": attr.string(
doc = ("Override the target_triple with a custom target specification. " +
"For more details see: https://doc.rust-lang.org/rustc/targets/custom.html"),
Expand Down
5 changes: 5 additions & 0 deletions test/unit/strip_level/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
load(":strip_level_test_suite.bzl", "strip_level_test_suite")

strip_level_test_suite(
name = "strip_level_test_suite",
)
100 changes: 100 additions & 0 deletions test/unit/strip_level/strip_level_test_suite.bzl
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
"""Starlark tests for `rust_toolchain.strip_level`"""

load("@bazel_skylib//lib:unittest.bzl", "analysistest")
load("@bazel_skylib//rules:write_file.bzl", "write_file")
load("//rust:defs.bzl", "rust_binary")
load(
"//test/unit:common.bzl",
"assert_action_mnemonic",
"assert_argv_contains",
)

def _strip_level_test_impl(ctx, expected_level):
env = analysistest.begin(ctx)
target = analysistest.target_under_test(env)

action = target.actions[0]
assert_action_mnemonic(env, action, "Rustc")

assert_argv_contains(env, action, "--codegen=strip={}".format(expected_level))
return analysistest.end(env)

def _strip_level_for_dbg_test_impl(ctx):
return _strip_level_test_impl(ctx, "none")

_strip_level_for_dbg_test = analysistest.make(
_strip_level_for_dbg_test_impl,
config_settings = {
"//command_line_option:compilation_mode": "dbg",
},
)

def _strip_level_for_fastbuild_test_impl(ctx):
return _strip_level_test_impl(ctx, "none")

_strip_level_for_fastbuild_test = analysistest.make(
_strip_level_for_fastbuild_test_impl,
config_settings = {
"//command_line_option:compilation_mode": "fastbuild",
},
)

def _strip_level_for_opt_test_impl(ctx):
return _strip_level_test_impl(ctx, "debuginfo")

_strip_level_for_opt_test = analysistest.make(
_strip_level_for_opt_test_impl,
config_settings = {
"//command_line_option:compilation_mode": "opt",
},
)

def strip_level_test_suite(name):
"""Entry-point macro called from the BUILD file.
Args:
name (str): The name of the test suite.
"""
write_file(
name = "bin_main",
out = "main.rs",
content = [
"fn main() {}",
"",
],
)

rust_binary(
name = "bin",
srcs = [":main.rs"],
edition = "2021",
target_compatible_with = [
"@platforms//os:linux",
"@platforms//os:macos",
"@platforms//os:none",
],
)

_strip_level_for_dbg_test(
name = "strip_level_for_dbg_test",
target_under_test = ":bin",
)

_strip_level_for_fastbuild_test(
name = "strip_level_for_fastbuild_test",
target_under_test = ":bin",
)

_strip_level_for_opt_test(
name = "strip_level_for_opt_test",
target_under_test = ":bin",
)

native.test_suite(
name = name,
tests = [
":strip_level_for_dbg_test",
":strip_level_for_fastbuild_test",
":strip_level_for_opt_test",
],
)

0 comments on commit bd1bd10

Please sign in to comment.