Ok, I think my question might have been a bit unclear. To wrap up, I circumvented the problem by omitting the --disable-dependency-tracking
option and changing the my Makefile.am
s to not include any sources prefixed by $(srcdir)
or $(top_srcdir)
because this seems to confuse automake
, at least when building out-of-source (see also my post here or this bug report). Although I don't know if this is the right place for this, I decided to set up a small example, which works correctly and avoids the problems I described in my question.
My directory structure is as follows:
autogen.sh
configure.ac
Makefile.am
adapter
Makefile.am
adapterA
Makefile.am
include
foo.h
src
foo.cpp
Makefile.am
adapterB
Makefile.am
include
foo.h
src
foo.cpp
Makefile.am
debug
include
hello.h
m4
src
hello.cpp
helloconf.sh.in
Makefile.am
The files contain the following code:
autogen.sh
:
#!/bin/sh
# GNU autotools toolchain
libtoolize --automake
aclocal
autoheader
automake --add-missing --force-missing --gnu
autoconf
configure.ac
:
dnl Process this file with autoconf to produce a configure script.
dnl Project name and version
AC_INIT([hello], [0.1])
dnl Library version information
AC_SUBST([HELLO_API_VERSION], [0.1])
AC_SUBST([HELLO_SO_VERSION], [0:0:0])
dnl Create a separate header with C preprocessor `#define` statements
AC_CONFIG_HEADERS([config.h])
dnl Look for auxiliary scripts in the current directory
AC_CONFIG_AUX_DIR([.])
dnl Automake initialization
dnl -Wall Show warnings
dnl -Wall Treat warnings as errors
dnl subdir-objects Place generated object files (.o) into the same as
dnl directory their source files, in order to avoid
dnl collisions when non-recursive make is used
AM_INIT_AUTOMAKE([-Wall subdir-objects])
m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
dnl Libtool settings
LT_INIT([disable-static])
AC_CONFIG_MACRO_DIR([m4])
dnl Doxygen
dnl DX_HTML_FEATURE(ON)
dnl DX_PDF_FEATURE(OFF)
dnl DX_INIT_DOXYGEN([$PACKAGE_NAME], [Doxyfile], [doc])
dnl Checks for programs
AC_PROG_CXX([g++])
AC_PROG_INSTALL
AC_PROG_LN_S
AM_PROG_LIBTOOL
dnl Use the C++ compiler for the following checks
AC_LANG([C++])
dnl Checks for libraries
dnl Checks for header files
AC_HEADER_STDC
AC_CHECK_HEADER(iostream)
dnl Checks for typedefs, structures, and compiler characteristics
AC_TYPE_SIZE_T
dnl Checks for library functions
dnl Compiler and linker flags
AC_SUBST([AM_CXXFLAGS], [-Wall]) # C++
AC_SUBST([AM_LDFLAGS], [-Wall]) # ld (Linker)
dnl Libraries
AC_SUBST([LIBS])
AC_CONFIG_FILES(
Makefile
adapter/Makefile
adapter/adapterA/Makefile
adapter/adapterA/src/Makefile
adapter/adapterB/Makefile
adapter/adapterB/src/Makefile
src/Makefile
src/helloconf.sh
)
AC_OUTPUT
Makefile.am
:
# Process this file with automake to produce Makefile.in
# Independent executable script for inclusion in the distribution archive
dist_noinst_SCRIPTS = autogen.sh
# Look for additional autoconf macros in the m4 subdirectory
ACLOCAL_AMFLAGS = \
-I m4 \
@ACLOCAL_FLAGS@
# Subdirectories
SUBDIRS = \
adapter \
src
# Entire directories copied recursively into the distribution
EXTRA_DIST =
# Delete anything except for files required to run `./configure && make`
MAINTAINERCLEANFILES =
# Delete anything which should not be part of the distribution
DISTCLEANFILES =
adapter/Makefile.am
:
# Process this file with automake to produce Makefile.in
SUBDIRS = \
adapterA \
adapterB
adapter/adapterA/Makefile.am
:
# Process this file with automake to produce Makefile.in
SUBDIRS = src
adapter/adapterA/include/foo.h
:
#ifndef FOO_H_
#define FOO_H_
void foo();
#endif
adapter/adapterA/src/foo.cpp
:
#include <iostream>
#include "foo.h"
void foo()
{
std::cout << "Hello, foo from adapterA" << std::endl;
}
adapter/adapterA/src/Makefile.am
:
# Process this file with automake to produce Makefile.in
# Adapter .so version
ADAPTER_SO_VERSION = 0:0:0
AM_CXXFLAGS = \
-I$(top_srcdir)/include \
-I$(srcdir)/../include \
@AM_CXXFLAGS@
# Library name
lib_LTLIBRARIES = libadapter-@HELLO_API_VERSION@.la
# Sources
libadapter_@HELLO_API_VERSION@_la_SOURCES = \
../../../src/hello.cpp \
foo.cpp
# Linker flags
libadapter_@HELLO_API_VERSION@_la_LDFLAGS = \
-version-info $(ADAPTER_SO_VERSION)
# Include directory and headers
libadapter_@HELLO_API_VERSION@_la_includedir = \
$(exec_prefix)/include/adapter/adapterA
libadapter_@HELLO_API_VERSION@_la_include_HEADERS = \
../include/foo.h
# Library install directory
libdir = $(exec_prefix)/lib/adapter/adapterA
adapter/adapterB/Makefile.am
and adapter/adapterB/include/foo.h
are identical to their A
equivalents.
adapter/adapterB/src/foo.cpp
:
#include <iostream>
#include "foo.h"
void foo()
{
std::cout << "Hello, foo from adapterB" << std::endl;
}
adapter/adapterB/src/Makefile.am
:
# Process this file with automake to produce Makefile.in
# Adapter .so version
ADAPTER_SO_VERSION = 0:0:0
AM_CXXFLAGS = \
-I$(top_srcdir)/include \
-I$(srcdir)/../include \
@AM_CXXFLAGS@
# Library name
lib_LTLIBRARIES = libadapter-@HELLO_API_VERSION@.la
# Sources
libadapter_@HELLO_API_VERSION@_la_SOURCES = \
../../../src/hello.cpp \
foo.cpp
# Linker flags
libadapter_@HELLO_API_VERSION@_la_LDFLAGS = \
-version-info $(ADAPTER_SO_VERSION)
# Include directory and headers
libadapter_@HELLO_API_VERSION@_la_includedir = \
$(exec_prefix)/include/adapter/adapterB
libadapter_@HELLO_API_VERSION@_la_include_HEADERS = \
../include/foo.h
# Library install directory
libdir = $(exec_prefix)/lib/adapter/adapterB
include/hello.h
:
#ifndef HELLO_H_
#define HELLO_H_
void hello();
#endif
src/hello.cpp
:
#include <iostream>
#include "hello.h"
void hello()
{
std::cout << "Hello, world!" << std::endl;
}
src/helloconf.sh.in
:
#!/bin/bash
echo @prefix@
src/Makefile.am
:
# Process this file with automake to produce Makefile.in
# Look for additional autoconf macros in the m4 subdirectory
ACLOCAL_AMFLAGS = \
-I m4 \
@ACLOCAL_FLAGS@
# Compiler flags
AM_CXXFLAGS = \
-I$(top_srcdir)/include \
@AM_CXXFLAGS@
# Library name
lib_LTLIBRARIES = libhello-@HELLO_API_VERSION@.la
# Sources
libhello_@HELLO_API_VERSION@_la_SOURCES = \
hello.cpp
# Libraries
libhello_@HELLO_API_VERSION@_la_LDFLAGS = \
-version-info $(HELLO_SO_VERSION)
libhello_@HELLO_API_VERSION@_la_LIBADD = @LTLIBOBJS@
# Include directory and headers
libhello_@HELLO_API_VERSION@_la_includedir = $(includedir)
libhello_@HELLO_API_VERSION@_la_include_HEADERS = \
$(top_srcdir)/include/hello.h
# Data
helloconf_DATA = helloconf.sh
helloconfdir = $(exec_prefix)/bin
EXTRA_DIST = $(helloconf_DATA)
P.S.: I know it might have been better to upload an archive but I wanted to keep everything in one place.