- Tue 21 February 2017
- gprbuild
- Jacob Sparre Andersen
- #version control, #code generation, #gprbuild
Would you like your executable files to be able to tell which commit in your version control system it corresponds to?
You can do it by:
- Creating a program (in this example a shell script), which generates Ada source files reporting the version control status.
- Defining a "language" in Gprbuild, which corresponds to reading out the version control status, using the program from the previous step.
- Write a project file, which builds "source files" in this language.
Generating an Ada package from Mercurial status information
Install hg_revision_to_ada - listed below - somewhere in your execution path.
#! /bin/bash
#-----------------------------------------------------------------------------
# Usage:
function usage() {
echo "Usage:"
echo " $0 --compile <source file>"
echo " $0 --dependencies <source file>"
echo
}
#-----------------------------------------------------------------------------
# Compile:
function compile() {
if [ -z "$1" ]; then
return 1
else
local source="$1"
fi
if [ -s "${source}" ]; then
local package_name=$(cat "${source}")
else
return 2
fi
local source_directory="$(dirname "${source}")"
local target="${source%.hg_status}.ads"
local buffer="$(mktemp)"
local hg_revision="$(cd "${source_directory}" && hg tip --template '{node}' 2>/dev/null)"
local hg_modifier="$(if [ $(cd "${source_directory}" && hg status 2>/dev/null | wc -c) -gt 0 ]; then
echo "plus changes"
else
echo "as committed"
fi)"
if [ -z "${hg_revision}" ]; then
hg_revision="Warning: Not built from a Mercurial check-out. "
hg_modifier=""
fi
(
echo 'package '${package_name}' is'
echo ' Revision : constant String (1 .. 53) :='
echo ' "'"${hg_revision}"' '"${hg_modifier}"'";'
echo 'end '${package_name}';'
) > "${buffer}" ; mv "${buffer}" "${target}"
}
#-----------------------------------------------------------------------------
# Dependencies:
function report_dependencies() {
echo "Dependency reporting not implemented yet." 1>&2
return 3
}
#-----------------------------------------------------------------------------
# Bad command-line arguments:
function bad_arguments() {
(
echo "Call:"
echo " $0 $*"
echo
usage
) 1>&2
exit 1
}
#-----------------------------------------------------------------------------
case "$1" in
"--help") usage ;;
"--compile") compile "$2" ;;
"--dependencies") report_dependencies "$2" ;;
*) bad_arguments $@ ;;
esac
#-----------------------------------------------------------------------------
With this tool, you can have a source file giving the name and file name for the Ada package containing the version control status information:
$ cat src/version_control_status.hg_status
Version_Control_Status
$ hg_revision_to_ada --compile src/version_control_status.hg_status
$ cat version_control_status.ads
package Version_Control_Status is
Revision : constant String (1 .. 53) :=
"76dc54636c40d2c5043575dd5809582a0bd8e703 as committed";
end Version_Control_Status;
$
Defining a new programming language in Gprbuild
We make the file `/usr/share/gprconfig/hg_revision.xml` contain this:
<?xml version="1.0" ?>
<gprconfig>
<compiler_description>
<name>Mercurial_revision_to_Ada</name>
<executable>hg_revision_to_ada</executable>
<version>1.0</version>
<languages>Mercurial</languages>
</compiler_description>
<configuration>
<compilers>
<compiler name="Mercurial_revision_to_Ada"/>
</compilers>
<config>
package Naming is
for Body_Suffix ("Mercurial") use ".hg_status";
end Naming;
package Compiler is
for Driver ("Mercurial") use "hg_revision_to_ada";
for Leading_Required_Switches ("Mercurial") use ("--compile");
for Dependency_Kind ("Mercurial") use "None";
end Compiler;
</config>
</configuration>
</gprconfig>
Project file
Now we can make a project file, which uses the language "Mercurial":
project VCS_Status is
for Languages use ("Mercurial");
for Source_Dirs use ("src");
for Object_Dir use "generated";
end VCS_Status;
Using it
$ gprbuild -p -P vcs_status
hg_revision_to_ada --compile version_control_status.hg_status
$ cat generated/version_control_status.ads
package Version_Control_Status is
Revision : constant String (1 .. 53) :=
"76dc54636c40d2c5043575dd5809582a0bd8e703 as committed";
end Version_Control_Status;
$
Now you can change your `Makefile` from:
build:
gprbuild -p -P some_project
to:
build:
gprbuild -p -P vcs_status
gprbuild -p -P some_project
and have access to the Ada package `Version_Control_Status` in your project once you add `generated` to the list of source directories in "some_project.gpr".