In software development it is often necessary to know the revision number that was used to build an application or a library. This is specially useful when a problem occurred to get and look at the good sources. Integrating this information automatically in the build process is a common practice. This article explains how an Ada application can report the subversion repository and revision in an application log.
Subversion keyword substitution
Subversion provides a substitution feature which allows to replace some pre-defined keywords by the file revision, the last modified date or the last author. In an Ada source, we could declare the following string variables:
package Version is Revision : constant String := "$Rev$"; Head_URL : constant String := "$HeadURL$"; end Version;
To activate the keyword substitution you have to set some subversion property on the file:
$ svn propset svn:keywords "Revision HeadURL" version.ads
Each time the file is committed, the keywords will be replaced to integrate the new value. The expanded string will look like:
$Rev: 318 $ $HeadURL: https://ada-util.googlecode.com/svn/trunk $
The issue with subversion keyword substitution is that the information reported only concerns the file changed not the revision of the project (as returned by svnversion for example). In other words, it is necessary to change the version.ads file to get an updated revision number.
Keyword substitution with gnatprep
The gnatprep tool is a pre-processor provided by the GNAT Ada compiler. It reads an input file, evaluates some conditions and expressions (similar to cpp but slightly different) and produces an output file with substituted values. The file to pre-process is an Ada file that will have the .gpb extension to differentiate it from regular Ada files. For our concern we will use gnatprep to substitute some variables, a String and a number. The declaration could be the following:
package Version is Head_URL : constant String := $URL; Revision : constant Positive := $REVISION; end Version;
To produce the expanded .ads file, we will invoke gnatprep and give it the URL and REVISION variables. The manual command would look like:
$ gnatprep -DREVISION=23 -DURL="https://..." \ src/version.gpb src/version.ads
Running such command by hand can be cumbersome. It is easy to use a Makefile with a make target that will do the full job of extracting the latest revision and invoke gnatprep. The make target is the following (make sure to have a tab as first character in the gnatprep command):
version: gnatprep `svn info | grep '^[UR][eR][Lv]' | sed -e 's,URL: \(.*\),-DURL="\1",' -e 's,Revision: ,-DREVISION=,'` \ src/version.gpb src/version.ads
This make target could be run manually or be integrated as part of the build process so that it is executed each time a release build is performed.
Writing the log
The easy part is to report the application revision number either in a log or on the standard output.
with Ada.Text_IO; ... Ada.Text_IO.Put_Line ("Revision " & Positive'Image (Revision));