Skip to content

Commit b078bbd

Browse files
authored
feat: Strip debug info from opt builds (#2513)
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)
1 parent f9626f9 commit b078bbd

File tree

7 files changed

+197
-28
lines changed

7 files changed

+197
-28
lines changed

docs/flatten.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1179,7 +1179,7 @@ rust_toolchain(<a href="#rust_toolchain-name">name</a>, <a href="#rust_toolchain
11791179
<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>,
11801180
<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>,
11811181
<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>,
1182-
<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>)
1182+
<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>)
11831183
</pre>
11841184

11851185
Declares a Rust toolchain for use.
@@ -1259,6 +1259,7 @@ See `@rules_rust//rust:repositories.bzl` for examples of defining the `@rust_cpu
12591259
| <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> |
12601260
| <a id="rust_toolchain-staticlib_ext"></a>staticlib_ext | The extension for static libraries created from rustc. | String | required | |
12611261
| <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 | |
1262+
| <a id="rust_toolchain-strip_level"></a>strip_level | Rustc strip levels. For all potential options, see https://doc.rust-lang.org/rustc/codegen-options/index.html#strip | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | <code>{"dbg": "none", "fastbuild": "none", "opt": "debuginfo"}</code> |
12621263
| <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> |
12631264
| <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> |
12641265

docs/rust_repositories.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ rust_toolchain(<a href="#rust_toolchain-name">name</a>, <a href="#rust_toolchain
4141
<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>,
4242
<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>,
4343
<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>,
44-
<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>)
44+
<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>)
4545
</pre>
4646

4747
Declares a Rust toolchain for use.
@@ -121,6 +121,7 @@ See `@rules_rust//rust:repositories.bzl` for examples of defining the `@rust_cpu
121121
| <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> |
122122
| <a id="rust_toolchain-staticlib_ext"></a>staticlib_ext | The extension for static libraries created from rustc. | String | required | |
123123
| <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 | |
124+
| <a id="rust_toolchain-strip_level"></a>strip_level | Rustc strip levels. For all potential options, see https://doc.rust-lang.org/rustc/codegen-options/index.html#strip | <a href="https://bazel.build/rules/lib/dict">Dictionary: String -> String</a> | optional | <code>{"dbg": "none", "fastbuild": "none", "opt": "debuginfo"}</code> |
124125
| <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> |
125126
| <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> |
126127

rust/private/rustc.bzl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -959,6 +959,7 @@ def construct_arguments(
959959
compilation_mode = get_compilation_mode_opts(ctx, toolchain)
960960
rustc_flags.add(compilation_mode.opt_level, format = "--codegen=opt-level=%s")
961961
rustc_flags.add(compilation_mode.debug_info, format = "--codegen=debuginfo=%s")
962+
rustc_flags.add(compilation_mode.strip_level, format = "--codegen=strip=%s")
962963

963964
# For determinism to help with build distribution and such
964965
if remap_path_prefix != None:
@@ -1288,12 +1289,15 @@ def rustc_compile_action(
12881289
if rustc_output:
12891290
action_outputs.append(rustc_output)
12901291

1292+
# Get the compilation mode for the current target.
1293+
compilation_mode = get_compilation_mode_opts(ctx, toolchain)
1294+
12911295
# Rustc generates a pdb file (on Windows) or a dsym folder (on macos) so provide it in an output group for crate
12921296
# types that benefit from having debug information in a separate file.
12931297
pdb_file = None
12941298
dsym_folder = None
12951299
if crate_info.type in ("cdylib", "bin"):
1296-
if toolchain.target_os == "windows":
1300+
if toolchain.target_os == "windows" and compilation_mode.strip_level == "none":
12971301
pdb_file = ctx.actions.declare_file(crate_info.output.basename[:-len(crate_info.output.extension)] + "pdb", sibling = crate_info.output)
12981302
action_outputs.append(pdb_file)
12991303
elif toolchain.target_os == "darwin":

rust/toolchain.bzl

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -490,11 +490,13 @@ def _rust_toolchain_impl(ctx):
490490
list: A list containing the target's toolchain Provider info
491491
"""
492492
compilation_mode_opts = {}
493-
for k, v in ctx.attr.opt_level.items():
493+
for k, opt_level in ctx.attr.opt_level.items():
494494
if not k in ctx.attr.debug_info:
495495
fail("Compilation mode {} is not defined in debug_info but is defined opt_level".format(k))
496-
compilation_mode_opts[k] = struct(debug_info = ctx.attr.debug_info[k], opt_level = v)
497-
for k, v in ctx.attr.debug_info.items():
496+
if not k in ctx.attr.strip_level:
497+
fail("Compilation mode {} is not defined in strip_level but is defined opt_level".format(k))
498+
compilation_mode_opts[k] = struct(debug_info = ctx.attr.debug_info[k], opt_level = opt_level, strip_level = ctx.attr.strip_level[k])
499+
for k in ctx.attr.debug_info.keys():
498500
if not k in ctx.attr.opt_level:
499501
fail("Compilation mode {} is not defined in opt_level but is defined debug_info".format(k))
500502

@@ -817,6 +819,17 @@ rust_toolchain = rule(
817819
),
818820
mandatory = True,
819821
),
822+
"strip_level": attr.string_dict(
823+
doc = (
824+
"Rustc strip levels. For all potential options, see " +
825+
"https://doc.rust-lang.org/rustc/codegen-options/index.html#strip"
826+
),
827+
default = {
828+
"dbg": "none",
829+
"fastbuild": "none",
830+
"opt": "debuginfo",
831+
},
832+
),
820833
"target_json": attr.string(
821834
doc = ("Override the target_triple with a custom target specification. " +
822835
"For more details see: https://doc.rust-lang.org/rustc/targets/custom.html"),

test/unit/debug_info/debug_info_analysis_test.bzl

Lines changed: 72 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,59 @@
33
load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts")
44
load("//rust:defs.bzl", "rust_binary", "rust_shared_library", "rust_test")
55

6-
def _pdb_file_test_impl(ctx):
6+
def _pdb_file_test_impl(ctx, expect_pdb_file):
77
env = analysistest.begin(ctx)
88
target = analysistest.target_under_test(env)
9-
109
files = target[DefaultInfo].files.to_list()
10+
11+
if not expect_pdb_file:
12+
asserts.equals(env, len(files), 0)
13+
return analysistest.end(env)
14+
1115
asserts.equals(env, len(files), 1)
1216
file = files[0]
1317
asserts.equals(env, file.extension, "pdb")
14-
1518
return analysistest.end(env)
1619

17-
pdb_file_test = analysistest.make(_pdb_file_test_impl)
20+
def _pdb_file_for_dbg_test_impl(ctx):
21+
"""Test for dbg compilation mode."""
22+
return _pdb_file_test_impl(ctx, True)
23+
24+
pdb_file_dbg_test = analysistest.make(
25+
_pdb_file_for_dbg_test_impl,
26+
config_settings = {
27+
"//command_line_option:compilation_mode": "dbg",
28+
},
29+
)
30+
31+
def _pdb_file_for_fastbuild_test_impl(ctx):
32+
"""Test for fastbuild compilation mode."""
33+
return _pdb_file_test_impl(ctx, True)
34+
35+
pdb_file_fastbuild_test = analysistest.make(
36+
_pdb_file_for_fastbuild_test_impl,
37+
config_settings = {
38+
"//command_line_option:compilation_mode": "fastbuild",
39+
},
40+
)
41+
42+
def _pdb_file_for_opt_test_impl(ctx):
43+
"""Test for opt compilation mode."""
44+
return _pdb_file_test_impl(ctx, False)
45+
46+
pdb_file_opt_test = analysistest.make(
47+
_pdb_file_for_opt_test_impl,
48+
config_settings = {
49+
"//command_line_option:compilation_mode": "opt",
50+
},
51+
)
52+
53+
# Mapping from compilation mode to pdb file test.
54+
pdb_file_tests = {
55+
"dbg": pdb_file_dbg_test,
56+
"fastbuild": pdb_file_fastbuild_test,
57+
"opt": pdb_file_opt_test,
58+
}
1859

1960
def _dsym_folder_test_impl(ctx):
2061
env = analysistest.begin(ctx)
@@ -47,11 +88,12 @@ def debug_info_analysis_test_suite(name):
4788
output_group = "pdb_file",
4889
)
4990

50-
pdb_file_test(
51-
name = "lib_pdb_test",
52-
target_under_test = ":mylib.pdb",
53-
target_compatible_with = ["@platforms//os:windows"],
54-
)
91+
for compilation_mode, pdb_test in pdb_file_tests.items():
92+
pdb_test(
93+
name = "lib_pdb_test_{}".format(compilation_mode),
94+
target_under_test = ":mylib.pdb",
95+
target_compatible_with = ["@platforms//os:windows"],
96+
)
5597

5698
native.filegroup(
5799
name = "mylib.dSYM",
@@ -77,11 +119,12 @@ def debug_info_analysis_test_suite(name):
77119
output_group = "pdb_file",
78120
)
79121

80-
pdb_file_test(
81-
name = "bin_pdb_test",
82-
target_under_test = ":mybin.pdb",
83-
target_compatible_with = ["@platforms//os:windows"],
84-
)
122+
for compilation_mode, pdb_test in pdb_file_tests.items():
123+
pdb_test(
124+
name = "bin_pdb_test_{}".format(compilation_mode),
125+
target_under_test = ":mybin.pdb",
126+
target_compatible_with = ["@platforms//os:windows"],
127+
)
85128

86129
native.filegroup(
87130
name = "mybin.dSYM",
@@ -108,11 +151,12 @@ def debug_info_analysis_test_suite(name):
108151
testonly = True,
109152
)
110153

111-
pdb_file_test(
112-
name = "test_pdb_test",
113-
target_under_test = ":mytest.pdb",
114-
target_compatible_with = ["@platforms//os:windows"],
115-
)
154+
for compilation_mode, pdb_test in pdb_file_tests.items():
155+
pdb_test(
156+
name = "test_pdb_test_{}".format(compilation_mode),
157+
target_under_test = ":mytest.pdb",
158+
target_compatible_with = ["@platforms//os:windows"],
159+
)
116160

117161
native.filegroup(
118162
name = "mytest.dSYM",
@@ -130,11 +174,17 @@ def debug_info_analysis_test_suite(name):
130174
native.test_suite(
131175
name = name,
132176
tests = [
133-
":lib_pdb_test",
134177
":lib_dsym_test",
135-
":bin_pdb_test",
136178
":bin_dsym_test",
137-
":test_pdb_test",
138179
":test_dsym_test",
180+
] + [
181+
":lib_pdb_test_{}".format(compilation_mode)
182+
for compilation_mode in pdb_file_tests
183+
] + [
184+
":bin_pdb_test_{}".format(compilation_mode)
185+
for compilation_mode in pdb_file_tests
186+
] + [
187+
":test_pdb_test_{}".format(compilation_mode)
188+
for compilation_mode in pdb_file_tests
139189
],
140190
)

test/unit/strip_level/BUILD.bazel

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
load(":strip_level_test_suite.bzl", "strip_level_test_suite")
2+
3+
strip_level_test_suite(
4+
name = "strip_level_test_suite",
5+
)
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"""Starlark tests for `rust_toolchain.strip_level`"""
2+
3+
load("@bazel_skylib//lib:unittest.bzl", "analysistest")
4+
load("@bazel_skylib//rules:write_file.bzl", "write_file")
5+
load("//rust:defs.bzl", "rust_binary")
6+
load(
7+
"//test/unit:common.bzl",
8+
"assert_action_mnemonic",
9+
"assert_argv_contains",
10+
)
11+
12+
def _strip_level_test_impl(ctx, expected_level):
13+
env = analysistest.begin(ctx)
14+
target = analysistest.target_under_test(env)
15+
16+
action = target.actions[0]
17+
assert_action_mnemonic(env, action, "Rustc")
18+
19+
assert_argv_contains(env, action, "--codegen=strip={}".format(expected_level))
20+
return analysistest.end(env)
21+
22+
def _strip_level_for_dbg_test_impl(ctx):
23+
return _strip_level_test_impl(ctx, "none")
24+
25+
_strip_level_for_dbg_test = analysistest.make(
26+
_strip_level_for_dbg_test_impl,
27+
config_settings = {
28+
"//command_line_option:compilation_mode": "dbg",
29+
},
30+
)
31+
32+
def _strip_level_for_fastbuild_test_impl(ctx):
33+
return _strip_level_test_impl(ctx, "none")
34+
35+
_strip_level_for_fastbuild_test = analysistest.make(
36+
_strip_level_for_fastbuild_test_impl,
37+
config_settings = {
38+
"//command_line_option:compilation_mode": "fastbuild",
39+
},
40+
)
41+
42+
def _strip_level_for_opt_test_impl(ctx):
43+
return _strip_level_test_impl(ctx, "debuginfo")
44+
45+
_strip_level_for_opt_test = analysistest.make(
46+
_strip_level_for_opt_test_impl,
47+
config_settings = {
48+
"//command_line_option:compilation_mode": "opt",
49+
},
50+
)
51+
52+
def strip_level_test_suite(name):
53+
"""Entry-point macro called from the BUILD file.
54+
55+
Args:
56+
name (str): The name of the test suite.
57+
"""
58+
write_file(
59+
name = "bin_main",
60+
out = "main.rs",
61+
content = [
62+
"fn main() {}",
63+
"",
64+
],
65+
)
66+
67+
rust_binary(
68+
name = "bin",
69+
srcs = [":main.rs"],
70+
edition = "2021",
71+
)
72+
73+
_strip_level_for_dbg_test(
74+
name = "strip_level_for_dbg_test",
75+
target_under_test = ":bin",
76+
)
77+
78+
_strip_level_for_fastbuild_test(
79+
name = "strip_level_for_fastbuild_test",
80+
target_under_test = ":bin",
81+
)
82+
83+
_strip_level_for_opt_test(
84+
name = "strip_level_for_opt_test",
85+
target_under_test = ":bin",
86+
)
87+
88+
native.test_suite(
89+
name = name,
90+
tests = [
91+
":strip_level_for_dbg_test",
92+
":strip_level_for_fastbuild_test",
93+
":strip_level_for_opt_test",
94+
],
95+
)

0 commit comments

Comments
 (0)