diff --git a/.bazelrc b/.bazelrc
index 7500e6d5..89dc2064 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -7,8 +7,8 @@ import %workspace%/.bazelrc.flags
# Deleted packages for integration tests.
# To update these lines, execute
# `bazel run @contrib_rules_bazel_integration_test//tools:update_deleted_packages`
-build --deleted_packages=e2e/workspace,e2e/workspace/multiple-sources-and-packages-test,e2e/workspace/multiple-sources-binary,e2e/workspace/simple-binary,e2e/workspace/simple-library,e2e/workspace/simple-test,e2e/workspace/transitive-zig-packages-binary,e2e/workspace/transitive-zig-packages-binary/hello-world,e2e/workspace/transitive-zig-packages-binary/hello-world/data,e2e/workspace/transitive-zig-packages-binary/hello-world/data/hello,e2e/workspace/transitive-zig-packages-binary/hello-world/data/world,e2e/workspace/transitive-zig-packages-binary/hello-world/io,e2e/workspace/zig-package-binary,e2e/workspace/zig-package-binary/data,e2e/workspace/zig-package-binary/io,zig/tests/integration_tests/workspace
-query --deleted_packages=e2e/workspace,e2e/workspace/multiple-sources-and-packages-test,e2e/workspace/multiple-sources-binary,e2e/workspace/simple-binary,e2e/workspace/simple-library,e2e/workspace/simple-test,e2e/workspace/transitive-zig-packages-binary,e2e/workspace/transitive-zig-packages-binary/hello-world,e2e/workspace/transitive-zig-packages-binary/hello-world/data,e2e/workspace/transitive-zig-packages-binary/hello-world/data/hello,e2e/workspace/transitive-zig-packages-binary/hello-world/data/world,e2e/workspace/transitive-zig-packages-binary/hello-world/io,e2e/workspace/zig-package-binary,e2e/workspace/zig-package-binary/data,e2e/workspace/zig-package-binary/io,zig/tests/integration_tests/workspace
+build --deleted_packages=e2e/workspace,e2e/workspace/configure-mode,e2e/workspace/multiple-sources-and-packages-test,e2e/workspace/multiple-sources-binary,e2e/workspace/simple-binary,e2e/workspace/simple-library,e2e/workspace/simple-test,e2e/workspace/transitive-zig-packages-binary,e2e/workspace/transitive-zig-packages-binary/hello-world,e2e/workspace/transitive-zig-packages-binary/hello-world/data,e2e/workspace/transitive-zig-packages-binary/hello-world/data/hello,e2e/workspace/transitive-zig-packages-binary/hello-world/data/world,e2e/workspace/transitive-zig-packages-binary/hello-world/io,e2e/workspace/zig-package-binary,e2e/workspace/zig-package-binary/data,e2e/workspace/zig-package-binary/io,zig/tests/integration_tests/workspace
+query --deleted_packages=e2e/workspace,e2e/workspace/configure-mode,e2e/workspace/multiple-sources-and-packages-test,e2e/workspace/multiple-sources-binary,e2e/workspace/simple-binary,e2e/workspace/simple-library,e2e/workspace/simple-test,e2e/workspace/transitive-zig-packages-binary,e2e/workspace/transitive-zig-packages-binary/hello-world,e2e/workspace/transitive-zig-packages-binary/hello-world/data,e2e/workspace/transitive-zig-packages-binary/hello-world/data/hello,e2e/workspace/transitive-zig-packages-binary/hello-world/data/world,e2e/workspace/transitive-zig-packages-binary/hello-world/io,e2e/workspace/zig-package-binary,e2e/workspace/zig-package-binary/data,e2e/workspace/zig-package-binary/io,zig/tests/integration_tests/workspace
# Load any settings specific to the current user.
# .bazelrc.user should appear in .gitignore so that settings are not shared with team members
diff --git a/docs/rules.md b/docs/rules.md
index 57beb4ff..d763052c 100644
--- a/docs/rules.md
+++ b/docs/rules.md
@@ -23,6 +23,66 @@ zig_binary(name, deps<
| srcs | Other source files required to build the target. | List of labels | optional | [] |
+
+
+## zig_configure
+
+
+zig_configure(name, actual, mode) ++ + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| actual | The target to transition. | Label | required | | +| mode | The build mode setting | String | optional |
"" |
+
+
+
+
+## zig_configure_binary
+
++zig_configure_binary(name, actual, mode) ++ + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| actual | The target to transition. | Label | required | | +| mode | The build mode setting | String | optional |
"" |
+
+
+
+
+## zig_configure_test
+
++zig_configure_test(name, actual, mode) ++ + + +**ATTRIBUTES** + + +| Name | Description | Type | Mandatory | Default | +| :------------- | :------------- | :------------- | :------------- | :------------- | +| name | A unique name for this target. | Name | required | | +| actual | The target to transition. | Label | required | | +| mode | The build mode setting | String | optional |
"" |
+
+
## zig_library
diff --git a/e2e/workspace/configure-mode/BUILD.bazel b/e2e/workspace/configure-mode/BUILD.bazel
new file mode 100644
index 00000000..52933f78
--- /dev/null
+++ b/e2e/workspace/configure-mode/BUILD.bazel
@@ -0,0 +1,124 @@
+load("@bazel_skylib//rules:build_test.bzl", "build_test")
+load("@bazel_skylib//rules:diff_test.bzl", "diff_test")
+load(
+ "@rules_zig//zig:defs.bzl",
+ "zig_binary",
+ "zig_configure",
+ "zig_configure_binary",
+ "zig_configure_test",
+ "zig_library",
+ "zig_test",
+)
+load(":defs.bzl", "run")
+
+zig_library(
+ name = "library",
+ main = "library.zig",
+ tags = ["manual"],
+)
+
+zig_configure(
+ name = "library_debug",
+ actual = ":library",
+ mode = "debug",
+)
+
+zig_configure(
+ name = "library_release_safe",
+ actual = ":library",
+ mode = "release_safe",
+)
+
+genrule(
+ name = "library_debug_symbol",
+ srcs = [":library_debug"],
+ outs = ["library_debug_symbol.txt"],
+ cmd = "$(NM) -j --defined-only $(SRCS) | grep Debug > $(OUTS)",
+ toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"],
+)
+
+genrule(
+ name = "library_release_safe_symbol",
+ srcs = [":library_release_safe"],
+ outs = ["library_release_safe_symbol.txt"],
+ cmd = "$(NM) -j --defined-only $(SRCS) | grep ReleaseSafe > $(OUTS)",
+ toolchains = ["@bazel_tools//tools/cpp:current_cc_toolchain"],
+)
+
+build_test(
+ name = "library_test",
+ targets = [
+ ":library_debug_symbol",
+ ":library_release_safe_symbol",
+ ],
+)
+
+zig_binary(
+ name = "binary",
+ main = "binary.zig",
+ tags = ["manual"],
+)
+
+zig_configure_binary(
+ name = "binary_debug",
+ actual = ":binary",
+ mode = "debug",
+)
+
+zig_configure_binary(
+ name = "binary_release_safe",
+ actual = ":binary",
+ mode = "release_safe",
+)
+
+# NOTE using genrule instead of run fails with Bazel version 5.3.2.
+# It seems that the configuration transition is not handled correctly by
+# genrule in Bazel version 5.3.2.
+
+run(
+ name = "binary_debug_output",
+ out = "binary_debug_output.actual",
+ tool = ":binary_debug",
+)
+
+run(
+ name = "binary_release_safe_output",
+ out = "binary_release_safe_output.actual",
+ tool = ":binary_release_safe",
+)
+
+diff_test(
+ name = "binary_debug_output_test",
+ file1 = ":binary_debug_output.expected",
+ file2 = ":binary_debug_output.actual",
+)
+
+diff_test(
+ name = "binary_release_safe_output_test",
+ file1 = ":binary_release_safe_output.expected",
+ file2 = ":binary_release_safe_output.actual",
+)
+
+zig_test(
+ name = "_test_debug",
+ main = "test_debug.zig",
+ tags = ["manual"],
+)
+
+zig_configure_test(
+ name = "test_debug",
+ actual = "_test_debug",
+ mode = "debug",
+)
+
+zig_test(
+ name = "_test_release_safe",
+ main = "test_release_safe.zig",
+ tags = ["manual"],
+)
+
+zig_configure_test(
+ name = "test_release_safe",
+ actual = "_test_release_safe",
+ mode = "release_safe",
+)
diff --git a/e2e/workspace/configure-mode/binary.zig b/e2e/workspace/configure-mode/binary.zig
new file mode 100644
index 00000000..11309dd5
--- /dev/null
+++ b/e2e/workspace/configure-mode/binary.zig
@@ -0,0 +1,9 @@
+const std = @import("std");
+const builtin = @import("builtin");
+
+pub fn main() void {
+ std.io.getStdOut().writer().print(
+ "{s}\n",
+ .{std.meta.tagName(builtin.mode)},
+ ) catch unreachable;
+}
diff --git a/e2e/workspace/configure-mode/binary_debug_output.expected b/e2e/workspace/configure-mode/binary_debug_output.expected
new file mode 100644
index 00000000..329d484d
--- /dev/null
+++ b/e2e/workspace/configure-mode/binary_debug_output.expected
@@ -0,0 +1 @@
+Debug
diff --git a/e2e/workspace/configure-mode/binary_release_safe_output.expected b/e2e/workspace/configure-mode/binary_release_safe_output.expected
new file mode 100644
index 00000000..9dc92ff9
--- /dev/null
+++ b/e2e/workspace/configure-mode/binary_release_safe_output.expected
@@ -0,0 +1 @@
+ReleaseSafe
diff --git a/e2e/workspace/configure-mode/defs.bzl b/e2e/workspace/configure-mode/defs.bzl
new file mode 100644
index 00000000..e6a153d7
--- /dev/null
+++ b/e2e/workspace/configure-mode/defs.bzl
@@ -0,0 +1,19 @@
+"""Implements a rule to run a binary and write its output to a file."""
+
+def _run_impl(ctx):
+ ctx.actions.run_shell(
+ outputs = [ctx.outputs.out],
+ tools = [ctx.executable.tool],
+ mnemonic = "RunBinary",
+ command = "{} > {}".format(ctx.executable.tool.path, ctx.outputs.out.path),
+ progress_message = "Running binary to create %{output}",
+ )
+ return [DefaultInfo(files = depset([ctx.outputs.out]))]
+
+run = rule(
+ _run_impl,
+ attrs = {
+ "out": attr.output(),
+ "tool": attr.label(executable = True, cfg = "exec"),
+ },
+)
diff --git a/e2e/workspace/configure-mode/library.zig b/e2e/workspace/configure-mode/library.zig
new file mode 100644
index 00000000..60f31612
--- /dev/null
+++ b/e2e/workspace/configure-mode/library.zig
@@ -0,0 +1,8 @@
+const std = @import("std");
+const builtin = @import("builtin");
+
+comptime {
+ @export(internalName, .{ .name = @tagName(builtin.mode), .linkage = .Strong });
+}
+
+fn internalName() callconv(.C) void {}
diff --git a/e2e/workspace/configure-mode/test_debug.zig b/e2e/workspace/configure-mode/test_debug.zig
new file mode 100644
index 00000000..ffaec1b8
--- /dev/null
+++ b/e2e/workspace/configure-mode/test_debug.zig
@@ -0,0 +1,6 @@
+const std = @import("std");
+const builtin = @import("builtin");
+
+test "mode is Debug" {
+ try std.testing.expectEqual(std.builtin.Mode.Debug, builtin.mode);
+}
diff --git a/e2e/workspace/configure-mode/test_release_safe.zig b/e2e/workspace/configure-mode/test_release_safe.zig
new file mode 100644
index 00000000..7b30b593
--- /dev/null
+++ b/e2e/workspace/configure-mode/test_release_safe.zig
@@ -0,0 +1,6 @@
+const std = @import("std");
+const builtin = @import("builtin");
+
+test "mode is ReleaseSafe" {
+ try std.testing.expectEqual(std.builtin.Mode.ReleaseSafe, builtin.mode);
+}
diff --git a/zig/BUILD.bazel b/zig/BUILD.bazel
index d31b2b02..d07e4f89 100644
--- a/zig/BUILD.bazel
+++ b/zig/BUILD.bazel
@@ -38,6 +38,7 @@ bzl_library(
visibility = ["//visibility:public"],
deps = [
"//zig/private:zig_binary",
+ "//zig/private:zig_configure",
"//zig/private:zig_library",
"//zig/private:zig_package",
"//zig/private:zig_test",
diff --git a/zig/defs.bzl b/zig/defs.bzl
index e7c82ada..0be601ec 100644
--- a/zig/defs.bzl
+++ b/zig/defs.bzl
@@ -4,8 +4,17 @@ load("//zig/private:zig_binary.bzl", _zig_binary = "zig_binary")
load("//zig/private:zig_library.bzl", _zig_library = "zig_library")
load("//zig/private:zig_package.bzl", _zig_package = "zig_package")
load("//zig/private:zig_test.bzl", _zig_test = "zig_test")
+load(
+ "//zig/private:zig_configure.bzl",
+ _zig_configure = "zig_configure",
+ _zig_configure_binary = "zig_configure_binary",
+ _zig_configure_test = "zig_configure_test",
+)
zig_binary = _zig_binary
zig_library = _zig_library
zig_package = _zig_package
zig_test = _zig_test
+zig_configure = _zig_configure
+zig_configure_binary = _zig_configure_binary
+zig_configure_test = _zig_configure_test
diff --git a/zig/private/BUILD.bazel b/zig/private/BUILD.bazel
index 78b29974..82010cea 100644
--- a/zig/private/BUILD.bazel
+++ b/zig/private/BUILD.bazel
@@ -48,6 +48,16 @@ bzl_library(
],
)
+bzl_library(
+ name = "zig_configure",
+ srcs = ["zig_configure.bzl"],
+ visibility = ["//zig:__subpackages__"],
+ deps = [
+ ":settings",
+ "@bazel_skylib//lib:paths",
+ ],
+)
+
bzl_library(
name = "resolved_toolchain",
srcs = ["resolved_toolchain.bzl"],
@@ -76,6 +86,7 @@ filegroup(
":toolchains_repo.bzl",
":versions.bzl",
":zig_binary.bzl",
+ ":zig_configure.bzl",
":zig_library.bzl",
":zig_package.bzl",
":zig_test.bzl",
diff --git a/zig/private/settings.bzl b/zig/private/settings.bzl
index 5b63fc67..4ddef3c1 100644
--- a/zig/private/settings.bzl
+++ b/zig/private/settings.bzl
@@ -20,6 +20,8 @@ MODE_ARGS = {
"release_fast": ["-O", "ReleaseFast"],
}
+MODE_VALUES = ["debug", "release_safe", "release_small", "release_fast"]
+
def _settings_impl(ctx):
args = []
diff --git a/zig/private/zig_configure.bzl b/zig/private/zig_configure.bzl
new file mode 100644
index 00000000..5debd504
--- /dev/null
+++ b/zig/private/zig_configure.bzl
@@ -0,0 +1,105 @@
+"""Implementation of the zig_configure rule."""
+
+load("@bazel_skylib//lib:paths.bzl", "paths")
+load("//zig/private:settings.bzl", "MODE_VALUES")
+
+DOC = """\
+"""
+
+def _zig_transition_impl(settings, attr):
+ result = {}
+ if attr.mode:
+ result["//zig/settings:mode"] = attr.mode
+ return result
+
+_zig_transition = transition(
+ implementation = _zig_transition_impl,
+ inputs = [],
+ outputs = ["//zig/settings:mode"],
+)
+
+def _make_attrs(*, executable, test):
+ return {
+ "actual": attr.label(
+ doc = "The target to transition.",
+ cfg = _zig_transition,
+ executable = executable,
+ mandatory = True,
+ ),
+ "mode": attr.string(
+ doc = "The build mode setting",
+ mandatory = False,
+ values = MODE_VALUES,
+ ),
+ "_whitelist_function_transition": attr.label(
+ default = "@bazel_tools//tools/whitelists/function_transition_whitelist",
+ ),
+ }
+
+_FORWARD_PROVIDERS = [
+]
+
+def _make_zig_configure_rule(*, executable, test):
+ _executable = executable
+ _test = test
+
+ def _zig_configure_impl(ctx):
+ executable = _executable
+ test = _test
+
+ if type(ctx.attr.actual) == "list":
+ if len(ctx.attr.actual) == 1:
+ actual = ctx.attr.actual[0]
+ else:
+ fail("INTERNAL ERROR: Unexpected 1:n transition encountered.")
+ else:
+ actual = ctx.attr.actual
+
+ providers = []
+ for provider in _FORWARD_PROVIDERS:
+ if provider in actual:
+ providers.append(actual[provider])
+
+ if executable:
+ # Executable rules must create the returned executable artifact
+ # themselves. This is required so that Bazel can create the
+ # corresponding runfiles tree or manifest next to the produced
+ # executable artifact.
+ # See https://github.com/bazelbuild/bazel/issues/4170
+
+ actual_executable = actual[DefaultInfo].files_to_run.executable
+ (_, extension) = paths.split_extension(actual_executable.path)
+ executable = ctx.actions.declare_file(
+ ctx.label.name + extension,
+ )
+ ctx.actions.symlink(
+ output = executable,
+ target_file = actual_executable,
+ is_executable = True,
+ )
+
+ # TODO[AH] Add a data attribute for executable rules.
+ runfiles = ctx.runfiles(files = [executable, actual_executable])
+ runfiles = runfiles.merge(actual[DefaultInfo].default_runfiles)
+
+ providers.append(DefaultInfo(
+ executable = executable,
+ files = depset(direct = [executable]),
+ runfiles = runfiles,
+ ))
+ else:
+ providers.append(actual[DefaultInfo])
+
+ return providers
+
+ return rule(
+ _zig_configure_impl,
+ attrs = _make_attrs(executable = executable, test = test),
+ doc = DOC,
+ executable = executable,
+ test = test,
+ )
+
+zig_configure = _make_zig_configure_rule(executable = False, test = False)
+zig_configure_binary = _make_zig_configure_rule(executable = True, test = False)
+zig_configure_test = _make_zig_configure_rule(executable = True, test = True)