autoreconf -i not running recursively with AX_SUBDIRS_CONFIGURE

Viewed 239

I am using autotools to generate a configure file to compile a C project called hello, whose compilation depends on the successful compilation of a library subdirectory. The subdirectory is called the_subdir and generates a library called lib_mytest.a.

The subdirectory project (the_subdir) may receive a flag called --enable-other. If it does not receive this flag, it creates the library(lib_mytest.a) by compiling a C file called myfile.c, if it does receive this flag, the library is generated with C file myfile_other.c. In both cases lib_mytest.a is generated, but they behave differently.

Project hello needs to use the version of lib_mytest.a that uses the special flag(--enable-other), so a Makefile for hello would have to recursively make the lib by passing the special --enable-other flag. I am trying to achieve this through autotools. Upon reading the documentation, I understand that I need to use the AX_SUBDIRS_CONFIGURE command, which emulates AC_CONFIG_SUBDIRS, but allows us to run automake recursively by passing specific flags to specific subdirectories.

To do this, I set up the project the following way. Directory hello has the tree structure and files stated below.

The issue: When I run autoreconf -i on the root directory to generate the ./configure file, the subdirectory configure file (the_subdir/configure) is not generated, and then when I run ./configure, I get a warning saying that the_subdir/configure does not exist. This is unlike the behavior of AC_CONFIG_SUBDIRS, which does create the configure subdirs when autoreconf -i is run. This does not agree with the fact that AX_SUBDIRS_CONFIGURE is supposed to emulate the behavior of AC_CONFIG_SUBDIRS. If I run autoreconf -i in both the root directory and inside the_subdir, then ./configure runs normally, running the checks both for the root and subdirectory. This, however, feels like a hack, since I find it unlikely that I need to automake all subdirectories on a larger project. What would be the correct syntax to attain both (1) passing the --enable-other flag to my subdirectory and (2) generating all configure files for my subdirectories with one call of autoreconf -i (or any other command) in the root?

This is the tree structure of this example project (the m4 and C files are not relevant to the problem I think?)

├── configure.ac
├── m4
│   ├── ax_configure_args.m4
│   └── ax_subdirs_configure.m4
├── main.c
├── Makefile.am
└── the_subdir
    ├── configure.ac
    ├── Makefile.am
    ├── mytest.c
    ├── mytest.h
    ├── mytest_other.c
    └── mytest_other.h

the root configure.ac has the following content:

AC_INIT([Tutorial Program], 1.0)                                                                                                                                                                                                                                                    
AM_INIT_AUTOMAKE([foreign])
AC_PROG_CC
AC_CONFIG_MACRO_DIR([m4])

dnl here we compare AC_CONFIG_SUBDIRS with
dnl AC_CONFIG_SUBDIRS([the_subdir])
AX_SUBDIRS_CONFIGURE([the_subdir], [--enable-other])

AC_CONFIG_FILES(Makefile)
AC_OUTPUT

the root Makefile.am:

SUBDIRS := the_subdir                                                                                                                                                                                                                                                               

bin_PROGRAMS = prog
prog_SOURCES = main.c

LDADD = the_subdir/lib_mytest.a

the_subdir/configure.ac:

AC_INIT([Subdir Program], 1.0)                                                                                                                                                                                                                                                      
AM_INIT_AUTOMAKE([foreign])
AC_PROG_CC

AC_CONFIG_SRCDIR([mytest.h])

AM_PROG_AR
AC_PROG_RANLIB

dnl the line breaks in this message are intended
other_fail_msg="

Failed to locate OtherLib on your system.
"

AC_ARG_ENABLE([other],
  [AS_HELP_STRING([--enable-other], [Enable OtherLib @<:@no@:>@])],
  [enable_other=yes], [enable_other=no])
dnl AS_IF([test "x$enable_other" = "xyes"],
dnl   [AC_CHECK_LIB([other], [other_version], [], [AC_MSG_FAILURE([$other_fail_msg])])])
AM_CONDITIONAL([ENABLE_OTHER], [test "x$enable_other" = "xyes"])

AC_CONFIG_FILES(Makefile)
AC_OUTPUT

the_subdir/Makefile.am:

lib_LIBRARIES = lib_mytest.a                                                                                                                                                                                                                                                        

lib_mytest_a_SOURCES = mytest.c

if ENABLE_OTHER
lib_mytest_a_SOURCES += mytest_other.c
endif

include_HEADERS = mytest.h

if ENABLE_OTHER
lib_mytest_a_SOURCES += mytest_other.h
endif

This is what I get when running autoreconf -v -i (note that it does not recurse into the subdirectory):

autoreconf: Entering directory `.'
autoreconf: configure.ac: not using Gettext
autoreconf: running: aclocal 
autoreconf: configure.ac: tracing
autoreconf: configure.ac: not using Libtool
autoreconf: running: /usr/bin/autoconf
autoreconf: configure.ac: not using Autoheader
autoreconf: running: automake --add-missing --copy --no-force
configure.ac:3: installing './compile'
configure.ac:2: installing './install-sh'
configure.ac:2: installing './missing'
Makefile.am: installing './depcomp'
autoreconf: Leaving directory `.'

And this is the output of ./configure, which complains about no ./configure in the_subdir:

checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking whether make supports the include directive... yes (GNU style)
checking dependency style of gcc... gcc3
checking that generated files are newer than configure... done
=== configuring in the_subdir (/home/sena/hello/the_subdir)
configure: WARNING: no configuration information is in the_subdir
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands

but then if I also run autoreconf -i in the subdir then run ./configure in root, everything goes well:

checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking whether make supports the include directive... yes (GNU style)
checking dependency style of gcc... gcc3
checking that generated files are newer than configure... done
=== configuring in the_subdir (/home/sena/hello/the_subdir)
configure: running /bin/bash ./configure '--prefix=/home/sena/hello' --disable-option-checking  '--enable-other' '--srcdir=.' --cache-file=
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables... 
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking whether make supports the include directive... yes (GNU style)
checking dependency style of gcc... gcc3
checking for ar... ar
checking the archiver (ar) interface... ar
checking for ranlib... ranlib
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands

Any help on the correct way to do this would be greatly appreciated!

1 Answers

AX_SUBDIRS_CONFIGURE is not part of Autoconf (which the AX_ prefix tells you). It can be obtained from the GNU-hosted Autoconf Archive, but the macro itself is not owned or maintained by GNU or the Autoconf developers. Accordingly, the autoreconf tool of Autoconf does not attribute any special significance to that macro or give it the kind of special treatment that it gives AC_CONFIG_SUBDIRS. To the extent that the former's documentation suggests otherwise, that documentation is flawed.

One alternative would be to use AC_CONFIG_SUBDIRS instead, and rely on passing --enable-other to the top-level configure script, which it will then forward to the (every) sub-configure. You could provide a wrapper script for the top-level configure that does this automatically, so as to reduce the likelihood of a misconfiguration arising from failing to specify that flag.

Another alternative would be (again) to use AC_CONFIG_SUBDIRS, and to rely on this detail of its behavior:

If a given dir contains configure.gnu, it is run instead of configure.

(Autoconf manual)

Although ...

This is for packages that might use a non-Autoconf script Configure, which can’t be called through a wrapper configure since it would be the same file on case-insensitive file systems.

... you can also use it for your purposes by dropping in a configure.gnu like this:

#!/bin/sh
exec "${0%.gnu}" --enable-other "$@"

The main other alternative is to be satisfied with autoreconf not recursing into the subdirectory. Depending on the specific circumstances, that could be considered a feature rather than a bug.

In this case, the description of the issue suggests that Autotools-built build-system components are not already available in the subdirectory, but why should that actually be? Source distributions of Autotools-based projects should include already-built autotooling, such that people who merely want to build the project don't need to have the Autotools themselves at all. That would apply just as well if you distribute a third-party project inside your own source distribution.

Under some circumstances, it might also be a viable option to merge the subproject into the main project, so that it no longer has a separate configuration script to worry about.

Related