From 9c1190a4a123932fe0f9368f4680b310099a2997 Mon Sep 17 00:00:00 2001 From: matte1 Date: Thu, 22 Feb 2024 16:37:38 -0700 Subject: [PATCH] feat: Strip debug info from opt builds 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. https://github.com/rust-lang/cargo/issues/4122#issuecomment-1868318860 --- rust/private/rustc.bzl | 1 + rust/toolchain.bzl | 16 +++- test/unit/strip_level/BUILD.bazel | 5 + .../strip_level/strip_level_test_suite.bzl | 95 +++++++++++++++++++ 4 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 test/unit/strip_level/BUILD.bazel create mode 100644 test/unit/strip_level/strip_level_test_suite.bzl diff --git a/rust/private/rustc.bzl b/rust/private/rustc.bzl index f6f632dba6..67fd9f0d3a 100644 --- a/rust/private/rustc.bzl +++ b/rust/private/rustc.bzl @@ -959,6 +959,7 @@ 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") + 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: diff --git a/rust/toolchain.bzl b/rust/toolchain.bzl index 36c42b7a67..10146e9552 100644 --- a/rust/toolchain.bzl +++ b/rust/toolchain.bzl @@ -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)) @@ -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"), diff --git a/test/unit/strip_level/BUILD.bazel b/test/unit/strip_level/BUILD.bazel new file mode 100644 index 0000000000..d342c6a6c3 --- /dev/null +++ b/test/unit/strip_level/BUILD.bazel @@ -0,0 +1,5 @@ +load(":strip_level_test_suite.bzl", "strip_level_test_suite") + +strip_level_test_suite( + name = "strip_level_test_suite", +) diff --git a/test/unit/strip_level/strip_level_test_suite.bzl b/test/unit/strip_level/strip_level_test_suite.bzl new file mode 100644 index 0000000000..a4b6b30171 --- /dev/null +++ b/test/unit/strip_level/strip_level_test_suite.bzl @@ -0,0 +1,95 @@ +"""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", + ) + + _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", + ], + )