In Bazel, stamping is the process of embedding additional information into built
binaries, such as the source control revision or other workspace-related information.
Rules that support stamping typically include an integer stamp attribute, where
1 means “always stamp”, 0 means “never stamp”, and -1 means “use the Bazel
build --stamp flag. This blog post explains how to write a rule that supports
these values.
Quite frankly, the 0 and 1 cases are trivial; the only trick is supporting -1. We can implement this by using a combination of Bazel macros and configurable build attributes
Consider a ruleset for the hypothetical programming language mylang.
First, define a config_setting() that can be used to detect whether --stamp
was set on the comamnd-line:
# @rules_mylang//mylang/private:BUILD.bzl
# Used to detect whether --stamp is specified on command-line. See
# https://github.com/bazelbuild/bazel/issues/11164 for details
config_setting(
name = "private_stamp_detect",
values = {"stamp": "1"},
)
Now, create a rule mylang_binary(), but rather than exposing the rule directly,
wrap the rule with a macro that reads the value of private_stamp_detect from
above:
# mylang_binary.bzl: Contains the definition of the mylang_binary, which
# is wrapped by a macro to support stamp detection
def mylang_binary(name, **kwargs):
_mylang_binary(
name = name,
private_stamp_detect = select({
"//mylang/private:private_stamp_detect": True,
"//conditions:default": False,
}),
**kwargs
)
Then implement the rule as normal, setting stamp based on a combination of
the rule’s stamp attribute and the value of private_stamp_detect:
# mylang_binary.bzl: Contains the definition of the mylang_binary, which
# is wrapped by a macro to support stamp detection
def _impl(ctx):
if ctx.attr.stamp == -1:
stamp = ctx.attr.private_stamp_detect
else:
stamp = (ctx.attr.stamp == 1)
# stamp is a boolean which says whether this rule should perform stamping
...
_mylang_binary = rule(
implementation = _impl,
attrs = {
"stamp": attr.int(default = -1),
"private_stamp_detect": attr.bool()
}
)
Now mylang_binary will stamp binaries by default if users use the
bazel build --stamp command-line optoin.