diff --git a/rust/private/debug_info.bzl b/rust/private/debug_info.bzl new file mode 100644 index 0000000000..cb9e8234bc --- /dev/null +++ b/rust/private/debug_info.bzl @@ -0,0 +1,26 @@ +"""A module defining Rust debug-info rules""" + +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") + +RustDebugInfoInfo = provider( + doc = "A provider describing the debug-info settings per compilation mode.", + fields = { + "levels": "dict[str, str]: Mapping of compilation mode to debug-info string.", + }, +) + +def _rust_debug_info_flag_impl(ctx): + levels = {} + for mode in ("dbg", "fastbuild", "opt"): + levels[mode] = getattr(ctx.attr, mode)[BuildSettingInfo].value + return [RustDebugInfoInfo(levels = levels)] + +rust_debug_info_flag = rule( + doc = "Aggregates the three per-mode debug-info flags into a single RustDebugInfoInfo provider. Valid values are defined by rustc: https://doc.rust-lang.org/rustc/codegen-options/index.html#debuginfo.", + implementation = _rust_debug_info_flag_impl, + attrs = { + "dbg": attr.label(default = "//rust/settings:debug_info_dbg"), + "fastbuild": attr.label(default = "//rust/settings:debug_info_fastbuild"), + "opt": attr.label(default = "//rust/settings:debug_info_opt"), + }, +) diff --git a/rust/private/opt_level.bzl b/rust/private/opt_level.bzl new file mode 100644 index 0000000000..c32b07f13f --- /dev/null +++ b/rust/private/opt_level.bzl @@ -0,0 +1,26 @@ +"""A module defining Rust opt-level rules""" + +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") + +RustOptLevelInfo = provider( + doc = "A provider describing the opt-level settings per compilation mode.", + fields = { + "levels": "dict[str, str]: Mapping of compilation mode to opt-level string.", + }, +) + +def _rust_opt_level_flag_impl(ctx): + levels = {} + for mode in ("dbg", "fastbuild", "opt"): + levels[mode] = getattr(ctx.attr, mode)[BuildSettingInfo].value + return [RustOptLevelInfo(levels = levels)] + +rust_opt_level_flag = rule( + doc = "Aggregates the three per-mode opt-level flags into a single RustOptLevelInfo provider. Valid values are defined by rustc: https://doc.rust-lang.org/rustc/codegen-options/index.html#opt-level", + implementation = _rust_opt_level_flag_impl, + attrs = { + "dbg": attr.label(default = "//rust/settings:opt_level_dbg"), + "fastbuild": attr.label(default = "//rust/settings:opt_level_fastbuild"), + "opt": attr.label(default = "//rust/settings:opt_level_opt"), + }, +) diff --git a/rust/private/repositories.bzl b/rust/private/repositories.bzl index cc463eb40a..a38eea45e3 100644 --- a/rust/private/repositories.bzl +++ b/rust/private/repositories.bzl @@ -64,6 +64,7 @@ def rust_register_toolchains( extra_rustc_flags = None, extra_exec_rustc_flags = None, opt_level = None, + debug_info = None, strip_level = None, urls = DEFAULT_STATIC_RUST_URL_TEMPLATES, versions = _RUST_TOOLCHAIN_VERSIONS, @@ -103,6 +104,7 @@ def rust_register_toolchains( extra_rustc_flags (dict, list, optional): Dictionary of target triples to list of extra flags to pass to rustc in non-exec configuration. extra_exec_rustc_flags (dict, list, optional): Dictionary of target triples to list of extra flags to pass to rustc in exec configuration. opt_level (dict, optional): Rustc optimization levels. For more details see the documentation for `rust_toolchain.opt_level`. + debug_info (dict, optional): Dictionary of target triples to debug info config. strip_level (dict, dict, optional): Dictionary of target triples to strip config. urls (list, optional): A list of mirror urls containing the tools from the Rust-lang static file server. These must contain the '{}' used to substitute the tool being fetched (using .format). versions (list, optional): A list of toolchain versions to download. This parameter only accepts one versions @@ -187,6 +189,7 @@ def rust_register_toolchains( extra_rustc_flags = extra_rustc_flags, extra_exec_rustc_flags = extra_exec_rustc_flags, opt_level = opt_level_by_triple, + debug_info = debug_info, strip_level = strip_level, sha256s = sha256s, urls = urls, @@ -275,6 +278,9 @@ _RUST_TOOLCHAIN_REPOSITORY_ATTRS = { "auth_patterns": attr.string_list( doc = "A list of patterns to match against urls for which the auth object should be used.", ), + "debug_info": attr.string_dict( + doc = "Rustc debug info levels. For more details see the documentation for `rust_toolchain.debug_info`.", + ), "dev_components": attr.bool( doc = "Whether to download the rustc-dev components (defaults to False). Requires version to be \"nightly\".", default = False, @@ -483,6 +489,7 @@ def _rust_toolchain_tools_repository_impl(ctx): extra_rustc_flags = ctx.attr.extra_rustc_flags, extra_exec_rustc_flags = ctx.attr.extra_exec_rustc_flags, opt_level = ctx.attr.opt_level if ctx.attr.opt_level else None, + debug_info = ctx.attr.debug_info if ctx.attr.debug_info else None, strip_level = ctx.attr.strip_level if ctx.attr.strip_level else None, version = toolchain_version, channel = channel, @@ -595,6 +602,7 @@ def rust_toolchain_repository( extra_rustc_flags = None, extra_exec_rustc_flags = None, opt_level = None, + debug_info = None, strip_level = None, sha256s = None, urls = DEFAULT_STATIC_RUST_URL_TEMPLATES, @@ -627,6 +635,7 @@ def rust_toolchain_repository( Subject to Make variable expansion with respect to RUST_SYSROOT, RUST_SYSROOT_SHORT, RUSTC, etc. opt_level (dict, optional): Optimization level config for this toolchain. + debug_info (dict, optional): Debug info level config for this toolchain. strip_level (dict, optional): Strip level config for this toolchain. sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. See [rust_register_toolchains](#rust_register_toolchains) for more details. @@ -660,6 +669,7 @@ def rust_toolchain_repository( extra_rustc_flags = extra_rustc_flags, extra_exec_rustc_flags = extra_exec_rustc_flags, opt_level = opt_level, + debug_info = debug_info, strip_level = strip_level, sha256s = sha256s, urls = urls, @@ -993,6 +1003,7 @@ def rust_repository_set( extra_rustc_flags = None, extra_exec_rustc_flags = None, opt_level = None, + debug_info = None, strip_level = None, sha256s = None, urls = DEFAULT_STATIC_RUST_URL_TEMPLATES, @@ -1026,6 +1037,7 @@ def rust_repository_set( extra_rustc_flags (dict, list, optional): Dictionary of target triples to list of extra flags to pass to rustc in non-exec configuration. extra_exec_rustc_flags (dict, list, optional): Dictionary of target triples to list of extra flags to pass to rustc in exec configuration. opt_level (dict, dict, optional): Dictionary of target triples to optimization config. + debug_info (dict, dict, optional): Dictionary of target triples to debug info config. strip_level (dict, dict, optional): Dictionary of target triples to strip config. sha256s (str, optional): A dict associating tool subdirectories to sha256 hashes. See [rust_register_toolchains](#rust_register_toolchains) for more details. @@ -1083,6 +1095,7 @@ def rust_repository_set( extra_rustc_flags = toolchain_extra_rustc_flags, extra_exec_rustc_flags = toolchain_extra_exec_rustc_flags, opt_level = opt_level.get(toolchain.target_triple) if opt_level != None else None, + debug_info = debug_info.get(toolchain.target_triple) if debug_info != None else None, strip_level = strip_level.get(toolchain.target_triple) if strip_level != None else None, sha256s = sha256s, urls = urls, diff --git a/rust/private/repository_utils.bzl b/rust/private/repository_utils.bzl index c1084bf60d..306ba3f120 100644 --- a/rust/private/repository_utils.bzl +++ b/rust/private/repository_utils.bzl @@ -367,6 +367,7 @@ rust_toolchain( extra_rustc_flags = {extra_rustc_flags}, extra_exec_rustc_flags = {extra_exec_rustc_flags}, opt_level = {opt_level}, + debug_info = {debug_info}, strip_level = {strip_level}, version = "{version}", channel = "{channel}", @@ -393,6 +394,7 @@ def BUILD_for_rust_toolchain( extra_rustc_flags = None, extra_exec_rustc_flags = None, opt_level = None, + debug_info = None, strip_level = None): """Emits a toolchain declaration to match an existing compiler and stdlib. @@ -418,6 +420,7 @@ def BUILD_for_rust_toolchain( extra_rustc_flags (list, optional): Extra flags to pass to rustc in non-exec configuration. extra_exec_rustc_flags (list, optional): Extra flags to pass to rustc in exec configuration. opt_level (dict, optional): Optimization level config for this toolchain. + debug_info (dict, optional): Debug info level config for this toolchain. strip_level (dict, optional): Strip level config for this toolchain. Returns: @@ -480,6 +483,7 @@ def BUILD_for_rust_toolchain( extra_rustc_flags = extra_rustc_flags, extra_exec_rustc_flags = extra_exec_rustc_flags, opt_level = opt_level, + debug_info = debug_info, strip_level = strip_level, version = version, channel = channel, diff --git a/rust/private/strip_level.bzl b/rust/private/strip_level.bzl new file mode 100644 index 0000000000..56b1647659 --- /dev/null +++ b/rust/private/strip_level.bzl @@ -0,0 +1,26 @@ +"""A module defining Rust strip-level rules""" + +load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo") + +RustStripLevelInfo = provider( + doc = "A provider describing the strip-level settings per compilation mode.", + fields = { + "levels": "dict[str, str]: Mapping of compilation mode to strip-level string.", + }, +) + +def _rust_strip_level_flag_impl(ctx): + levels = {} + for mode in ("dbg", "fastbuild", "opt"): + levels[mode] = getattr(ctx.attr, mode)[BuildSettingInfo].value + return [RustStripLevelInfo(levels = levels)] + +rust_strip_level_flag = rule( + doc = "Aggregates the three per-mode strip-level flags into a single RustStripLevelInfo provider. Valid values are defined by rustc: https://doc.rust-lang.org/rustc/codegen-options/index.html#strip", + implementation = _rust_strip_level_flag_impl, + attrs = { + "dbg": attr.label(default = "//rust/settings:strip_level_dbg"), + "fastbuild": attr.label(default = "//rust/settings:strip_level_fastbuild"), + "opt": attr.label(default = "//rust/settings:strip_level_opt"), + }, +) diff --git a/rust/private/toolchain.bzl b/rust/private/toolchain.bzl index 8effcbca4e..f325763ab4 100644 --- a/rust/private/toolchain.bzl +++ b/rust/private/toolchain.bzl @@ -8,12 +8,15 @@ load("@rules_cc//cc/common:cc_common.bzl", "cc_common") load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") load("//rust/platform:triple.bzl", "triple") load("//rust/private:common.bzl", "rust_common") +load("//rust/private:debug_info.bzl", "RustDebugInfoInfo") load("//rust/private:lto.bzl", "RustLtoInfo") +load("//rust/private:opt_level.bzl", "RustOptLevelInfo") load( "//rust/private:rust_allocator_libraries.bzl", "make_libstd_and_allocator_ccinfo", ) load("//rust/private:semver.bzl", "semver") +load("//rust/private:strip_level.bzl", "RustStripLevelInfo") load( "//rust/private:utils.bzl", "deduplicate", @@ -393,16 +396,18 @@ def _rust_toolchain_impl(ctx): Returns: list: A list containing the target's toolchain Provider info """ + effective_opt_levels = dict(ctx.attr._opt_level[RustOptLevelInfo].levels) + effective_opt_levels.update(ctx.attr.opt_level) + + effective_debug_info = dict(ctx.attr._debug_info[RustDebugInfoInfo].levels) + effective_debug_info.update(ctx.attr.debug_info) + + effective_strip_level = dict(ctx.attr._strip_level[RustStripLevelInfo].levels) + effective_strip_level.update(ctx.attr.strip_level) + compilation_mode_opts = {} - 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)) - 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)) + for k, opt_level in effective_opt_levels.items(): + compilation_mode_opts[k] = struct(debug_info = effective_debug_info[k], opt_level = opt_level, strip_level = effective_strip_level[k]) rename_first_party_crates = ctx.attr._rename_first_party_crates[BuildSettingInfo].value third_party_dir = ctx.attr._third_party_dir[BuildSettingInfo].value @@ -693,12 +698,13 @@ rust_toolchain = rule( cfg = "exec", ), "debug_info": attr.string_dict( - doc = "Rustc debug info levels per opt level", - default = { - "dbg": "2", - "fastbuild": "0", - "opt": "0", - }, + doc = "Per-toolchain debug-info overrides per compilation mode. Any mode set here takes precedence over the global `//rust/settings:debug_info_*` flags. Omit a mode (or leave empty) to use the global flag value.", + default = {}, + ), + "_debug_info": attr.label( + default = Label("//rust/settings:debug_info"), + providers = [RustDebugInfoInfo], + doc = "Global debug-info defaults, read from the `//rust/settings:debug_info_*` flags.", ), "default_edition": attr.string( doc = ( @@ -796,12 +802,13 @@ rust_toolchain = rule( doc = "Label to an LTO setting whether which can enable custom LTO settings", ), "opt_level": attr.string_dict( - doc = "Rustc optimization levels.", - default = { - "dbg": "0", - "fastbuild": "0", - "opt": "3", - }, + doc = "Per-toolchain opt-level overrides per compilation mode. Any mode set here takes precedence over the global `//rust/settings:opt_level_*` flags. Omit a mode (or leave empty) to use the global flag value.", + default = {}, + ), + "_opt_level": attr.label( + default = Label("//rust/settings:opt_level"), + providers = [RustOptLevelInfo], + doc = "Global opt-level defaults, read from the `//rust/settings:opt_level_*` flags.", ), "per_crate_rustc_flags": attr.string_list( doc = "Extra flags to pass to rustc in non-exec configuration", @@ -857,15 +864,13 @@ rust_toolchain = rule( mandatory = True, ), "strip_level": attr.string_dict( - doc = ( - "Rustc strip levels. For all potential options, see " + - "https://doc.rust-lang.org/rustc/codegen-options/index.html#strip" - ), - default = { - "dbg": "none", - "fastbuild": "none", - "opt": "debuginfo", - }, + doc = "Per-toolchain strip-level overrides per compilation mode. Any mode set here takes precedence over the global `//rust/settings:strip_level_*` flags. Omit a mode (or leave empty) to use the global flag value.", + default = {}, + ), + "_strip_level": attr.label( + default = Label("//rust/settings:strip_level"), + providers = [RustStripLevelInfo], + doc = "Global strip-level defaults, read from the `//rust/settings:strip_level_*` flags.", ), "target_json": attr.string( doc = ("Override the target_triple with a custom target specification. " + diff --git a/rust/settings/BUILD.bazel b/rust/settings/BUILD.bazel index 375ea537ee..f3a8ad344e 100644 --- a/rust/settings/BUILD.bazel +++ b/rust/settings/BUILD.bazel @@ -10,6 +10,7 @@ load( "clippy_toml", "codegen_units", "collect_cfgs", + "debug_info", "default_allocator_library", "error_format", "experimental_compile_rustdoc_tests", @@ -31,11 +32,13 @@ load( "incompatible_do_not_include_transitive_data_in_compile_inputs", "lto", "no_std", + "opt_level", "pipelined_compilation", "rename_first_party_crates", "require_explicit_unstable_features", "rustc_output_diagnostics", "rustfmt_toml", + "strip_level", "third_party_dir", "toolchain_generated_sysroot", "toolchain_linker_preference", @@ -117,10 +120,14 @@ incompatible_do_not_include_data_in_compile_data() incompatible_do_not_include_transitive_data_in_compile_inputs() +debug_info() + lto() no_std() +opt_level() + pipelined_compilation() rename_first_party_crates() @@ -131,6 +138,8 @@ rustc_output_diagnostics() rustfmt_toml() +strip_level() + third_party_dir() toolchain_generated_sysroot() diff --git a/rust/settings/settings.bzl b/rust/settings/settings.bzl index b6d3494264..8f740d483a 100644 --- a/rust/settings/settings.bzl +++ b/rust/settings/settings.bzl @@ -16,7 +16,9 @@ load( _clippy_flags = "clippy_flags", _clippy_output_diagnostics = "clippy_output_diagnostics", ) +load("//rust/private:debug_info.bzl", "rust_debug_info_flag") load("//rust/private:lto.bzl", "rust_lto_flag") +load("//rust/private:opt_level.bzl", "rust_opt_level_flag") load( "//rust/private:rustc.bzl", _always_enable_metadata_output_groups = "always_enable_metadata_output_groups", @@ -32,6 +34,7 @@ load( _rustc_output_diagnostics = "rustc_output_diagnostics", _zself_profile_events = "zself_profile_events", ) +load("//rust/private:strip_level.bzl", "rust_strip_level_flag") load("//rust/private:unpretty.bzl", "UNPRETTY_MODES", "rust_unpretty_flag") load(":incompatible.bzl", "incompatible_flag") @@ -67,6 +70,124 @@ def lto(): build_setting_default = "unspecified", ) +# buildifier: disable=unnamed-macro +def opt_level(): + """Build settings to control the rustc optimization level per compilation mode. + + Three flags are defined, one per Bazel compilation mode. Accepted values are + documented at https://doc.rust-lang.org/rustc/codegen-options/index.html#opt-level. + The value sets the default for all toolchains that do not explicitly override + it via the `opt_level` attribute on `rust_toolchain`. + + | Flag | Compilation mode | Default | + |---------------------------------------------------|------------------|---------| + | `@rules_rust//rust/settings:opt_level_dbg` | `dbg` | `"0"` | + | `@rules_rust//rust/settings:opt_level_fastbuild` | `fastbuild` | `"0"` | + | `@rules_rust//rust/settings:opt_level_opt` | `opt` | `"3"` | + + Example: + + Enable size optimization in `opt` mode and light optimization in `fastbuild`: + + ``` + build --@rules_rust//rust/settings:opt_level_opt=s + build --@rules_rust//rust/settings:opt_level_fastbuild=1 + ``` + """ + string_flag( + name = "opt_level_dbg", + build_setting_default = "0", + ) + string_flag( + name = "opt_level_opt", + build_setting_default = "3", + ) + string_flag( + name = "opt_level_fastbuild", + build_setting_default = "0", + ) + rust_opt_level_flag( + name = "opt_level", + ) + +# buildifier: disable=unnamed-macro +def debug_info(): + """Build settings to control the rustc debug info level per compilation mode. + + Three flags are defined, one per Bazel compilation mode. Accepted values are + documented at https://doc.rust-lang.org/rustc/codegen-options/index.html#debuginfo. + The value sets the default for all toolchains that do not explicitly override + it via the `debug_info` attribute on `rust_toolchain`. + + | Flag | Compilation mode | Default | + |-----------------------------------------------------|------------------|---------| + | `@rules_rust//rust/settings:debug_info_dbg` | `dbg` | `"2"` | + | `@rules_rust//rust/settings:debug_info_fastbuild` | `fastbuild` | `"0"` | + | `@rules_rust//rust/settings:debug_info_opt` | `opt` | `"0"` | + + Example: + + Emit line tables in `fastbuild` mode for profiling without full debug info: + + ``` + build --@rules_rust//rust/settings:debug_info_fastbuild=1 + ``` + """ + string_flag( + name = "debug_info_dbg", + build_setting_default = "2", + ) + string_flag( + name = "debug_info_opt", + build_setting_default = "0", + ) + string_flag( + name = "debug_info_fastbuild", + build_setting_default = "0", + ) + rust_debug_info_flag( + name = "debug_info", + ) + +# buildifier: disable=unnamed-macro +def strip_level(): + """Build settings to control the rustc strip level per compilation mode. + + Three flags are defined, one per Bazel compilation mode. Accepted values are + documented at https://doc.rust-lang.org/rustc/codegen-options/index.html#strip. + The value sets the default for all toolchains that do not explicitly override + it via the `strip_level` attribute on `rust_toolchain`. + + | Flag | Compilation mode | Default | + |-----------------------------------------------------|------------------|----------------| + | `@rules_rust//rust/settings:strip_level_dbg` | `dbg` | `"none"` | + | `@rules_rust//rust/settings:strip_level_fastbuild` | `fastbuild` | `"none"` | + | `@rules_rust//rust/settings:strip_level_opt` | `opt` | `"debuginfo"` | + + Example: + + Strip all symbols in `opt` mode to minimize binary size: + + ``` + build --@rules_rust//rust/settings:strip_level_opt=symbols + ``` + """ + string_flag( + name = "strip_level_dbg", + build_setting_default = "none", + ) + string_flag( + name = "strip_level_opt", + build_setting_default = "debuginfo", + ) + string_flag( + name = "strip_level_fastbuild", + build_setting_default = "none", + ) + rust_strip_level_flag( + name = "strip_level", + ) + def rename_first_party_crates(): """A flag controlling whether to rename first-party crates such that their names \ encode the Bazel package and target name, instead of just the target name. diff --git a/test/unit/debug_info/debug_info_analysis_test.bzl b/test/unit/debug_info/debug_info_analysis_test.bzl index ad5bbf6b36..ae9338620b 100644 --- a/test/unit/debug_info/debug_info_analysis_test.bzl +++ b/test/unit/debug_info/debug_info_analysis_test.bzl @@ -1,7 +1,39 @@ -"""Analysis tests for debug info in cdylib and bin targets.""" +"""Analysis tests for debug info: output files (PDB, dSYM) and global flag defaults.""" load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") +load("@bazel_skylib//rules:write_file.bzl", "write_file") load("//rust:defs.bzl", "rust_binary", "rust_shared_library", "rust_test") +load("//rust/private:debug_info.bzl", "RustDebugInfoInfo") +load("//rust/private:opt_level.bzl", "RustOptLevelInfo") +load("//rust/private:strip_level.bzl", "RustStripLevelInfo") +load( + "//test/unit:common.bzl", + "assert_action_mnemonic", + "assert_argv_contains", +) + +def _debug_info_modes_match_test_impl(ctx): + env = analysistest.begin(ctx) + debug_modes = sorted(analysistest.target_under_test(env)[RustDebugInfoInfo].levels.keys()) + opt_modes = sorted(ctx.attr._opt_level[RustOptLevelInfo].levels.keys()) + strip_modes = sorted(ctx.attr._strip_level[RustStripLevelInfo].levels.keys()) + asserts.equals(env, debug_modes, opt_modes, "debug_info and opt_level compilation modes must match") + asserts.equals(env, debug_modes, strip_modes, "debug_info and strip_level compilation modes must match") + return analysistest.end(env) + +_debug_info_modes_match_test = analysistest.make( + _debug_info_modes_match_test_impl, + attrs = { + "_opt_level": attr.label( + default = "//rust/settings:opt_level", + providers = [RustOptLevelInfo], + ), + "_strip_level": attr.label( + default = "//rust/settings:strip_level", + providers = [RustStripLevelInfo], + ), + }, +) def _pdb_file_test_impl(ctx, expect_pdb_file): env = analysistest.begin(ctx) @@ -70,6 +102,77 @@ def _dsym_folder_test_impl(ctx): dsym_folder_test = analysistest.make(_dsym_folder_test_impl) +def _debug_info_flag_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=debuginfo={}".format(expected_level)) + return analysistest.end(env) + +def _debug_info_for_dbg_test_impl(ctx): + return _debug_info_flag_test_impl(ctx, "2") + +_debug_info_for_dbg_test = analysistest.make( + _debug_info_for_dbg_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "dbg", + }, +) + +def _debug_info_for_fastbuild_test_impl(ctx): + return _debug_info_flag_test_impl(ctx, "0") + +_debug_info_for_fastbuild_test = analysistest.make( + _debug_info_for_fastbuild_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "fastbuild", + }, +) + +def _debug_info_for_opt_test_impl(ctx): + return _debug_info_flag_test_impl(ctx, "0") + +_debug_info_for_opt_test = analysistest.make( + _debug_info_for_opt_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "opt", + }, +) + +def _debug_info_dbg_setting_test_impl(ctx): + return _debug_info_flag_test_impl(ctx, "1") + +_debug_info_dbg_setting_test = analysistest.make( + _debug_info_dbg_setting_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "dbg", + str(Label("//rust/settings:debug_info_dbg")): "1", + }, +) + +def _debug_info_opt_setting_test_impl(ctx): + return _debug_info_flag_test_impl(ctx, "1") + +_debug_info_opt_setting_test = analysistest.make( + _debug_info_opt_setting_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "opt", + str(Label("//rust/settings:debug_info_opt")): "1", + }, +) + +def _debug_info_fastbuild_setting_test_impl(ctx): + return _debug_info_flag_test_impl(ctx, "2") + +_debug_info_fastbuild_setting_test = analysistest.make( + _debug_info_fastbuild_setting_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "fastbuild", + str(Label("//rust/settings:debug_info_fastbuild")): "2", + }, +) + def debug_info_analysis_test_suite(name): """Analysis tests for debug info in cdylib and bin targets. @@ -171,12 +274,69 @@ def debug_info_analysis_test_suite(name): target_compatible_with = ["@platforms//os:macos"], ) + _debug_info_modes_match_test( + name = "debug_info_modes_match_test", + target_under_test = "//rust/settings:debug_info", + ) + + write_file( + name = "flag_bin_main", + out = "flag_main.rs", + content = [ + "fn main() {}", + "", + ], + ) + + rust_binary( + name = "flag_bin", + srcs = [":flag_main.rs"], + edition = "2021", + ) + + _debug_info_for_dbg_test( + name = "debug_info_for_dbg_test", + target_under_test = ":flag_bin", + ) + + _debug_info_for_fastbuild_test( + name = "debug_info_for_fastbuild_test", + target_under_test = ":flag_bin", + ) + + _debug_info_for_opt_test( + name = "debug_info_for_opt_test", + target_under_test = ":flag_bin", + ) + + _debug_info_dbg_setting_test( + name = "debug_info_dbg_setting_test", + target_under_test = ":flag_bin", + ) + + _debug_info_opt_setting_test( + name = "debug_info_opt_setting_test", + target_under_test = ":flag_bin", + ) + + _debug_info_fastbuild_setting_test( + name = "debug_info_fastbuild_setting_test", + target_under_test = ":flag_bin", + ) + native.test_suite( name = name, tests = [ ":lib_dsym_test", ":bin_dsym_test", ":test_dsym_test", + ":debug_info_modes_match_test", + ":debug_info_for_dbg_test", + ":debug_info_for_fastbuild_test", + ":debug_info_for_opt_test", + ":debug_info_dbg_setting_test", + ":debug_info_opt_setting_test", + ":debug_info_fastbuild_setting_test", ] + [ ":lib_pdb_test_{}".format(compilation_mode) for compilation_mode in pdb_file_tests diff --git a/test/unit/opt_level/opt_level_test_suite.bzl b/test/unit/opt_level/opt_level_test_suite.bzl index 9003a67200..be06d0a6dd 100644 --- a/test/unit/opt_level/opt_level_test_suite.bzl +++ b/test/unit/opt_level/opt_level_test_suite.bzl @@ -1,8 +1,11 @@ """Starlark tests for `rust_toolchain.opt_level`""" -load("@bazel_skylib//lib:unittest.bzl", "analysistest") +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") load("@bazel_skylib//rules:write_file.bzl", "write_file") load("//rust:defs.bzl", "rust_binary") +load("//rust/private:debug_info.bzl", "RustDebugInfoInfo") +load("//rust/private:opt_level.bzl", "RustOptLevelInfo") +load("//rust/private:strip_level.bzl", "RustStripLevelInfo") load( "//test/unit:common.bzl", "assert_action_mnemonic", @@ -49,6 +52,84 @@ _opt_level_for_opt_test = analysistest.make( }, ) +def _opt_level_dbg_setting_test_impl(ctx): + return _opt_level_test_impl(ctx, "1") + +_opt_level_dbg_setting_test = analysistest.make( + _opt_level_dbg_setting_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "dbg", + str(Label("//rust/settings:opt_level_dbg")): "1", + }, +) + +def _opt_level_opt_setting_test_impl(ctx): + return _opt_level_test_impl(ctx, "2") + +_opt_level_opt_setting_test = analysistest.make( + _opt_level_opt_setting_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "opt", + str(Label("//rust/settings:opt_level_opt")): "2", + }, +) + +def _opt_level_fastbuild_setting_test_impl(ctx): + return _opt_level_test_impl(ctx, "1") + +_opt_level_fastbuild_setting_test = analysistest.make( + _opt_level_fastbuild_setting_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "fastbuild", + str(Label("//rust/settings:opt_level_fastbuild")): "1", + }, +) + +def _opt_level_size_setting_test_impl(ctx): + return _opt_level_test_impl(ctx, "s") + +_opt_level_size_setting_test = analysistest.make( + _opt_level_size_setting_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "opt", + str(Label("//rust/settings:opt_level_opt")): "s", + }, +) + +def _opt_level_minsize_setting_test_impl(ctx): + return _opt_level_test_impl(ctx, "z") + +_opt_level_minsize_setting_test = analysistest.make( + _opt_level_minsize_setting_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "opt", + str(Label("//rust/settings:opt_level_opt")): "z", + }, +) + +def _opt_level_modes_match_test_impl(ctx): + env = analysistest.begin(ctx) + opt_modes = sorted(analysistest.target_under_test(env)[RustOptLevelInfo].levels.keys()) + debug_modes = sorted(ctx.attr._debug_info[RustDebugInfoInfo].levels.keys()) + strip_modes = sorted(ctx.attr._strip_level[RustStripLevelInfo].levels.keys()) + asserts.equals(env, opt_modes, debug_modes, "opt_level and debug_info compilation modes must match") + asserts.equals(env, opt_modes, strip_modes, "opt_level and strip_level compilation modes must match") + return analysistest.end(env) + +_opt_level_modes_match_test = analysistest.make( + _opt_level_modes_match_test_impl, + attrs = { + "_debug_info": attr.label( + default = "//rust/settings:debug_info", + providers = [RustDebugInfoInfo], + ), + "_strip_level": attr.label( + default = "//rust/settings:strip_level", + providers = [RustStripLevelInfo], + ), + }, +) + def opt_level_test_suite(name): """Entry-point macro called from the BUILD file. @@ -85,11 +166,47 @@ def opt_level_test_suite(name): target_under_test = ":bin", ) + _opt_level_dbg_setting_test( + name = "opt_level_dbg_setting_test", + target_under_test = ":bin", + ) + + _opt_level_opt_setting_test( + name = "opt_level_opt_setting_test", + target_under_test = ":bin", + ) + + _opt_level_fastbuild_setting_test( + name = "opt_level_fastbuild_setting_test", + target_under_test = ":bin", + ) + + _opt_level_size_setting_test( + name = "opt_level_size_setting_test", + target_under_test = ":bin", + ) + + _opt_level_minsize_setting_test( + name = "opt_level_minsize_setting_test", + target_under_test = ":bin", + ) + + _opt_level_modes_match_test( + name = "opt_level_modes_match_test", + target_under_test = "//rust/settings:opt_level", + ) + native.test_suite( name = name, tests = [ ":opt_level_for_dbg_test", ":opt_level_for_fastbuild_test", ":opt_level_for_opt_test", + ":opt_level_dbg_setting_test", + ":opt_level_opt_setting_test", + ":opt_level_fastbuild_setting_test", + ":opt_level_size_setting_test", + ":opt_level_minsize_setting_test", + ":opt_level_modes_match_test", ], ) diff --git a/test/unit/strip_level/strip_level_test_suite.bzl b/test/unit/strip_level/strip_level_test_suite.bzl index a4b6b30171..2dcb5048f2 100644 --- a/test/unit/strip_level/strip_level_test_suite.bzl +++ b/test/unit/strip_level/strip_level_test_suite.bzl @@ -1,8 +1,11 @@ """Starlark tests for `rust_toolchain.strip_level`""" -load("@bazel_skylib//lib:unittest.bzl", "analysistest") +load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") load("@bazel_skylib//rules:write_file.bzl", "write_file") load("//rust:defs.bzl", "rust_binary") +load("//rust/private:debug_info.bzl", "RustDebugInfoInfo") +load("//rust/private:opt_level.bzl", "RustOptLevelInfo") +load("//rust/private:strip_level.bzl", "RustStripLevelInfo") load( "//test/unit:common.bzl", "assert_action_mnemonic", @@ -49,6 +52,62 @@ _strip_level_for_opt_test = analysistest.make( }, ) +def _strip_level_modes_match_test_impl(ctx): + env = analysistest.begin(ctx) + strip_modes = sorted(analysistest.target_under_test(env)[RustStripLevelInfo].levels.keys()) + opt_modes = sorted(ctx.attr._opt_level[RustOptLevelInfo].levels.keys()) + debug_modes = sorted(ctx.attr._debug_info[RustDebugInfoInfo].levels.keys()) + asserts.equals(env, strip_modes, opt_modes, "strip_level and opt_level compilation modes must match") + asserts.equals(env, strip_modes, debug_modes, "strip_level and debug_info compilation modes must match") + return analysistest.end(env) + +_strip_level_modes_match_test = analysistest.make( + _strip_level_modes_match_test_impl, + attrs = { + "_opt_level": attr.label( + default = "//rust/settings:opt_level", + providers = [RustOptLevelInfo], + ), + "_debug_info": attr.label( + default = "//rust/settings:debug_info", + providers = [RustDebugInfoInfo], + ), + }, +) + +def _strip_level_dbg_setting_test_impl(ctx): + return _strip_level_test_impl(ctx, "symbols") + +_strip_level_dbg_setting_test = analysistest.make( + _strip_level_dbg_setting_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "dbg", + str(Label("//rust/settings:strip_level_dbg")): "symbols", + }, +) + +def _strip_level_opt_setting_test_impl(ctx): + return _strip_level_test_impl(ctx, "symbols") + +_strip_level_opt_setting_test = analysistest.make( + _strip_level_opt_setting_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "opt", + str(Label("//rust/settings:strip_level_opt")): "symbols", + }, +) + +def _strip_level_fastbuild_setting_test_impl(ctx): + return _strip_level_test_impl(ctx, "debuginfo") + +_strip_level_fastbuild_setting_test = analysistest.make( + _strip_level_fastbuild_setting_test_impl, + config_settings = { + "//command_line_option:compilation_mode": "fastbuild", + str(Label("//rust/settings:strip_level_fastbuild")): "debuginfo", + }, +) + def strip_level_test_suite(name): """Entry-point macro called from the BUILD file. @@ -70,6 +129,11 @@ def strip_level_test_suite(name): edition = "2021", ) + _strip_level_modes_match_test( + name = "strip_level_modes_match_test", + target_under_test = "//rust/settings:strip_level", + ) + _strip_level_for_dbg_test( name = "strip_level_for_dbg_test", target_under_test = ":bin", @@ -85,11 +149,30 @@ def strip_level_test_suite(name): target_under_test = ":bin", ) + _strip_level_dbg_setting_test( + name = "strip_level_dbg_setting_test", + target_under_test = ":bin", + ) + + _strip_level_opt_setting_test( + name = "strip_level_opt_setting_test", + target_under_test = ":bin", + ) + + _strip_level_fastbuild_setting_test( + name = "strip_level_fastbuild_setting_test", + target_under_test = ":bin", + ) + native.test_suite( name = name, tests = [ + ":strip_level_modes_match_test", ":strip_level_for_dbg_test", ":strip_level_for_fastbuild_test", ":strip_level_for_opt_test", + ":strip_level_dbg_setting_test", + ":strip_level_opt_setting_test", + ":strip_level_fastbuild_setting_test", ], )