Brief
In training (Qs-GnuBuildEnvironment)
we discussed the rationale and means of using the Gnu Build System in
application development and deployment. This training extends on
that training to include instructions on how to utilize this build
environment in the development of more sophisticated applications
where autoconf will examine the system and tailor the application
dependent on the existence of module dependencies.
Introduction
The GNU Build System (also known as
autotools) is a suite of tools authored by Gnu used to make portable
software products. The build system includes two significant
programs: automake and autoconf. The automake
utility is used in the generation of makefiles from a Makefile.am
template. The autoconf utility provides a set of utilities
that help to generate the configure script. Together, these
utilities provide the means of interrogating the target system and
generating a target-specific makefile to be used to compile the
application.
Before beginning, it is assumed that
your system has the following packages installed:
-
autoconf
-
automake
-
gcc
-
g++
-
pkg-config
-
libgtk2.0-dev
Discussion
We begin with a similar example to that
outlined in training Qs-GnuBuildEnvironment.
The example is similar
but simplified to use a single source file. Without discussion we
will identify the contents of the input files and abbreviated
procedure for setting up the build environment.
Base Example
configure.ac
AC_PREREQ(2.59)
AC_INIT(FULL-PACKAGE-NAME,
VERSION, BUG-REPORT-ADDRESS)
AM_INIT_AUTOMAKE(someApp,2.1)
AC_CONFIG_HEADER([config.h])
AC_PROG_CC
AC_OUTPUT(Makefile)
Makefile.am
bin_PROGRAMS=someApp
someApp_SOURCES=myMain.c
myMain.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("(%s:%d)
main process initializing\n",__FILE__,__LINE__);
printf("(%s:%d)
main process terminating\n",__FILE__,__LINE__);
return
EXIT_SUCCESS;
}
Brief Build System Setup
Given the
configure.ac, Makefile.am, and myMain.c files stepping through the
following procedure will result in building the someApp application.
$ aclocal
$ autoconf
$ autoheader
$ touch NEWS
README AUTHORS ChangeLog
$ automake -a
$ ./configure
$ make
Example Extension
The autoconf
utility allows examining the target system for features. A common
action for applications is to allow autoconf to define C
preprocessor symbols based on the result of such feature tests.
configure.ac
AC_PREREQ(2.59)
AC_INIT(FULL-PACKAGE-NAME,
VERSION, BUG-REPORT-ADDRESS)
AM_INIT_AUTOMAKE(someApp,2.1)
AC_CONFIG_HEADER([config.h])
AC_PROG_CC
AC_CHECK_HEADER([popt.h],
[AC_DEFINE([HAVE_POPT_H], [1],
[Define to 1 if you have <popt.h>.])],
[AC_MSG_ERROR([Sorry, can't do anything for you])])
AC_OUTPUT(Makefile)
After making the
above changes to the configure.ac file you must repeat the procedure
for re-establishing the build environment.
$ aclocal
$ autoheader
$ automake –add-missing –copy
$ autoconf
Running ./configure
will now execute the AC_CHECK_HEADER feature test, giving the
following output:
checking for
popt.h... no
configure:
error: Sorry, can't do anything for you
or
checking for
popt.h... yes
If the feature test
for popt.h fails configure outputs an error and aborts the
script. If the feature test for popt.h succeeds AC_DEFINE
will define the HAVE_POPT_H precompiler symbol as 1, defined
in config.h. This test effectively defines a critical dependency on
popt.h, which isn't exactly what we intended. What we
intended is the definition of a precompiler symbol based on the
autoconf examination of the system. If we update the
configure.ac file as follows we will get the desired result.
configure.ac
AC_PREREQ(2.59)
AC_INIT(FULL-PACKAGE-NAME,
VERSION, BUG-REPORT-ADDRESS)
AM_INIT_AUTOMAKE(someApp,2.1)
AC_CONFIG_HEADER([config.h])
AC_PROG_CC
AC_CHECK_HEADER([popt.h],
[AC_DEFINE([HAVE_POPT_H], [1],
[Define to 1 if you have <popt.h>.])])
AC_OUTPUT(Makefile)
Next,
by placing precompiler commands we can test for the definition of the
HAVE_POPT_H symbol. This allows us to place conditional code in our
application. In the absence of popt libraries we could
substitute our own command line parsing routine.
myMain.c
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("(%s:%d)
main process initializing\n",__FILE__,__LINE__);
#ifdef HAVE_POPT_H
printf("(%s:%d) whee...we have popt.h\n",__FILE__,__LINE__);
#else
printf("(%s:%d) rats...we don't have
popt.h\n",__FILE__,__LINE__);
#endif
printf("(%s:%d)
main process terminating\n",__FILE__,__LINE__);
return
EXIT_SUCCESS;
}
Conclusion
In closing, authoring a Gnu Build
Environment compliant product offers flexibility to the user by
incorporating a standardized means for examining the target system
and ensuring the required product dependencies are met and offers a
well defined configuration and build environment when distributing
your product by source. Incorporation
of autoconf feature examination allows the conditional definition of
precompiler symbols. These symbols can be used to place conditional
code in our application, giving us alternatives to continue in the
absence of optional features.
References
-
Introduction to the GNU Build System; FSK Consulting
No comments:
Post a Comment