Introduction
While GNU Autotools contains a large assortment of predefined m4 macros (those beginning with either AC_
for Autoconf or AM_
for Automake) that do various things, they don’t do everything you might need for a particular project. However, it’s often the case that a particular thing you might need has also been needed by others, hence the creation of the Autoconf Archive that contains nearly 600 macros that others have written and contributed for the benefit of everyone that you’re free to download and use in your own projects.
Somewhat related, both the C standard and POSIX libraries (in theory) provide a base API that you can use in your programs. In practice, there are several versions of the C and POSIX standards, and various platforms have varying levels of conformance to those standards. Yet you presumably want your programs to be able to compile and run on as many platforms as possible. The Gnulib portability library provides full source code for common C functions that are sometimes missing from various platforms that you’re free to download and use in your own projects (subject to the terms of the license).
Continuing in this series, this article is about using both the Autoconf Archive and Gnulib in your programs.
Using the Autoconf Archive
To use macros from the Autoconf archive, all you have to do is:
- Browse and choose the macros you want from the list.
- Download the
.m4
source code of the macros you want by going to the macros’ page (for example, this one) and right-clicking the “Download the latest version of …” to “Download Linked File As …”. - Rename the files to remove the
m4_
prefix. - Move them into your project’s
m4
subdirectory.
That’s it. Then you can use them in your configure.ac
.
Per this page, you can also
git clone
the entire archive, but I don’t see the point of downloading a huge archive when you need only a few.m4
files.
By convention, all macros from the archive start with AX_
to distinguish them from the built-in ones starting with either AC_
or AM_
.
For example, cdecl
uses the AX_C___ATTRIBUTE__
, AX_CFLAGS_WARN_ALL
, AX_PROG_FLEX
, AX_PROG_FLEX_VERSION
, AX_PROG_BISON
, and AX_PROG_BISON_VERSION
macros.
Macro Versions
By convention, all m4 macro files have a line that looks like:
#serial 9
that is a comment of serial
followed by “serial number” of the macro, an integer. Whenever macro authors update a macro, they increment the serial number. (By convention, macros use single integers and not the typical major.minor.patch nomenclature.)
If you’re using a set of macros, you should occasionally check the serial numbers of the ones you’re using on the site: if they’re larger than yours, you should download the newer ones and replace your old ones.
Using Gnulib
To use “modules” from Gnulib, first download it. Unlike the Autoconf Archive, you do really need to git clone
it. Since you use Gnulib source code, it’s not installed. Just pick somewhere on your filesystem as I’ve done, download it, then symlink gnulib-tool
(its module manager command) to somewhere in your PATH
:
$ cd /usr/local/src
$ git clone https://git.savannah.gnu.org/git/gnulib.git
$ cd /usr/local/bin
$ ln -s /usr/local/src/gnulib/gnulib-tool .
To find modules to use, you can read this documentation or directly browse the module list.
Installing Modules in Your Project
For an example, cdecl
uses the fnmatch, getline, and the getopt-gnu modules (among others). To install them:
$ gnulib-tool --add-import fnmatch getline getopt-gnu
This will install additional m4 macros, such as fnmatch.m4
, getline.m4
, and getopt.m4
, into your project’s m4
directory; and also source files into your project’s lib
directory.
When configure
is run, these macros will probe the platform looking to see if the functions fnmatch
, getline
, and getopt_long
already exist. If so, those will be used; if not, then the source files in lib
will be compiled and used instead.
Integrating with Autoconf
In order to cause configure
to do the probing, two things need to be added to your configure.ac
:
-
gl_EARLY
immediately afterAC_PROC_CC
in the “Check for programs” section. -
gl_INIT
at the end of the “Check for header files“ section.
For example:
AC_PREREQ([2.69])
AC_INIT([cdecl], [18.6],
[https://github.com/paul-j-lucas/cdecl/issues],[],[https://github.com/paul-j-lucas/cdecl])
AC_CONFIG_MACRO_DIR([m4])
AM_INIT_AUTOMAKE
# Checks for programs.
AC_LANG(C)
AC_PROG_CC
gl_EARLY
# Checks for header files.
AC_CHECK_HEADERS(...)
gl_INIT
# ...
Now if you re-run bootstrap
to regenerate configure
, then run configure
, you’ll see that it’ll do the additional probing.
Additionally, in Makefile,.am
, you need to add m4/gnulib-cache.m4
to EXTRA_DIST
:
EXTRA_DIST = bootstrap \
m4/gnulib-cache.m4 \
README.md
Lastly, in src/Makefile.am
, you need to add:
AM_CPPFLAGS = -I$(top_srcdir)/lib -I$(top_builddir)/lib
LDADD = $(top_builddir)/lib/libgnu.a
The first line adds the lib
directory to the compiler’s (preprocessor’s) include path where top_srcdir
is automatically set for you. (top_builddir
is the same unless you do out-of-source-tree builds, but that’s a story for another time.)
The second line will cause your program to link against libgnu.a
, the compiled module code.
Updating Modules
As time passes, module authors will update their modules. To incorporate their latest changes into your projects, you need to update your copy of Gnulib, then run gnulib-tool
:
$ cd /usr/local/src/gnulib
$ git pull
$ cd ~/src/your_project
$ gnulib-tool --add-import
Specifying --add-import
without any arguments means just update the modules you’ve already imported.
In my projects, I add a pseudo target to the top-level Makefile.am
:
update-gnulib:
gnulib-tool --add-import --no-vc-files
Integrating with Git
You might be wondering what the --no-vc-files
option is for. The gnulib-tool
has the (IMHO) annoying habit of creating or modifying .gitignore
(or other version control) files in both the m4
and lib
directories in ways that I personally think are wrong. The --no-vc-files
option stops gnulib-tool
from either creating or modifying .gitignore
.
Instead, in lib
, for every file *.in.h
, you need to add an entry to .gitignore
of *.h
. For example, the fnmatch and getopt-gnu modules contain the files fnmatch.in.h
and getopt.in.h
that are processed into fnmatch.h
and getopt.h
, respectively, when configure
is run. It’s those generated files that should not be checked-in and so be put into .gitignore
:
/fnmatch.h
/getopt.h
It’s my recommendation that you should always use the --no-vc-files
option whenever you invoke gnulib-tool
. (Perhaps even create a shell alias so you never forget it.)
Conclusion
Both the Autoconf Archive and the Gnulib Library facilitate you making your programs to be able to compile and run on as many platforms as possible. Granted, there are a lot of fiddly steps to getting them set up, but once you do, maintenance is fairly easy.
There are more parts to come!
Top comments (0)