Suppose that foo.c
includes bindir.h
, which is
installation-dependent and not distributed: it needs to be built. Here
bindir.h
defines the preprocessor macro bindir
to the
value of the make
variable bindir
(inherited from
configure
).
We suggest several implementations below. It's not meant to be an exhaustive listing of all ways to handle built sources, but it will give you a few ideas if you encounter this issue.
This first implementation will illustrate the bootstrap issue mentioned in the previous section (see Sources).
Here is a tentative Makefile.am
.
# This won't work. bin_PROGRAMS = foo foo_SOURCES = foo.c nodist_foo_SOURCES = bindir.h CLEANFILES = bindir.h bindir.h: Makefile echo '#define bindir "$(bindir)"' >$@
This setup doesn't work, because Automake doesn't know that foo.c
includes bindir.h
. Remember, automatic dependency tracking works
as a side-effect of compilation, so the dependencies of foo.o
will
be known only after foo.o
has been compiled (see Dependencies).
The symptom is as follows.
% make source='foo.c' object='foo.o' libtool=no \ depfile='.deps/foo.Po' tmpdepfile='.deps/foo.TPo' \ depmode=gcc /bin/sh ./depcomp \ gcc -I. -I. -g -O2 -c `test -f 'foo.c' || echo './'`foo.c foo.c:2: bindir.h: No such file or directory make: *** [foo.o] Error 1
BUILT_SOURCES
A solution is to require bindir.h
to be built before anything
else. This is what BUILT_SOURCES
is meant for (see Sources).
bin_PROGRAMS = foo foo_SOURCES = foo.c BUILT_SOURCES = bindir.h CLEANFILES = bindir.h bindir.h: Makefile echo '#define bindir "$(bindir)"' >$@
See how bindir.h
get built first:
% make echo '#define bindir "/usr/local/bin"' >bindir.h make all-am make[1]: Entering directory `/home/adl/tmp' source='foo.c' object='foo.o' libtool=no \ depfile='.deps/foo.Po' tmpdepfile='.deps/foo.TPo' \ depmode=gcc /bin/sh ./depcomp \ gcc -I. -I. -g -O2 -c `test -f 'foo.c' || echo './'`foo.c gcc -g -O2 -o foo foo.o make[1]: Leaving directory `/home/adl/tmp'
However, as said earlier, BUILT_SOURCES
applies only to the
all
, check
, and install
targets. It still fails
if you try to run make foo
explicitly:
% make clean test -z "bindir.h" || rm -f bindir.h test -z "foo" || rm -f foo rm -f *.o core *.core % : > .deps/foo.Po # Suppress previously recorded dependencies % make foo source='foo.c' object='foo.o' libtool=no \ depfile='.deps/foo.Po' tmpdepfile='.deps/foo.TPo' \ depmode=gcc /bin/sh ./depcomp \ gcc -I. -I. -g -O2 -c `test -f 'foo.c' || echo './'`foo.c foo.c:2: bindir.h: No such file or directory make: *** [foo.o] Error 1
Usually people are happy enough with BUILT_SOURCES
because they
never run targets such as make foo
before make all
, as in
the previous example. However if this matters to you, you can avoid
BUILT_SOURCES
and record such dependencies explicitly in the
Makefile.am
.
bin_PROGRAMS = foo foo_SOURCES = foo.c foo.$(OBJEXT): bindir.h CLEANFILES = bindir.h bindir.h: Makefile echo '#define bindir "$(bindir)"' >$@
You don't have to list all the dependencies of foo.o
explicitly, only those which might need to be built. If a dependency
already exists, it will not hinder the first compilation and will be
recorded by the normal dependency tracking code. (Note that after this
first compilation the dependency tracking code will also have recorded
the dependency between foo.o
and bindir.h
; so our explicit
dependency is really useful to the first build only.)
Adding explicit dependencies like this can be a bit dangerous if you are
not careful enough. This is due to the way Automake tries not to
overwrite your rules (it assumes you know better than it).
foo.$(OBJEXT): bindir.h
supersedes any rule Automake may want to
output to build foo.$(OBJEXT)
. It happens to work in this case
because Automake doesn't have to output any foo.$(OBJEXT):
target: it relies on a suffix rule instead (i.e., .c.$(OBJEXT):
).
Always check the generated Makefile.in
if you do this.
bindir.h
from configure
It's possible to define this preprocessor macro from configure
,
either in config.h
(see Defining Directories), or by processing a
bindir.h.in
file using AC_CONFIG_FILES
(see Configuration Actions).
At this point it should be clear that building bindir.h
from
configure
work well for this example. bindir.h
will exist
before you build any target, hence will not cause any dependency issue.
The Makefile can be shrunk as follows. We do not even have to mention
bindir.h
.
bin_PROGRAMS = foo foo_SOURCES = foo.c
However, it's not always possible to build sources from
configure
, especially when these sources are generated by a tool
that needs to be built first...
bindir.c
, not bindir.h
.
Another attractive idea is to define bindir
as a variable or
function exported from bindir.o
, and build bindir.c
instead of bindir.h
.
noinst_PROGRAMS = foo foo_SOURCES = foo.c bindir.h nodist_foo_SOURCES = bindir.c CLEANFILES = bindir.c bindir.c: Makefile echo 'const char bindir[] = "$(bindir)";' >$
bindir.h
contains just the variable's declaration and doesn't
need to be built, so it won't cause any trouble. bindir.o
is
always dependent on bindir.c
, so bindir.c
will get built
first.
There is no panacea, of course. Each solution has its merits and drawbacks.
You cannot use BUILT_SOURCES
if the ability to run make
foo
on a clean tree is important to you.
You won't add explicit dependencies if you are leery of overriding an Automake target by mistake.
Building files from ./configure
is not always possible, neither
is converting .h
files into .c
files.