DEV Community

Paul J. Lucas
Paul J. Lucas

Posted on

GNU Autoconf Archive & Portability Library

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:

  1. Browse and choose the macros you want from the list.
  2. 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 …”.
  3. Rename the files to remove the m4_ prefix.
  4. 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
Enter fullscreen mode Exit fullscreen mode

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 .
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

  1. gl_EARLY immediately after AC_PROC_CC in the “Check for programs” section.
  2. 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

# ...
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)