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