-
Notifications
You must be signed in to change notification settings - Fork 21
Description
Summary
Nearly every Ada project that produces deployable binaries needs to embed VCS information (e.g. Git commit hash) into the binary. Currently this requires an external pre-build step — typically a shell script that generates an Ada spec before calling gprbuild. This is fragile, breaks the self-contained nature of gprbuild, and is a problem every project has to solve independently.
Precedent
GNAT already provides GNAT.Compile_Time which embeds non-deterministic build metadata (date/time) at compile time. A VCS revision is actually more reproducible than a timestamp — the same source state always produces the same hash.
Proposed Solution
Add built-in support for querying VCS information during the build, for example:
Option A — GPR-level external variable from shell command:
Allow a project file to define a scenario variable populated from a shell command:
VERSION := external_command("git rev-parse --short HEAD");
This would be the most flexible approach and not limited to Git.
Option B — Built-in GNAT package (similar to GNAT.Compile_Time):
package GNAT.VCS_Version is
function Revision return String; -- e.g. "a1b2c3d"
function Is_Modified return Boolean; -- true if working tree has uncommitted changes
end GNAT.VCS_Version;Option C — Pre/Post-Build hooks in GPR files:
package Builder is
for Pre_Build_Command use ("./updateVersionInfo.sh");
end Builder;
Rationale
- Widespread need: This is a universally solved problem outside of Ada. CMake has
GIT_HASH, Cargo hasenv!("GIT_HASH"), Go has-ldflags. Ada projects currently need a Makefile or shell script wrapper around gprbuild. - Precedent exists:
GNAT.Compile_Timealready embeds non-deterministic build metadata. A git hash is more stable and more useful for identifying deployed binaries. - Simplicity: A project could replace
Makefile+updateVersionInfo.sh+ generatedvcs_version.adswith a single built-in mechanism. - Graceful fallback: If no VCS is detected (e.g. building from a tarball), the revision could default to
"unknown".
Current Workaround
A typical workaround looks like this:
#!/bin/bash
VERSION=$(git rev-parse --short HEAD)
GIT_MODS="-M"
if output=$(git status --porcelain) && [ -z "$output" ]; then
GIT_MODS=""
fi
echo -e "package VCS_Version is VERSION : constant String := \"${VERSION}${GIT_MODS}\"; end VCS_Version;" > src/vcs_version.adsThis must be called before every gprbuild invocation, either manually or via a Makefile/CI script.
Any of the proposed options would eliminate this pattern.