We have a code generator that takes random seed as an input. If no seed specified, it will randomly pick a random seed, which means the outcome is not deterministic:
# generated_code1.h and generated_code2.h are almost always different
my-code-gen -o generated_code1.h
my-code-gen -o generated_code2.h
On the other hand,
# generated_code3.h and generated_code4.h are always the same
my-code-gen --seed 1234 -o generated_code3.h
my-code-gen --seed 1234 -o generated_code4.h
Our first attempt to create a target for the generated code was:
genrule(
name = "generated_code",
srcs = [],
outs = ["generated_code.h"],
cmd = "my-code-gen -o $@", # Notice that seed not specified
)
However, we think this breaks the hermeticity of targets depending on :generated_code
.
So we ended up implementing a customized rule and use build_setting
(i.e. configuration) to configure the seed for the invocation of my-code-gen
.
This makes it possible to specify the seed from CLI to any targets that depends on the generated code, e.g.
bazel build :generated_code --//:code-gen-seed=1234
bazel build :binary --//:code-gen-seed=1234
My questions are:
- Consider the
genrule
definition above, it is callingmy-code-gen
without--seed
which results in non-deterministic output. Does that mean non-hermetic? What is the cost of breaking hermeticity? (e.g. what trouble would it cause in the future?) - I've found
--action_env
as an alternative tobuild_setting
, which also allow us to pass a seed value from CLI tomy-code-gen
. Compared tobuild_setting
, what is the preferred approach in our case?