bazelbuild / bazel

a fast, scalable, multi-language and extensible build system
https://bazel.build
Apache License 2.0
22.97k stars 4.03k forks source link

stamp parameter for genrule is undocumented #4942

Open dfabulich opened 6 years ago

dfabulich commented 6 years ago

https://docs.bazel.build/versions/master/be/general.html#genrule

genrule(name, srcs, outs, cmd, compatible_with, deprecation, distribs,
  executable, features, licenses, local, message, output_licenses,
  output_to_bindir, restricted_to, tags, testonly, tools, visibility)

It doesn't mention the stamp parameter, used together with --workspace_status_command to add bazel-out/stable-status.txt and bazel-out/volatile-status.txt as dependencies.

kellycampbell commented 4 years ago

This looks like a duplicate of #4219

Also, related to this documentation issue, it's unclear from https://docs.bazel.build/versions/master/user-manual.html#workspace_status how to make use of the variables in those files. I tried using them in genrule in a similar fashion to how rules_docker makes them templated, e.g. genrule outs = ["release-{BUILD_TIMESTAMP}.tar.gz"] but that doesn't work, so some example or explanation that you have to read and use those files directly would be good.

rules_docker's source uses ctx.info_file, and ctx.version_file but these aren't documented publicly. SkylarkRuleContextApi.java has them set to documented = false. Is there a reason that isn't set to true?

Additionally, BazelGenRuleRule.java has a TODO saying that stamping doesn't seem to work, but I don't think that's true now so it could be removed.

dfr commented 1 year ago

I used the stable-status.txt file to embed a git hash into my build:

genrule(
    name = "gen_version",
    srcs = ["version.h.in"],
    outs = ["version.h"],
    cmd_bash = """
        h=$$(grep ^STABLE_GIT_COMMIT bazel-out/stable-status.txt | cut -d' ' -f2); \
        sed -e 's/%%GIT_COMMIT%%/'$$h'/' < $< > $@
    """,
    stamp = 1,
)

The STABLE_GIT_COMMIT value comes from a script which I'm using with the workspace_status_command flag:

$ cat .bazelrc
build --workspace_status_command=tools/git-status.sh
$ cat tools/git-status.sh
#! /bin/sh
echo "STABLE_GIT_COMMIT $(git rev-parse HEAD)"

There are probably more elegant ways to do this but this works for me. Without stamp = 1 it is flaky which I only discovered by reading old issues found with Google. The stable attribute is mentioned in https://bazel.build/docs/user-manual#workspace-status but would probably be easier to discover if it was documented in genrule (and other rules where it works).

pauldraper commented 1 year ago

The authoritative guide to stamping:

Workspace status

Bazel invokes the workspace status command for each build. This command can output variables to stdout in KEY VALUE format.

Files

Bazel places variables in two files in KEY VALUE format.

bazel-out/volatile-status.txt is special in that it is not considered when calculating cache keys.

Rules

It is up to each rule if any how they use these files (ctx.info_file and ctx.version_file respectively).

Many rules have a stamp attribute that is 0 (disabled), 1 (enabled), or -1 (follow the CLI option --stamp). (It's possible but difficult for Starlark rules to implement stamp = -1 behavior.)

Genrule

I tried using them in genrule in a similar fashion to how rules_docker makes them templated, e.g. genrule outs = ["release-{BUILD_TIMESTAMP}.tar.gz"] but that doesn't work, so some example or explanation that you have to read and use those files directly would be good

You have to read from bazel-out/stable-status.txt and bazel-out/volatile-status.txt in the genrule command itself.

arohner commented 1 year ago

Does this mean that genrules using stamp always read both stable and volatile status, unconditionally? If I want to write a rule to only read volatile status I need a full rule?

pauldraper commented 1 year ago

Does this mean that genrules using stamp always read both stable and volatile status, unconditionally?

Correct.

If I want to write a helper rule to only read volatile status I need a full rule?

Yes.

Though, I often write a rule to extract a single value anyway.

status(
  name = "example",
  key = "FOO",
  type = "volatile",
)

And then pass that to downstream rules, for better cache hits.

github-actions[bot] commented 1 month ago

Thank you for contributing to the Bazel repository! This issue has been marked as stale since it has not had any activity in the last 1+ years. It will be closed in the next 90 days unless any other activity occurs. If you think this issue is still relevant and should stay open, please post any comment here and the issue will no longer be marked as stale.

sbussard commented 2 weeks ago

bump