| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- # Part of the Carbon Language project, under the Apache License v2.0 with LLVM
- # Exceptions. See /LICENSE for license information.
- # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- """Rule to expand Bazel templates with version and build information.
- This rule takes a source code template and turns that into a specific source
- code output, substituting version information and build information from Bazel's
- `stable-status.txt` and `volatile-status.txt` produced by the
- `workpsace_status_command` during the build. When stamping is disabled, the
- build information is replaced with constant values to provide better caching.
- The template files should use Python's "template strings" syntax[1]. These rules
- provide a fixed set of keys whose values will be substituted, and those keys
- will always be substituted with something. They will have the value in the
- stable status file if present, otherwise the value in the volatile status file
- if present, otherwise the value "unknown". When reading keys from the status
- files, a prefix of `STABLE_` will be removed from the key if present.
- [1]: https://docs.python.org/3/library/string.html#template-strings
- The substituted keys, and any guidance on values:
- - `VERSION` (the version string for Carbon)
- - `BUILD_EMBED_LABEL` (value of --embed_label)
- - `BUILD_HOST` (the name of the host machine running the build)
- - `BUILD_USER` (the name of the user running the build)
- - `GIT_COMMIT_SHA` (output of `git parse-rev --short HEAD` or `unknown`)
- - `GIT_DIRTY_SUFFIX` (`.dirty` if dirty client state or `` if unknown)
- - `BUILD_TIMESTAMP` (the time of the build in seconds since the Unix Epoch)
- - `ATTRIBUTE` (an optional attribute to apply to definitions, defaults to empty)
- """
- load(":compute_version.bzl", "compute_version")
- _STAMP_DOC = """
- Follows behavior of the common 'stamp' attributes on rules. Set to 1 or 0 to
- force stamping with actual build info on or off respectively, and to -1 to
- follow the value of the command line flag `--stamp`.
- """
- def _is_exec_config(ctx):
- """Detect if this is the exec configuration, previously known as "host".
- Sadly, there is not yet a supported way to detect this so replicate the
- hacks others currently use. Bazel issue:
- https://github.com/bazelbuild/bazel/issues/14444
- """
- return "-exec" in ctx.bin_dir.path or "/host/" in ctx.bin_dir.path
- def _expand_version_build_info_impl(ctx):
- """Generates a file from a template, substituting version and build info."""
- inputs = [ctx.file.template]
- # The substitutions provided and their default values.
- substitutions = {
- "BUILD_EMBED_LABEL": "unknown",
- "BUILD_HOST": "unknown",
- "BUILD_TIMESTAMP": "unknown",
- "BUILD_USER": "unknown",
- "GIT_COMMIT_SHA": "unknown",
- "GIT_DIRTY_SUFFIX": "",
- "MAKE_WEAK": "0",
- "VERSION": compute_version(ctx),
- }
- substitutions.update(ctx.attr.substitutions)
- arguments = [
- "--template=" + ctx.file.template.path,
- "--output=" + ctx.outputs.out.path,
- ] + [
- "--substitution=" + key + "=" + value
- for key, value in substitutions.items()
- ]
- # We only want to allow stamping outside of the exec configuration.
- if not _is_exec_config(ctx):
- # Look at the attribute.
- stamp = ctx.attr.stamp
- # If requested, use the command line flag to select.
- if stamp == -1:
- # Set the default from `--stamp` / `--nostamp` command line flag,
- # which we detect through a macro and `config_setting`, and pipe
- # through an attribute.
- stamp = 1 if ctx.attr.internal_stamp_flag_detect else 0
- # Add the status files if stamping.
- if stamp == 1:
- inputs += [
- ctx.info_file,
- ctx.version_file,
- ]
- arguments += [
- "--status-file=" + ctx.info_file.path,
- "--status-file=" + ctx.version_file.path,
- ]
- ctx.actions.run(
- inputs = inputs,
- outputs = [ctx.outputs.out],
- executable = ctx.executable._gen_tmpl_tool,
- arguments = arguments,
- progress_message = "Generating templated source file: " +
- ctx.outputs.out.short_path,
- )
- expand_version_build_info_internal = rule(
- implementation = _expand_version_build_info_impl,
- attrs = {
- "internal_stamp_flag_detect": attr.bool(default = False),
- "out": attr.output(mandatory = True),
- "stamp": attr.int(values = [-1, 0, 1], default = -1, doc = _STAMP_DOC),
- "substitutions": attr.string_dict(
- doc = "Extra substitutions, potentially overriding defaults.",
- ),
- "template": attr.label(
- allow_single_file = True,
- ),
- "_alpha_number_flag": attr.label(default = ":alpha_number"),
- "_beta_number_flag": attr.label(default = ":beta_number"),
- "_gen_tmpl_tool": attr.label(
- default = Label("//bazel/version:gen_tmpl"),
- allow_files = True,
- executable = True,
- cfg = "exec",
- ),
- "_nightly_date_flag": attr.label(default = ":nightly_date"),
- "_pre_release_flag": attr.label(default = ":pre_release"),
- "_rc_number_flag": attr.label(default = ":rc_number"),
- "_release_flag": attr.label(default = ":release"),
- },
- )
- # We need a macro wrapping the rule so that we can inject a select that observes
- # the `--stamp` command-line value and use that when needed.
- def expand_version_build_info(name, **kwargs):
- expand_version_build_info_internal(
- name = name,
- internal_stamp_flag_detect = select({
- "//bazel/version:internal_stamp_flag_detect": True,
- "//conditions:default": False,
- }),
- **kwargs
- )
|