diff --git a/docs/rules.md b/docs/rules.md index 3a63dde0..e71e00bb 100644 --- a/docs/rules.md +++ b/docs/rules.md @@ -64,7 +64,7 @@ zig_binary( | linker_script | Custom linker script for the target.

Note, as of Zig version 0.15.1 linker-scripts require the LLVM/LLD backend to be enabled, see https://github.com/ziglang/zig/issues/25069. Set `zigopts=["-fllvm", "-flld"]` to that end. | Label | optional | `None` | | linkopts | Additional list of flags passed to the linker. Subject to location expansion. | List of strings | optional | `[]` | | main | The main source file.

If not set, deps must contain exactly one Zig module dependency which will be used as the root module. Note that in that case, 'srcs', 'extra_srcs' and 'csrcs' must also be empty as they are taken from the root module instead. | Label | optional | `None` | -| strip_debug_symbols | Whether to pass '-fstrip' to the zig compiler to remove debug symbols. | Boolean | optional | `False` | +| strip_debug_symbols | Whether to force passing '-fstrip' to the zig compiler to remove debug symbols. Bazel's `--strip` flag is also supported globally. | Boolean | optional | `False` | | zigopts | Additional list of flags passed to the zig compiler. Subject to location expansion.

This is an advanced feature that can conflict with attributes, build settings, and other flags defined by the toolchain itself. Use this at your own risk of hitting undefined behaviors. | List of strings | optional | `[]` | @@ -451,7 +451,7 @@ zig_shared_library( | linkopts | Additional list of flags passed to the linker. Subject to location expansion. | List of strings | optional | `[]` | | main | The main source file.

If not set, deps must contain exactly one Zig module dependency which will be used as the root module. Note that in that case, 'srcs', 'extra_srcs' and 'csrcs' must also be empty as they are taken from the root module instead. | Label | optional | `None` | | shared_lib_name | - | String | optional | `""` | -| strip_debug_symbols | Whether to pass '-fstrip' to the zig compiler to remove debug symbols. | Boolean | optional | `False` | +| strip_debug_symbols | Whether to force passing '-fstrip' to the zig compiler to remove debug symbols. Bazel's `--strip` flag is also supported globally. | Boolean | optional | `False` | | zigopts | Additional list of flags passed to the zig compiler. Subject to location expansion.

This is an advanced feature that can conflict with attributes, build settings, and other flags defined by the toolchain itself. Use this at your own risk of hitting undefined behaviors. | List of strings | optional | `[]` | @@ -514,7 +514,7 @@ zig_static_library( | linker_script | Custom linker script for the target.

Note, as of Zig version 0.15.1 linker-scripts require the LLVM/LLD backend to be enabled, see https://github.com/ziglang/zig/issues/25069. Set `zigopts=["-fllvm", "-flld"]` to that end. | Label | optional | `None` | | linkopts | Additional list of flags passed to the linker. Subject to location expansion. | List of strings | optional | `[]` | | main | The main source file.

If not set, deps must contain exactly one Zig module dependency which will be used as the root module. Note that in that case, 'srcs', 'extra_srcs' and 'csrcs' must also be empty as they are taken from the root module instead. | Label | optional | `None` | -| strip_debug_symbols | Whether to pass '-fstrip' to the zig compiler to remove debug symbols. | Boolean | optional | `False` | +| strip_debug_symbols | Whether to force passing '-fstrip' to the zig compiler to remove debug symbols. Bazel's `--strip` flag is also supported globally. | Boolean | optional | `False` | | zigopts | Additional list of flags passed to the zig compiler. Subject to location expansion.

This is an advanced feature that can conflict with attributes, build settings, and other flags defined by the toolchain itself. Use this at your own risk of hitting undefined behaviors. | List of strings | optional | `[]` | @@ -576,7 +576,7 @@ zig_test( | linker_script | Custom linker script for the target.

Note, as of Zig version 0.15.1 linker-scripts require the LLVM/LLD backend to be enabled, see https://github.com/ziglang/zig/issues/25069. Set `zigopts=["-fllvm", "-flld"]` to that end. | Label | optional | `None` | | linkopts | Additional list of flags passed to the linker. Subject to location expansion. | List of strings | optional | `[]` | | main | The main source file.

If not set, deps must contain exactly one Zig module dependency which will be used as the root module. Note that in that case, 'srcs', 'extra_srcs' and 'csrcs' must also be empty as they are taken from the root module instead. | Label | optional | `None` | -| strip_debug_symbols | Whether to pass '-fstrip' to the zig compiler to remove debug symbols. | Boolean | optional | `False` | +| strip_debug_symbols | Whether to force passing '-fstrip' to the zig compiler to remove debug symbols. Bazel's `--strip` flag is also supported globally. | Boolean | optional | `False` | | test_runner | Optional Zig file to specify a custom test runner | Label | optional | `None` | | zigopts | Additional list of flags passed to the zig compiler. Subject to location expansion.

This is an advanced feature that can conflict with attributes, build settings, and other flags defined by the toolchain itself. Use this at your own risk of hitting undefined behaviors. | List of strings | optional | `[]` | diff --git a/zig/config/BUILD.bazel b/zig/config/BUILD.bazel index 1647d643..eaed6455 100644 --- a/zig/config/BUILD.bazel +++ b/zig/config/BUILD.bazel @@ -5,6 +5,7 @@ filegroup( ":BUILD.bazel", "//zig/config/bootstrapped:all_files", "//zig/config/mode:all_files", + "//zig/config/strip:all_files", "//zig/config/threaded:all_files", "//zig/config/use_standalone_translate_c:all_files", ], diff --git a/zig/config/strip/BUILD.bazel b/zig/config/strip/BUILD.bazel new file mode 100644 index 00000000..8977ad4a --- /dev/null +++ b/zig/config/strip/BUILD.bazel @@ -0,0 +1,27 @@ +config_setting( + name = "always", + values = { + "strip": "always", + }, +) + +config_setting( + name = "never", + values = { + "strip": "never", + }, +) + +config_setting( + name = "sometimes", + values = { + "strip": "sometimes", + }, +) + +# Execute `bazel run //util:update_filegroups` to update this target. +filegroup( + name = "all_files", + srcs = [":BUILD.bazel"], + visibility = ["//zig/config:__pkg__"], +) diff --git a/zig/private/common/zig_build.bzl b/zig/private/common/zig_build.bzl index 902d7736..bdf285bb 100644 --- a/zig/private/common/zig_build.bzl +++ b/zig/private/common/zig_build.bzl @@ -115,7 +115,7 @@ enabled, see https://github.com/ziglang/zig/issues/25069. Set mandatory = False, ), "strip_debug_symbols": attr.bool( - doc = "Whether to pass '-fstrip' to the zig compiler to remove debug symbols.", + doc = "Whether to force passing '-fstrip' to the zig compiler to remove debug symbols. Bazel's `--strip` flag is also supported globally.", mandatory = False, default = False, ), @@ -262,7 +262,8 @@ def zig_build_impl(ctx, *, kind): translate_c_toolchain = translate_c_exec_group_toolchain(ctx) translatectoolchaininfo = translate_c_toolchain.translatectoolchaininfo if translate_c_toolchain else None - use_cc_common_link = ctx.attr._settings[ZigSettingsInfo].use_cc_common_link + settings = ctx.attr._settings[ZigSettingsInfo] + use_cc_common_link = settings.use_cc_common_link use_test_obj = kind == "zig_test" and use_cc_common_link and semver.gte(zigtoolchaininfo.zig_version, "0.16.0") providers = [] @@ -305,7 +306,7 @@ def zig_build_impl(ctx, *, kind): elif ctx.attr.compiler_runtime == "exclude": args.add("-fno-compiler-rt") - if ctx.attr.strip_debug_symbols: + if ctx.attr.strip_debug_symbols and not settings.strip: args.add("-fstrip") zig_lib_dir( @@ -411,7 +412,7 @@ def zig_build_impl(ctx, *, kind): ) zig_settings( - settings = ctx.attr._settings[ZigSettingsInfo], + settings = settings, args = global_args, ) diff --git a/zig/private/providers/zig_settings_info.bzl b/zig/private/providers/zig_settings_info.bzl index 1f5d9b95..aed0fb03 100644 --- a/zig/private/providers/zig_settings_info.bzl +++ b/zig/private/providers/zig_settings_info.bzl @@ -8,6 +8,7 @@ FIELDS = { "mode": "The Zig build mode.", "use_cc_common_link": "Whether to use cc_common.link to link zig binaries, tests and shared libraries.", "threaded": "The Zig multi- or single-threaded setting.", + "strip": "Whether Zig compile actions should remove debug symbols.", "args": "The collected compiler arguments for all active settings.", } diff --git a/zig/private/settings.bzl b/zig/private/settings.bzl index 331381f7..00bd3b42 100644 --- a/zig/private/settings.bzl +++ b/zig/private/settings.bzl @@ -14,6 +14,30 @@ You can build the settings target to obtain a JSON file capturing all configured Zig build settings. """ +MODE_ARGS = { + "debug": ["-O", "Debug"], + "release_safe": ["-O", "ReleaseSafe"], + "release_small": ["-O", "ReleaseSmall"], + "release_fast": ["-O", "ReleaseFast"], +} + +MODE_VALUES = ["auto", "debug", "release_safe", "release_small", "release_fast"] + +COMPILATION_MODE_TO_MODE = { + "dbg": "debug", + "fastbuild": "debug", + "opt": "release_fast", +} + +THREADED_ARGS = { + "multi": ["-fno-single-threaded"], + "single": ["-fsingle-threaded"], +} + +THREADED_VALUES = ["multi", "single"] + +STRIP_VALUES = ["always", "never", "sometimes"] + ATTRS = { "mode": attr.label( doc = "The build mode setting.", @@ -64,29 +88,16 @@ Use this at your own risk of hitting undefined behaviors. """, mandatory = True, ), + "_bazel_strip": attr.label( + doc = "The selected Bazel --strip option value.", + default = "//zig/settings:strip", + ), } -MODE_ARGS = { - "debug": ["-O", "Debug"], - "release_safe": ["-O", "ReleaseSafe"], - "release_small": ["-O", "ReleaseSmall"], - "release_fast": ["-O", "ReleaseFast"], -} - -MODE_VALUES = ["auto", "debug", "release_safe", "release_small", "release_fast"] - -COMPILATION_MODE_TO_MODE = { - "dbg": "debug", - "fastbuild": "debug", - "opt": "release_fast", -} - -THREADED_ARGS = { - "multi": ["-fno-single-threaded"], - "single": ["-fsingle-threaded"], -} - -THREADED_VALUES = ["multi", "single"] +BazelStripInfo = provider( + doc = "The selected Bazel --strip option value.", + fields = ["strip"], +) def _is_exec_configuration(ctx): return ctx.genfiles_dir.path.find("-exec") != -1 @@ -101,6 +112,16 @@ def _resolve_mode(ctx, mode): return COMPILATION_MODE_TO_MODE[compilation_mode] +def _resolve_strip(ctx, strip): + if strip == "always": + return True + if strip == "never": + return False + if strip == "sometimes": + return ctx.var["COMPILATION_MODE"] == "fastbuild" + + fail("Unrecognized Bazel strip setting {}.".format(strip)) + def _settings_impl(ctx): args = [] @@ -115,12 +136,17 @@ def _settings_impl(ctx): use_cc_common_link = ctx.attr.host_use_cc_common_link[BuildSettingInfo].value if is_exec_configuration else ctx.attr.use_cc_common_link[BuildSettingInfo].value + strip = _resolve_strip(ctx, ctx.attr._bazel_strip[BazelStripInfo].strip) + if strip: + args.append("-fstrip") + args.extend(ctx.attr.host_zigopt[BuildSettingInfo].value if is_exec_configuration else ctx.attr.zigopt[BuildSettingInfo].value) settings_info = ZigSettingsInfo( mode = mode, threaded = threaded, use_cc_common_link = use_cc_common_link, + strip = strip, args = args, ) @@ -141,3 +167,18 @@ settings = rule( attrs = ATTRS, doc = DOC, ) + +def _bazel_strip_impl(ctx): + return [BazelStripInfo(strip = ctx.attr.strip)] + +bazel_strip = rule( + _bazel_strip_impl, + attrs = { + "strip": attr.string( + doc = "The Bazel --strip option value.", + mandatory = True, + values = STRIP_VALUES, + ), + }, + doc = "Captures the selected Bazel --strip option value.", +) diff --git a/zig/settings/BUILD.bazel b/zig/settings/BUILD.bazel index 6f85aba6..417a8985 100644 --- a/zig/settings/BUILD.bazel +++ b/zig/settings/BUILD.bazel @@ -3,6 +3,7 @@ load( "//zig/private:settings.bzl", "MODE_VALUES", "THREADED_VALUES", + "bazel_strip", "settings", ) @@ -19,6 +20,15 @@ settings( zigopt = ":zigopt", ) +bazel_strip( + name = "strip", + strip = select({ + "//zig/config/strip:always": "always", + "//zig/config/strip:never": "never", + "//zig/config/strip:sometimes": "sometimes", + }), +) + bool_flag( name = "use_cc_common_link", build_setting_default = False, diff --git a/zig/tests/rules_test.bzl b/zig/tests/rules_test.bzl index 4ca197c3..4dfd5d8c 100644 --- a/zig/tests/rules_test.bzl +++ b/zig/tests/rules_test.bzl @@ -5,6 +5,7 @@ See https://bazel.build/rules/testing#testing-rules load("@bazel_skylib//lib:sets.bzl", "sets") load("@bazel_skylib//lib:unittest.bzl", "analysistest", "asserts") load("@rules_cc//cc/common:cc_info.bzl", "CcInfo") +load("//zig/private/providers:zig_settings_info.bzl", "ZigSettingsInfo") load( ":util.bzl", "assert_find_unique_surrounded_arguments", @@ -13,6 +14,8 @@ load( "canonical_label", ) +_COMPILATION_MODE = "//command_line_option:compilation_mode" +_STRIP = "//command_line_option:strip" _SETTINGS_USE_CC_COMMON_LINK = canonical_label("@//zig/settings:use_cc_common_link") def _simple_binary_test_impl(ctx): @@ -453,6 +456,99 @@ _strip_debug_symbols_test = analysistest.make( attrs = { "strip_debug_symbols": attr.bool(mandatory = False), }, + config_settings = { + _STRIP: "never", + }, +) + +def _define_bazel_strip_settings_test(*, strip, compilation_mode, expected_strip): + def _test_impl(ctx): + env = analysistest.begin(ctx) + + settings = analysistest.target_under_test(env)[ZigSettingsInfo] + asserts.equals(env, expected_strip, settings.strip) + if expected_strip: + assert_flag_set(env, "-fstrip", settings.args) + else: + assert_flag_unset(env, "-fstrip", settings.args) + + return analysistest.end(env) + + return analysistest.make( + _test_impl, + config_settings = { + _COMPILATION_MODE: compilation_mode, + _STRIP: strip, + }, + ) + +_bazel_strip_settings_always_test = _define_bazel_strip_settings_test( + strip = "always", + compilation_mode = "opt", + expected_strip = True, +) +_bazel_strip_settings_never_test = _define_bazel_strip_settings_test( + strip = "never", + compilation_mode = "fastbuild", + expected_strip = False, +) +_bazel_strip_settings_sometimes_fastbuild_test = _define_bazel_strip_settings_test( + strip = "sometimes", + compilation_mode = "fastbuild", + expected_strip = True, +) +_bazel_strip_settings_sometimes_opt_test = _define_bazel_strip_settings_test( + strip = "sometimes", + compilation_mode = "opt", + expected_strip = False, +) + +def _define_bazel_strip_action_test(*, strip, compilation_mode, expected_strip): + def _test_impl(ctx): + env = analysistest.begin(ctx) + + build = [ + action + for action in analysistest.target_actions(env) + if action.mnemonic == "ZigBuildExe" + ] + asserts.equals(env, 1, len(build), "Target should have one ZigBuildExe action.") + build = build[0] + + if expected_strip: + assert_flag_set(env, "-fstrip", build.argv) + else: + assert_flag_unset(env, "-fstrip", build.argv) + + return analysistest.end(env) + + return analysistest.make( + _test_impl, + config_settings = { + _COMPILATION_MODE: compilation_mode, + _STRIP: strip, + }, + ) + +_bazel_strip_action_always_test = _define_bazel_strip_action_test( + strip = "always", + compilation_mode = "opt", + expected_strip = True, +) +_bazel_strip_action_never_test = _define_bazel_strip_action_test( + strip = "never", + compilation_mode = "fastbuild", + expected_strip = False, +) +_bazel_strip_action_sometimes_fastbuild_test = _define_bazel_strip_action_test( + strip = "sometimes", + compilation_mode = "fastbuild", + expected_strip = True, +) +_bazel_strip_action_sometimes_opt_test = _define_bazel_strip_action_test( + strip = "sometimes", + compilation_mode = "opt", + expected_strip = False, ) def _test_strip_debug_symbols(name): @@ -488,6 +584,59 @@ def _test_strip_debug_symbols(name): name + "-test-strip", ] +def _test_bazel_strip(name): + _bazel_strip_settings_always_test( + name = name + "-settings-always", + target_under_test = "//zig/settings", + size = "small", + ) + _bazel_strip_settings_never_test( + name = name + "-settings-never", + target_under_test = "//zig/settings", + size = "small", + ) + _bazel_strip_settings_sometimes_fastbuild_test( + name = name + "-settings-sometimes-fastbuild", + target_under_test = "//zig/settings", + size = "small", + ) + _bazel_strip_settings_sometimes_opt_test( + name = name + "-settings-sometimes-opt", + target_under_test = "//zig/settings", + size = "small", + ) + _bazel_strip_action_always_test( + name = name + "-action-always", + target_under_test = "//zig/tests/strip_debug_symbols:binary", + size = "small", + ) + _bazel_strip_action_never_test( + name = name + "-action-never", + target_under_test = "//zig/tests/strip_debug_symbols:binary", + size = "small", + ) + _bazel_strip_action_sometimes_fastbuild_test( + name = name + "-action-sometimes-fastbuild", + target_under_test = "//zig/tests/strip_debug_symbols:binary", + size = "small", + ) + _bazel_strip_action_sometimes_opt_test( + name = name + "-action-sometimes-opt", + target_under_test = "//zig/tests/strip_debug_symbols:binary", + size = "small", + ) + + return [ + name + "-settings-always", + name + "-settings-never", + name + "-settings-sometimes-fastbuild", + name + "-settings-sometimes-opt", + name + "-action-always", + name + "-action-never", + name + "-action-sometimes-fastbuild", + name + "-action-sometimes-opt", + ] + def _use_cc_common_link_simple_binary_test_impl(ctx): env = analysistest.begin(ctx) target = analysistest.target_under_test(env) @@ -548,6 +697,7 @@ def rules_test_suite(name): tests += _test_c_sources_binary(name = "c_sources_binary_test") tests += _test_compiler_runtime(name = "compiler_runtime_test") tests += _test_strip_debug_symbols(name = "strip_debug_symbols_test") + tests += _test_bazel_strip(name = "bazel_strip_test") tests += _test_use_cc_common_link_simple_binary(name = "use_cc_common_link_simple_binary_test") native.test_suite( name = name,