Monday, October 13, 2014

Autotools in Ten Minutes or Less

I've recently been getting more exposure to autotools. I found out quickly that when learning autotools, one can easily get overwhelmed with details that aren't relevant to his purposes. The complexity of it all can easily be observed when one comes across, for example, an introductory tutorial that is 162 pages long. For me, this gets frustrating.

I've found that for 90% of cases, all I need is a set of simple templates of the files containing the basic elements for building a package with autotools. For this reason, I've put together such a template here, which builds a simple "hello world" program. I've also included the components necessary to build a parser using flex and bison, since this is a common need which requires some modifications to the files.

To build the example, simply untar the tarball, enter the directory, type "autoreconf -fiv", "configure", and then "make". And that's it. You can build the distribution tarball by typing "make dist".

To remove the parser from the build, open "src/Makefile.am" and comment out "parser" from the "bin_PROGRAMS" variable, along with following three lines (the lines starting with "parser_SOURCES", "AM_YFLAGS", and "BUILT_SOURCES").

Modifying the files for your own project is straightforward. Add your C files to the "src/" directory. Now, add the name of your executable to build to the "bin_PROGRAMS" variable. Say that the name of your new program is "myprog". Now, create a variable "myprog_SOURCES", and assign to it the list of .c and .h files on which it depends. Finally, rerun "./configure" and "make".

To learn about more of the details of how autotools works so that you can customize the example to suit a broader range of purposes, the best tutorial I've found is the one linked above.

In the future, I might modify this example to include provisions for libtool, which is used widely alongside autotools.



To generate the build system for a directory structure containing your own source files, the following should work in basic cases:

1. In the top-level directory of your project, run
$ autoscan
$ mv configure.scan configure.ac

2. Now edit configure.ac.
a. Change:
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
to
AC_INIT([my_package], [0.1], [myemail@organization.com])
or whatever your package name, version, and email address are.

b. For the line:
AC_CONFIG_SRCDIR([src/cpp/my_source.cpp])
Make sure that "src/cpp/my_source.cpp" is a source file in your project.

c. Add the line
AM_INIT_AUTOMAKE([foreign -Wall -Werror])
after the line near the top containing AC_CONFIG_HEADERS

d. Add the lines
AC_CONFIG_FILES([Makefile
src/cpp/Makefile])

With all Makefiles to be built.

e. If the package depends on another library, you can force the user of the configure script to specify the location of this library through the AC_ARG_WITH macro. For example, say the SystemC library is needed. To allow the user to specify the location of SystemC with a "--with-systemc" argument to the configure script, add the lines below. The AC_SUBST macro allows the use of the SYSC_LOC variable in the Makefiles.

AC_ARG_WITH([systemc],
 [AS_HELP_STRING([--with-systemc],
 [Specify where the SystemC libraries is installed.])],
 [sysc_loc=$withval
 AC_SUBST(SYSC_LOC,$sysc_loc)
 AC_DEFINE([HAVE_SYSC],[1],[Define when SYSC is enabled.])],
            [sysc=no])

You can then tell configure check to make sure that the SystemC libraries can be found:

AC_LANG_PUSH(C++)
CPPFLAGS="$CPPFLAGS -I$sysc_loc/include/"
AC_CHECK_HEADERS([systemc.h],
 #[AC_MSG_RESULT()],
 [],
 [AC_MSG_ERROR([Need to specify location of SystemC through --with-systemc.])])
 AC_LANG_POP(C++)

f. add a Makefile.am file to each directory with a Makefile listed above.
Follow the formats of the Makefile.am found in the tarball linked above.
The Makefile.am in the top-level directory usually just points to
the subdirectories containing other Makefile.am files.

3. All files should now be in place to create the build system. Now run:
$ autoreconf -fiv
$ ./configure
$ make

No comments:

Post a Comment