I would use a
genrule that generates a .h file you can #include. 'echo "#define MY_SHELL_COMMAND \"$(git describe --abbrev=4 --dirty --always --tags)\"" > $@' or so for the command. However, I suspect Bazel's caching behavior is going to get in your way for that particular command. It's either going to never re-run the command or you'll have to include glob(['.git/**']) or something in the srcs and then it will result in things being rebuilt unnecessarily.
For that command, you should probably use the workspace status functionality instead. Bazel will handle re-running the command on each `bazel build` and using the new output for any binaries being re-linked, but not rebuilding binaries just because the output from that command changed. tools/buildstamp/get_workspace_status in the Bazel source tree is a good example to start from. Put a "build --workspace_status_command=scripts/ci/build_status_command.sh" (or wherever you put it in your source tree) line in your tools/bazel.rc to use it, and change the `git rev-parse` command to your command instead.
When using the builtin workspace status feature, Bazel will automatically decide which rules actually get the information included and which ones don't. You can override those decisions via the --stamp command-line flag and the stamp attribute on various rules. When you have a rule compiled without stamping (cc_test rules by default, for example), the linkstamp source file won't be linked in at all. I deal with that using weak symbols which aren't defined for rules without stamping, but there might be nicer ways to do it.
To get the information into C++ code, create a cc_library with the linkstamp attribute set to the name of a C++ source file which will be compiled with BUILD_SCM_REVISION, BUILD_SCM_STATUS, and various other macros defined to the appropriate values, and then depend on that library from your binary. Here's a more concrete example of that, because I mostly figured it all out via trial and error which took a bit:
linkstamping/BUILD:
cc_library(
name = 'build_revision',
hdrs = [
'build_revision.h',
],
srcs = [
'build_revision.cc',
],
linkstamp = 'build_revision_linkstamp.cc',
)
linkstamping/build_revision_linkstamp.cc:
extern const char kBuildRevision[];
const char kBuildRevision[] = BUILD_SCM_REVISION;
extern const char kBuildStatus[];
const char kBuildStatus[] = BUILD_SCM_STATUS;
linkstamping/build_revision.h:
const char *BuildRevision();
const char *BuildStatus();
linkstamping/build_revision.cc:
extern const char kBuildRevision[] __attribute__((weak));
extern const char kBuildStatus[] __attribute__((weak));
const char *BuildRevision() {
if (&kBuildRevision == nullptr) return "unknown";
return kBuildRevision;
}
const char *BuildStatus() {
if (&kBuildStatus == nullptr) return "unknown";
return kBuildStatus;
}