DEV Community

Paul J. Lucas
Paul J. Lucas

Posted on

Autotools Miscellany

Introduction

This last part in this series on Autotools will cover miscellaneous things in Autotools that don’t really fit anywhere else.

Maintainer Tree

For many software packages, there are typically two versions of its “source tree,” that is the complete set of files that comprise it:

  1. A maintainer tree that contains the complete set of files as checked-out from source control. For git, this means there is also a .git subdirectory containing the files git needs to do what it does.
  2. A distribution tree (or dist tree) that contains the complete set of files resulting from un-tar’ing a downloaded tar file for a particular version of the software, and perhaps other files. A dist tree does not contain a .git subdirectory, but does contain a pre-built configure script.

Sometimes when running configure, you want to be able to perform different actions depending on whether you’re running in a maintainer or dist tree. To be able to tell, you can add the following early in configure.ac:

AS_IF([test -d "$srcdir/.git"], [is_maintainer_tree=yes])
Enter fullscreen mode Exit fullscreen mode

That is, if the .git subdirectory is present, assume it’s a maintainer tree.

What’s an example use? If your program uses programs like Flex or Bison, a dist tree will contain the generated lexer and parser C source files, hence neither Flex nor Bison are required to compile your program which makes it easier for users.

However, a maintainer tree should require Flex and Bison so the lexer and parser can be rebuilt as necessary. To do this in configure.ac:

AS_IF([test "x$is_maintainer_tree" = xyes], [
  flex_min_version="2.5.30"
  bison_min_version="3.4.2"

  AC_PROG_LEX([noyywrap])
  AM_PROG_LEX

  AX_PROG_FLEX([FLEX=$LEX],
    [AC_MSG_ERROR([required program "flex" not found])])
  AX_PROG_FLEX_VERSION([$flex_min_version], [],
    [AC_MSG_ERROR([flex version $flex_min_version or later required])])

  AX_PROG_BISON([BISON=$YACC],
    [AC_MSG_ERROR([required program "bison" not found])])
  AX_PROG_BISON_VERSION([$bison_min_version], [],
    [AC_MSG_ERROR([bison version $bison_min_version or later required])])
])
Enter fullscreen mode Exit fullscreen mode

The AX_PROG_FLEX, AX_PROG_FLEX_VERSION, AX_PROG_BISON, and AX_PROG_BISON_VERSION macros are called only when in a maintainer tree.

C11 Compiler

To require a C compiler that supports at least C11, add an AS_IF after AC_PROG_CC in configure.ac:

AC_LANG(C)
AC_PROG_CC
AS_IF([test "x$ac_cv_prog_cc_c11" = xno], [
  AC_MSG_ERROR([a C11 compiler is required to compile $PACKAGE_NAME])
])
Enter fullscreen mode Exit fullscreen mode

To test for _Generic support specifically:

AC_C__GENERIC
AS_IF([test "x$ac_cv_c__Generic" != xyes], [
  AC_MSG_ERROR([C11 _Generic support required to compile $PACKAGE_NAME])
])
Enter fullscreen mode Exit fullscreen mode

Checking for Functions

If you want to check whether the platform support specific functions, you can use AC_CHECK_FUNCS, e.g.:

AC_CHECK_FUNCS([geteuid getpwuid])
Enter fullscreen mode Exit fullscreen mode

would check for the existence of the geteuid and getpwuid functions. If present, the macros HAVE_GETEUID and HAVE_GETPWUID will be defined in config.h.

Checking for Structure Members

If you want to check whether the platform’s version of a particular struct contains particular member, you can use AC_CHECK_MEMBERS, e.g.:

AC_CHECK_MEMBERS([struct passwd.pw_dir], [], [], [#include <pwd.h>])
Enter fullscreen mode Exit fullscreen mode

would check whether struct passwd contains a pw_dir member. If present, the macro HAVE_STRUCT_PASSWD_PW_DIR will be defined.

For example, a function that determines the user’s home directory is:

char const* home_dir( void ) {
  char const *home = getenv( "HOME" );
#if HAVE_GETEUID && HAVE_GETPWUID && HAVE_STRUCT_PASSWD_PW_DIR
  if ( home == NULL ) {
    struct passwd const *const pw = getpwuid( geteuid() );
    if ( pw != NULL )
      home = pw->pw_dir;
  }
#endif
  return home;
}
Enter fullscreen mode Exit fullscreen mode

That is:

  1. First try the HOME environment variable; if NULL:
  2. If we have geteuid, getpwuid, and the pw_dir member exists, get that value (that’s the user’s home directory).

Conclusion

As stated in the Autotools Introduction, if you’ve ever compiled and installed most any open-source software, you’ve most likely typed the commands:

$ ./configure && make && make install
Enter fullscreen mode Exit fullscreen mode

and it all just works thanks to Autotools. Using Autotools, you can create your own programs that are portable to a wide variety of Unix platforms.

Top comments (0)