Introduction


The standard GNU make utility eases many of the burdens associated with building an executable from multiple source files. It enables incremental building of the source and allows the commands and processes needed to maintain a source package to be collected in a single location. GNU make is excellent at implementing the steps needed to build a moderately complex project. GNU make starts to become cumbersome as projects grow in complexity. Examples of factors that cause Makefile maintenance to become cumbersome are these:

  • Projects with a large number of files that have varied build requirements.

  • Dependencies on external libraries.

  • A desire to build in a multiplatform environment.

  • Installing built software in multiple environments.

  • Distributing a source package.

The solution to these complexities is to move up one level and automatically generate the appropriate Makefiles to build the project. This allows GNU mmake to focus on the things it is good at while still allowing the capability to configure for the current build environment. The GNU Autotools are an attempt to provide this next level of build functionality on top of the GNU mmake utility.

An Example Project

The examples in this chapter will show various ways to build a project consisting of four source files. Two of the source files will be used to build a library, and the other files will build an application that uses the library (see Figure 9.1).

click to expand
Figure 9.1: Directory structure of example project.

A Makefile Solution

The following listing shows a simple Makefile that builds the library and an application that uses the library. This Makefile will be used to provide a basis for comparing how Autotools would build the same project. Keep in mind that the example considered here is very simple. The application of automake/autoconf to this project will seem like more work than payoff, but as the project grows, the payback from using the Autotools will increase.

Listing 9.1: Simple Makefile to Build Example (on the CD-ROM at ./source/ch9/Makefile.simple )
start example
  1:  VPATH= lib app  2:   3:  LIBSRC= lib.c bar.c  4:  LIBOBJ= $(LIBSRC:.c=.o)  5:   6:  APPSRC= main.c app.c  7:  APPOBJ= $(APPSRC:.c=.o)  8:   9:  CFLAGS=  10:  INCLUDES= -I ./lib  11:   12:  all: libexp.a appex  13:   14:  %.o:%.c  15:  $(CC) -c $(CFLAGS) $(INCLUDES) -o $@ $  16:   17:  libexp.a: $(LIBOBJ)  18:  $(AR) cru libexp.a $(LIBOBJ)  19:   20:  appex: $(APPOBJ) libexp.a  21:  $(CC) -o appex $(APPOBJ) -lexp -L . 
end example
 

Line 1 of the listing sets the VPATH variable. The VPATH variable specifies search paths that will be used by the make utility to find the source files for the build rules. The VPATH capability of make allows the use of a single Makefile to reference the source files in the lib and app subdirectories. Lines 3 through 7 create source and object file lists for use by the build rules. Notice that the file list doesn t include paths because this is taken care of by the VPATH search variable. Lines 9 and 10 set up the necessary compiler flags to perform the build. Line 12 sets up the default build target to build both the library and application. Lines 14 and 15 define the rules used to turn c-source files into object files. Lines 17 and 18 describe how to build the library. Finally, lines 20 and 21 describe how to build the application.

The simplified Makefile is missing a few features that would need to be included in a real build system to make it useable: a clean target, dependency tracking on included header files, a method for installing the generated binaries, and so forth. The Autotools implementation will provide many of these missing features with only a little bit of additional work when compared to the effort needed to create the simplified Makefile.

A Simple Implementation Using Autotools

The initial implementation using the Autotools will require the creation of five files to replace the simple Makefile described in Listing 9.1. Although this seems like a lot of files to replace a single file, each of the replacement files is generally simpler. Both the simple Makefile and the Autotool files will contain roughly the same information, but Autotools chooses to distribute the information differently with a project s directory structure. Figure 9.2 illustrates the directory structure from Figure 9.1 with the additional of the Autotools files.

click to expand
Figure 9.2: Directory structure of example project with Autotool files.

The additional files added to support a simple Autotools project are these:

  autogen .sh :    A shell script to run Autotools to generate the build environment.

 configure.ac :    The input file for the autoconf tool.

 Makefile.am :    The top-level Makefile template.

app/Makefile.am:    The Makefile template for appexp executable.

lib/Makefile.am:    The Makefile template for building the libexp.a library.

These files describe the intended build products and environment to Autotools. Autotools will take this input and generate a build environment template that will be further configured on the build system to generate the final set of Makefiles. Assuming that we are developing and building on the same machine, the following commands should configure and build our example project:

 # ./autogen.sh     # ./configure     # make 

Running the  autogen.sh script will execute the Autotool utilities to convert the input files into a build environment template that can be configured on the host system. Executing the configure script causes the build environment template to be customized for the build machine. The output of the configure script is a set of GNU Makefiles that can be used to build the system. Executing the make command in the root directory will cause both the library and application to be built.

An examination of  autogen.sh should be the starting point for understanding how this process works. Listing 9.2 shows a very simple  autogen.sh script that just executes the Autotools utilities. Generally the  autogen.sh script in a real project will be much more complicated to first check that the Autotools exist and are of the appropriate version. To find an example of a more complex  autogen.sh script, you should examine this file in the source repositories of your favorite open source project.

Listing 9.2: Simple autogen.sh Script (on the CD-ROM at ./source/ch9/autogen.sh )
start example
  1:  #!/bin/sh  2:  # Run this to generate all the initial makefiles, etc.  3:   4:  aclocal  5:  libtoolize automake  6:  automake -a  7:  autoconf 
end example
 

Line 1 indicates the shell to use when running this script. Line 4 runs the aclocal utility. The aclocal utility creates the local environment needed by the automake and autoconf tools to work. Specifically aclocal makes sure the m4 macro environment that automake and autoconf use to implement their functionality is set up appropriately. Line 5 executes the libtoolize utility, which enables the libtool functionality in automake . The libtool functionality will be discussed in a subsequent section. Line 6 executes the automake utility, which turns the  Makefile.am files into Makefile.in files. This operation is discussed more in the next section. Line 7 executes the autoconf utility that takes the  configure.ac input file and turns it into a pure shell script named configure .

automake

The input to the automake utility is a series of  Makefile.am files that describe the targets to be built and the parameters used to build them. The automake utility transforms the  Makefile.am files into makefile.in files. The Makefile.in file is a GNU make format file that acts as a template that the configure script will transform into the final Makefile. automake has built-in support for building binaries and libraries, and with the support of libtool can also be used to build shared libraries. The example project required three separate automake files: one in the root directory and one for each subdirectory. Let s examine the root  Makefile.am to see how automake handles subdirectories.

Listing 9.3: Listing of the Root Makefile.am (on the CD-ROM at ./source/ch9/_Makefile.am )
start example
  1:  SUBDIRS = lib app 
end example
 

The contents of the root  Makefile.am simply indicate that all the work for this project will be done in the subdirectories. Line 1 tells the automake utility that it should descend into the subdirectories and process the  Makefile.am files it finds there. The ordering of directories in the SUBDIRS variable is significant; the subdirectories will be built in the left to right order specified in the subdirectories list. The sample project uses this to ensure that the lib directory is built before the app directory; a requirement of the sample project because the application is dependent on the library being built first. Let s move on to the lib/Makefile.am file that shows automake how to build the libexp.a library.

Listing 9.4: Listing of lib/Makefile.am (on the CD-ROM at ./source/ch9/_lib/Makefile.am )
start example
  1:  lib_LIBRARIES = libexp.a  2:  libexp_a_SOURCES = bar.c lib.c 
end example
 

Line 1 is a list of the static libraries to be built in this directory. In this case the only library being built is libexp.a . The syntax of line 1 is more complex than it first appears. The lib_LIBRARIES variable name indicates two pieces of information. The lib portion indicates that when the library is installed it will be put in the lib directory. The LIBRARIES portion indicates that the listed targets should be built as static libraries. Line 2 lists the source files that go into building the libexp.a static library. Again automake uses the format of the variable name to provide the association between both the library that the variable applies to and content of the variable. The libexp_a portion of the name indicates that this variable s value applies to building libexp.a . The SOURCES portion of the name implies that the value of this variable will be a space-separated list of source files. The app/Makefile.am file is very similar to the one in the lib directory but includes a few additional variables to take care of using the libexp.a library that was previously built in the lib directory.

Listing 9.5: Listing of app/Makefile.am (on the CD-ROM at ./source/ch9/_app/Makefile.am )
start example
  1:  bin_PROGRAMS = appexp  2:  appexp_SOURCES = app.c main.c  3:  appexp_LDADD = $(top_builddir)/lib/libexp.a  4:  appexp_CPPFLAGS = -I $(top_srcdir)/lib 
end example
 

Line 1 of Listing 9.5 should look similar to line 1 in Listing 9.4 in that it is a list of things to be built. In this case the bin_PROGRAMS variable name indicates to automake that the result will be installed in the bin directory and listed targets should be built as executables. The appexp _ prefix on the variable in lines 2 through 4 indicates that these variables apply to building the appexp executable. Line 2 has the SOURCES variable that lists the source files that will be compiled into the appexp executable. Line 3 specifies the LDADD variable, which are things that will be included during linking. In this example, the LDADD variable is used to add the library that was previously built in the lib directory. The $(top_builddir) is set by the configure script when it is run and provides a mechanism for Makefiles to reference the build directories in a relative manner. Line 4 specifies the CPPFLAGS variable that is passed to the preprocessor when it runs. This variable should contain the -I include paths and the -D defines that would normally be passed to the preprocessor in a Makefile. In this example it is being used to get access to the library header file contained in the lib directory. The $(top_srcdir) variable is set by the configure script; it provides a mechanism for Makefiles to reference source files in a relative manner.

autoconf

The autoconf utility converts the  configure.ac input file into a shell script named configure . The configure script is responsible for collecting information about the current build system and using the information to transform the Makefile.in template files into the Makefiles used by the GNU make utility. The configure script performs the transformation by replacing occurrences of configuration variables in the Makefile.in template file with values for those variables as determined by the configure script. The  configure.ac input file contains macros that describe the types of configuration checks the configure script should perform when it is run. The  configure.ac for our example project illustrates the very simple series of checks needed to compile c-files and create static libraries.

Listing 9.6: Listing of configure.ac (on the CD-ROM at ./source/ch9/configure.ac )
start example
  1:  dnl Process this file with autoconf to produce a configure script  2:  AC_PREREQ(2.53)  3:  AC_INIT(app)  4:  AM_INIT_AUTOMAKE(appexp, 0.1.00)  5:  AC_PROG_CC  6:  AC_PROG_RANLIB  7:  AC_OUTPUT(app/Makefile lib/Makefile Makefile) 
end example
 

Line 1 illustrates the comment format used by autoconf . Line 2 is a macro defined by autoconf to ensure that the version of the autoconf utility being used to create the configure script is new enough. This macro results in a check to make sure that autoconf utility has a version number equal to or greater than 2.53. If the version isn t recent enough, an error will be generated, and the configure script will not be generated. Line 3 is a required autoconf macro that must be called before any other macros are invoked; it gives autoconf a chance to initialize itself and parse its command line parameters. The parameter to AC_INIT is a name for the project. Line 4 is the initialization macro for automake. autoconf can be used independently of automake , but if they are to be used together, then the AM_INIT_AUTOMAKE macro is required in the project s  configure.ac file. Line 5 and 6 are the first macros that actually check for tools used during the make process. Line 5 indicates that the project will cause the configure script to find and prepare the make files to use the C compiler. Line 6 does the checks to find the tools needed to build static libraries. Line 7 is the other required macro that must exist in a  configure.ac file. This macro indicates the output files that should be generated by the configure script. When the configure script is ready to generate its output files, it will iterate through the files in the AC_OUTPUT macro and look for a corresponding file with an .in suffix. It will then perform a substitution step on the .in file to generate the output file.

The configure Script

The output of the autoconf utility is a shell script named configure . The example  configure.ac in Listing 9.7 generates a configure script with approximately 4,000 lines when run through the autoconf utility. Executing the configure script will collect the required configuration information from the executing system and generate the appropriate Makefiles by performing a substitution step on the Makefile.in files generated by automake . Let s examine the output of running the configure script generated by our example.

Listing 9.7: Output from the Example configure Script
start example
  1:  checking for a BSD-compatible install... /usr/bin/install -c  2:  checking whether build environment is sane... yes  3:  checking for gawk... gawk  4:  checking whether make sets $(MAKE)... yes  5:  checking for gcc... gcc  6:  checking for C compiler default output file name... a.exe  7:  checking whether the C compiler works... yes  8:  checking whether we are cross compiling... no  9:  checking for suffix of executables... .exe  10  :      checking for suffix of object files... o  11  :      checking whether we are using the GNU C compiler... yes  12  :      checking whether gcc accepts -g... yes  13  :      checking for gcc option to accept ANSI C... none needed  14  :      checking for style of include used by make... GNU  15  :      checking dependency style of gcc... gcc3  16  :      checking for ranlib... ranlib  17  :      configure: creating ./config.status  18  :      config.status: creating app/Makefile  19  :      config.status: creating lib/Makefile  20  :      config.status: creating Makefile  21  :      config.status: executing depfiles commands 
end example
 

Lines 1 through 4 are checks that occur to ensure that the build environment has the appropriate tools to support the make process. Lines 5 through 15 are checks generated by the AC_PROG_CC macro that locate and ready the compiler toolchain for processing C-source code. Line 16 is a check generated by the AC_PROG_RANLIB macro to ensure that the ranlib utility exists for generating static libraries. Lines 18 through 20 indicate that the substitution step to turn the Makefile.in templates into the actual Makefiles is occurring.

Once the configure script has completed successfully, then all of the Makefiles needed to build the project should have been successfully created. Typing make in the root directory at this point should build the project.

The Generated Makefiles

The generated Makefiles have a number of nice characteristics that were lacking in the simple Makefile of Listing 9.1, such as:

  • Automatic dependency tracking. For example, when a header file is modified, only the source files that are affected will be rebuilt.

  • A clean target that will clean up all the generated output.

  • The automated ability to install the generated binaries into the appropriate system directories for execution.

  • The automated ability to generate a distribution of the source code as a compressed tar file.

The generated Makefiles have numerous predefined targets that allow the user to invoke these capabilities. Let s examine the common targets used in the automake -generated Makefiles:

make:    The default target. This will cause the project binaries to be built.

make clean:    The clean target. This will remove all of the generated build files so that the next call to make will rebuild everything.

make distclean:    This target removes all generated files, including those generated by the configure script. After using this target, the configure script will need to be run again before another build can take place.

make install:    This target will move the generated binaries and supporting files into the system directory structure. The location of the installation can be controlled with the -enable-prefix parameter that can be passed to the configure script when it is run.

make dist:    This target generates a .tar.gz file that can be used to distribute the source code and build setup. Included in the tarball will be all of the source files, the makefile.in files, and the configure script.

Just looking at the default targets provided by the standard automake Makefile should indicate some of the power that exists in using the Autotools to generate the Makefiles for your project. The initial setup to use the Autotools can be a bit cumbersome, but once the infrastructure is in place, then future updates to the files are very incremental, and the payback is large compared to implementing the same capabilities by hand in a developer- maintained Makefile.




GNU/Linux Application Programming
GNU/Linux Application Programming (Programming Series)
ISBN: 1584505680
EAN: 2147483647
Year: 2006
Pages: 203
Authors: M. Tim Jones

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net