automake: Built Sources Example

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