The Perl framework for performing continuous, unattended, automated software builds
To achieve complete independance from the language and tools used for a project, the build stage of the autobuild cycle is considered a black box. To perform the build, autobuild merely invokes an opaque control file provided by the developer. This shell script will typically perform four tasks - configure, build, install and package. The autobuild will capture the standard output and error streams, saving to the modules build log files. In common with standard UNIX behaviour, an exit status of zero indicates a successful build, while non-zero indicates failure.
When the control file is invoked, a number of environment variables will be set in its shell. In versions 1.0.x, there are two environment variables.
In the 1.1.x series, these two are deprecated (but still available) in favour of an expanded set
rpmbuild --define '_topdir $AUTOBUILD_PACKAGE_ROOT/rpm' -ta foo.tar.gz
All Perl modules which use ExtUtils::MakeMaker for their build and install process can use the same pattern for their control file. The key to this pattern is to set the value for the PREFIX
variable to $AUTO_BUILD_PREFIX
when running the Makefile.PL
script:
perl Makefile.PL PREFIX=$AUTOBUILD_INSTALL_ROOT
Any non-trivial Perl module will likely have dependancies on other modules built and installed earlier in the cycle. To enable MakeMaker's pre-requisite checking to pick these up, it is neccessary to set the PERL5LIB
environment variable to point to the virtual install root containing the site specific modules:
PERL5LIB=$AUTOBUILD_INSTALL_ROOT/lib/perl5/site_perl/5.8.0
Hard coding the site_perl
in this way is not very good practice, however, since the same code (and thus control file) may be used across many autobuild instances with differing versions of Perl installed. The solution is to make use of the standard Config
module to extract the location.
PERL5LIB=`perl -e 'use Config; my $dir = $Config{sitelib}; \ $dir =~ s|/usr|$ENV{AUTOBUILD_INSTALL_ROOT}|; print $dir'`
To a complete script to configure, build, install the module and create a source code distribution would look like:
#!/bin/sh set -e # Pull in prerequisite modules PERL5LIB=`perl -e 'use Config; my $dir = $Config{sitelib}; \ $dir =~ s|/usr|$ENV{AUTOBUILD_INSTALL_ROOT}|; print $dir'` export PERL5LIB # Clean up build area [ -f Makefile ] && make -k realclean ||: rm -rf MANIFEST blib # Configure the build perl Makefile.PL PREFIX=$AUTOBUILD_INSTALL_ROOT # Make & install make make install # Create source code dist make dist
With a few notable exceptions (Perl & Apache), C and C++ programmers have been increasingly converging on GNU Auto Tools for configuring and building their software. As with MakeMaker, the key task is to set the installation prefix when running the configure script:
./configure --prefix=$AUTOBUILD_INSTALL_ROOT
The task of resolving inter-module build dependancies is somewhat less well defined. There are a number of approaches that may work - some programs may even need a combination of all of them!
Some libraries install a small shell script to the bin directory that programs can use to determine the correct compiler and linker flags. For example, the gtk-config
script can print out the compiler flags required when building against GTK. These scripts are typically generated at build time based on the values to the configure
script. Thus it is sufficient to add the bin
directory containing this script to the PATH
environment variable:
PATH=$AUTOBUILD_INSTALL_ROOT/bin:$PATH
Another common approach to locating pre-requisite libraries is for the program's configure script to have command line options for specifying include and library search paths. For example, when building the Resin Java servlet container, the configure script has --with-openssl-lib and --with-openssl-include options. Thus when configuring Resin, as well as setting the prefix, we'd set these two options:
./configure --prefix=$AUTOBUILD_INSTALL_ROOT \ --with-openssl-lib=$AUTOBUILD_INSTALL_ROOT/lib --with-openssl-include=$AUTOBUILD_INSTALL_ROOT/include
An alternative to specifying both library and include search paths is to just tell the configure script the installation prefix of the library:
./configure --prefix=$AUTOBUILD_INSTALL_ROOT \ --with-openssl=$AUTOBUILD_INSTALL_ROOT
If there is no explicit support for specifying the location of pre-requisite libraries then the final approach is to try setting compiler environment variables. The two important ones being CFLAGS
and LDFLAGS
:
CFLAGS=-I$AUTOBUILD_INSTALL_ROOT/include LDFLAGS=-L$AUTOBUILD_INSTALL_ROOT/lib
Now a complete example control file might look like
#!/bin/sh set -e # Pull in config scripts PATH=$AUTOBUILD_INSTALL_ROOT/bin:$PATH export PATH # Clean up build area [ -f Makefile ] && make -k maintainer-clean ||: # Re-generate autotools scripts autoconf automake -a # Configure the build ./configure --prefix=$AUTOBUILD_INSTALL_ROOT \ --with-openssl=$AUTOBUILD_INSTALL_ROOT # Make & install make make install # Create source code dist make dist
When it comes to writing build.xml files for Java programs with ANT, pretty much anything goes. Fortunately, most of the time there are only two things to worry about, firstly where/how any pre-requisite JARs are located/found, and secondly where to put any generated JARs. For Linux systems, JPackage has been pushing standardization efforts towards a central repository in /usr/share/java, with the alternatives
program being used to manage concurrent, differing versions. Thus the first step when creating a Java program is to get the pre-requisite libraries into the ClassPath. The simplest way is to have a bunch of lines such as:
CLASSPATH=$CLASSPATH:$AUTOBUILD_INSTALL_ROOT/share/java/[somepackage].jar
Some ANT build.xml files may have a property for specifying the location of libraries which can be set for compilation
ant -Dlibrary.dir=$AUTOBUILD_INSTALL_ROOT/share/java build
Very few ANT build.xml files concern themselves with installation of JARs, however, it is pretty simple to use the standard UNIX install
program from the control file:
install -D mylib.jar $AUTOBUILD_INSTALL_ROOT/share/java/mylib.jar
So a complete control file for a Java program might look like
#!/bin/sh ant -Dlibrary.dir=$AUTOBUILD_INSTALL_ROOT/share/java build install -D mylib.jar $AUTOBUILD_INSTALL_ROOT/share/java/mylib.jar