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 has env!("GIT_HASH"), Go has -ldflags. Ada projects currently need a Makefile or shell script wrapper around gprbuild.
- Precedent exists:
GNAT.Compile_Time already 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 + generated vcs_version.ads with 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.ads
This must be called before every gprbuild invocation, either manually or via a Makefile/CI script.
Any of the proposed options would eliminate this pattern.
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_Timewhich 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:
This would be the most flexible approach and not limited to Git.
Option B — Built-in GNAT package (similar to
GNAT.Compile_Time):Option C — Pre/Post-Build hooks in GPR files:
Rationale
GIT_HASH, Cargo hasenv!("GIT_HASH"), Go has-ldflags. Ada projects currently need a Makefile or shell script wrapper around gprbuild.GNAT.Compile_Timealready embeds non-deterministic build metadata. A git hash is more stable and more useful for identifying deployed binaries.Makefile+updateVersionInfo.sh+ generatedvcs_version.adswith a single built-in mechanism."unknown".Current Workaround
A typical workaround looks like this:
This must be called before every
gprbuildinvocation, either manually or via a Makefile/CI script.Any of the proposed options would eliminate this pattern.