-
-
Notifications
You must be signed in to change notification settings - Fork 88
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6f52c77
commit de081fb
Showing
9 changed files
with
401 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
"""A small utility module dedicated to detecting whether or not the `--stamp` flag is enabled | ||
This module can be removed likely after the following PRs ar addressed: | ||
- https://github.com/bazelbuild/bazel/issues/11164 | ||
""" | ||
|
||
StampSettingInfo = provider( | ||
doc = "Information about the `--stamp` command line flag", | ||
fields = { | ||
"value": "bool: Whether or not the `--stamp` flag was enabled", | ||
}, | ||
) | ||
|
||
def _stamp_build_setting_impl(ctx): | ||
return StampSettingInfo(value = ctx.attr.value) | ||
|
||
_stamp_build_setting = rule( | ||
doc = "Adapter from our config_setting to a Provider for downstream rules", | ||
implementation = _stamp_build_setting_impl, | ||
attrs = { | ||
"value": attr.bool( | ||
doc = "The default value of the stamp build flag", | ||
mandatory = True, | ||
), | ||
}, | ||
) | ||
|
||
def stamp_build_setting(name, visibility = ["//visibility:public"]): | ||
native.config_setting( | ||
name = "stamp_detect", | ||
values = {"stamp": "1"}, | ||
visibility = visibility, | ||
) | ||
|
||
_stamp_build_setting( | ||
name = name, | ||
value = select({ | ||
":stamp_detect": True, | ||
"//conditions:default": False, | ||
}), | ||
visibility = visibility, | ||
) | ||
|
||
def is_stamping_enabled(attr): | ||
"""Determine whether or not build stamping is enabled. | ||
Args: | ||
attr (struct): A rule's struct of attributes (`ctx.attr`) | ||
Returns: | ||
bool: The stamp value | ||
""" | ||
stamp_num = getattr(attr, "stamp", -1) | ||
if stamp_num > 0: | ||
return True | ||
elif stamp_num == 0: | ||
return False | ||
elif stamp_num < 0: | ||
stamp_flag = getattr(attr, "_stamp_flag", None) | ||
return stamp_flag[StampSettingInfo].value if stamp_flag else False | ||
else: | ||
fail("Unexpected `stamp` value: {}".format(stamp_num)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
"""Version Stamping | ||
Bazel is generally only a build tool, and is unaware of your version control system. | ||
However, when publishing releases, you may want to embed version information in the resulting distribution. | ||
Bazel supports this with the concept of a "Workspace status" which is evaluated before each build. | ||
See [the Bazel workspace status docs](https://docs.bazel.build/versions/master/user-manual.html#workspace_status) | ||
To stamp a build, you pass the `--stamp` argument to Bazel. | ||
> Note: https://github.com/bazelbuild/bazel/issues/14341 proposes that Bazel enforce this by | ||
> only giving constant values to rule implementations when stamping isn't enabled. | ||
Stamping is typically performed on a later action in the graph, like on a linking or packaging rule (`pkg_*`). | ||
This means that a changed status variable only causes that action, not re-compilation and thus does not cause cascading re-builds. | ||
Bazel provides a couple of statuses by default, such as `BUILD_EMBED_LABEL` which is the value of the `--embed_label` | ||
argument, as well as `BUILD_HOST` and `BUILD_USER`. You can supply more with the workspace status script, see below. | ||
Some rules accept an attribute that uses the status variables. | ||
They will usually say something like "subject to stamp variable replacements". | ||
## Stamping with a Workspace status script | ||
To define additional statuses, pass the `--workspace_status_command` argument to `bazel`. | ||
The value of this flag is a path to a script that prints space-separated key/value pairs, one per line, such as | ||
```bash | ||
#!/usr/bin/env bash | ||
echo STABLE_GIT_COMMIT $(git rev-parse HEAD) | ||
``` | ||
> For a more full-featured script, take a look at the [bazel_stamp_vars in Angular] | ||
Make sure you set the executable bit, eg. `chmod 755 tools/bazel_stamp_vars.sh`. | ||
> **NOTE** keys that start with `STABLE_` will cause a re-build when they change. | ||
> Other keys will NOT cause a re-build, so stale values can appear in your app. | ||
> Non-stable (volatile) keys should typically be things like timestamps that always vary between builds. | ||
You might like to encode your setup using an entry in `.bazelrc` such as: | ||
```sh | ||
# This tells Bazel how to interact with the version control system | ||
# Enable this with --config=release | ||
build:release --stamp --workspace_status_command=./tools/bazel_stamp_vars.sh | ||
``` | ||
[bazel_stamp_vars in Angular]: https://github.com/angular/angular/blob/master/tools/bazel_stamp_vars.sh | ||
## Writing a custom rule which reads stamp variables | ||
First, load the helpers: | ||
```starlark | ||
load("@aspect_bazel_lib//lib:stamping.bzl", "STAMP_ATTRS", "maybe_stamp") | ||
``` | ||
In your rule implementation, call the `maybe_stamp` function. | ||
If it returns `None` then this build doesn't have stamping enabled. | ||
Otherwise you can use the returned struct to access two files. | ||
The stable_status file contains the keys which were prefixed with `STABLE_`, see above. | ||
The volatile_status file contains the rest of the keys. | ||
```starlark | ||
def _rule_impl(ctx): | ||
args = ctx.actions.args() | ||
inputs = [] | ||
stamp = maybe_stamp(ctx) | ||
if stamp: | ||
args.add("--volatile_status_file", stamp.volatile_status) | ||
args.add("--stable_status_file", stamp.stable_status) | ||
inputs.extend([stamp.volatile_status, stamp.stable_status]) | ||
# ... call actions which parse the stamp files and do something with the values ... | ||
``` | ||
Finally, in the declaration of the rule, include the `STAMP_ATTRS` to declare attributes | ||
which are read by that `maybe_stamp` function above. | ||
```starlark | ||
my_stamp_aware_rule = rule( | ||
attrs = dict({ | ||
# ... my attributes ... | ||
}, **STAMP_ATTRS), | ||
) | ||
``` | ||
""" | ||
|
||
load("//lib/private:stamping.bzl", "is_stamping_enabled") | ||
|
||
def maybe_stamp(ctx): | ||
"""Provide the bazel-out/stable_status.txt and bazel-out/volatile_status.txt files. | ||
Args: | ||
ctx: The rule context | ||
Returns: | ||
If stamping is not enabled for this rule under the current build, returns None. | ||
Otherwise, returns a struct containing (volatile_status_file, stable_status_file) keys | ||
""" | ||
if is_stamping_enabled(ctx.attr): | ||
return struct( | ||
volatile_status_file = ctx.version_file, | ||
stable_status_file = ctx.info_file, | ||
) | ||
|
||
return None | ||
|
||
STAMP_ATTRS = { | ||
"stamp": attr.int( | ||
doc = """\ | ||
Whether to encode build information into the output. Possible values: | ||
- `stamp = 1`: Always stamp the build information into the output, even in | ||
[--nostamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) builds. | ||
This setting should be avoided, since it is non-deterministic. | ||
It potentially causes remote cache misses for the target and | ||
any downstream actions that depend on the result. | ||
- `stamp = 0`: Never stamp, instead replace build information by constant values. | ||
This gives good build result caching. | ||
- `stamp = -1`: Embedding of build information is controlled by the | ||
[--[no]stamp](https://docs.bazel.build/versions/main/user-manual.html#flag--stamp) flag. | ||
Stamped targets are not rebuilt unless their dependencies change. | ||
""", | ||
default = -1, | ||
values = [1, 0, -1], | ||
), | ||
"_stamp_flag": attr.label( | ||
doc = "Internal use only. A setting used to determine whether or not the `--stamp` flag is enabled.", | ||
default = Label("//lib:stamp"), | ||
), | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
load(":stamp_aware_rule.bzl", "my_stamp_aware_rule") | ||
load("//lib:run_binary.bzl", "run_binary") | ||
|
||
my_stamp_aware_rule( | ||
name = "test_stamped", | ||
out = "always", | ||
stamp = 1, | ||
) | ||
|
||
my_stamp_aware_rule( | ||
name = "test_unstamped", | ||
out = "never", | ||
stamp = 0, | ||
) | ||
|
||
my_stamp_aware_rule( | ||
name = "test_default", | ||
out = "default", | ||
) | ||
|
||
sh_binary( | ||
name = "stamper", | ||
srcs = ["stamper.sh"], | ||
) | ||
|
||
# Build this with --stamp enabled to see your username in the resulting output file | ||
run_binary( | ||
name = "run_stamper", | ||
outs = ["stamped"], | ||
args = ["$(location stamped)"], | ||
tool = "stamper", | ||
) |
Oops, something went wrong.