Stamping is the act of embedding build metadata into the product that we ship to customers. It can help with issue diagnosis, analytics, and so on. Conveniently, Bazel offers us a first-class solution, and it is very easy to take advantage of it in the context of iOS apps.
Workspace status script
The first step in enabling stamping is to create a workspace status script. For example, we can create a script that emits the current Git commit hash:
#!/usr/bin/env bash
set -eu -o pipefail
echo "STABLE_GIT_COMMIT $(git rev-parse HEAD)"
Now we need to tell Bazel to execute the script:
--workspace_status_command=./tools/workspace_status.sh
Reading the value at build time
For iOS apps, or really any Apple platform app, it is usually best to embed this data in a plist file so we can read it at runtime. First, we use a genrule to read the workspace status data and materialize a plist file:
genrule(
name = "commit_plist",
outs = ["Commit.plist"],
cmd = """
commit="$$(sed -n 's/^STABLE_GIT_COMMIT //p' bazel-out/stable-status.txt)"
plutil -convert xml1 -o "$@" - <<EOF
{
"GIT_COMMIT": "$${commit}"
}
EOF
""",
stamp = True,
)
From there, it is just a matter of adding this target to the infoplists attribute of any Apple platform application target, like ios_application. Because rules_apple performs plist merging, this value will end up in the final Info.plist file that we ship in the app bundle.
A word on the stamp attribute
Notice the stamp = True attribute on the genrule? That is what allows the genrule action to access bazel-out/stable-status.txt and bazel-out/volatile-status.txt.
Without it, the action should not rely on those files being present. In this example, the important part is stamping the genrule that materializes the plist.
This is separate from the stamp attribute you may see on Apple rules like ios_application, where stamping controls whether build information is encoded into the binary. For this plist-based approach, we do not need to rely on link stamping at the application target level.
Reading the value at runtime
Because the value ends up in Info.plist, we can read it at runtime through the Bundle / NSBundle API.
Conclusion
There you have it: an easy way to stamp iOS builds. I hope it helps you discover and fix bugs in production more easily.