bug-automake
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: automake 1.7.1 dependency tracking regression?


From: Alexandre Duret-Lutz
Subject: Re: automake 1.7.1 dependency tracking regression?
Date: Mon, 02 Dec 2002 12:34:24 +0100
User-agent: Gnus/5.090008 (Oort Gnus v0.08) Emacs/20.7 (i386-debian-linux-gnu)

Sorry for the delay.

>>> "Matthias" == Matthias Andree <address@hidden> writes:

[...]

 Matthias> Could this be documented in 1.7.2/1.8 automake.info
 Matthias> until it's fixed -- for example, the dependencies and
 Matthias> BUILT_SOURCES sections were good places to list this.

(It's unlikely to get fixed.)

Here is a proposal for the documentation.  Let me know what you
think.  It also answers your other questions.

Built sources
=============

   Occasionally a file which would otherwise be called `source' (e.g. a
C `.h' file) is actually derived from some other file.  Such files
should be listed in the `BUILT_SOURCES' variable.

   `BUILT_SOURCES' is actually a bit of a misnomer, as any file which
must be created early in the build process can be listed in this
variable.
   
   A source file listed in `BUILT_SOURCES' is created on `make all' or
`make check' before other targets are made.  However, such a source
file is not compiled unless explicitly requested by mentioning it in
some other `_SOURCES' variable.

   So, for instance, if you had header files which were created by a
script run at build time, then you would list these headers in
`BUILT_SOURCES', to ensure that they would be built before any other
compilations (perhaps ones using these headers) were started.

Example
-------

   Here is an example.  `foo.c' includes `bindir.h', which is built on
demand and not distributed.

     # This won't work.
     bin_PROGRAMS = foo
     foo_SOURCES = foo.c
     nodist_foo_SOURCES = bindir.h
     CLEANFILES = bindir.h
     bindir.h:
             echo "#define bindir \"@address@hidden"" >$@

   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 (*note 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

   A solution is to require `bindir.h' to be built before anything
else.  This is what `BUILT_SOURCES' is meant for.

     bin_PROGRAMS = foo
     foo_SOURCES = foo.c
     BUILT_SOURCES = bindir.h
     CLEANFILES = bindir.h
     bindir.h:
             echo "#define bindir \"@address@hidden"" >$@

   See how `bindir.h' get built first:

     % make
     echo >bindir.h "#define bindir \"/usr/local/bin\""
     make  all-am
     make[1]: Entering directory `/home/adl/tmp/automake-bindir'
     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/automake-bindir
   
   However, as said earlier, `$(BUILT_SOURCES)' applies only to the
`all' and `check' 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 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 such targets before `make all'.  However if this matters to
you, you can record such dependencies explicitely in the `Makefile.am'.

     bin_PROGRAMS = foo
     foo_SOURCES = foo.c
     bindir.$(OBJEXT): bindir.h
     CLEANFILES = bindir.h
     bindir.h:
             echo "#define bindir \"@address@hidden"" >$@
   
   You don't have to list _all_ the dependencies if `foo.o'
explicitely, only those which need to be built.  If a dependencies
already exist, it will not hinder the first compilation, and will be
recorded by the normal dependency tracking code.
   
   This game can turn to be a bit dangerous if you are not careful
enough.  `bindir.$(OBJEXT): bindir.h' overwrites any rule that Automake
may want to output to build `bindir.$(OBJEXT)'.  It happens to work
here because Automake doesn't have to output any `bindir.$(OBJEXT):'
target, as it relies on a suffix rule instead (i.e., `.c.$(OBJEXT):').
Always check the generated `Makefile.am' if you do this.
   
   Another much safer solution to the same problem is to generate
`bindir.h' from `configure'.

-- 
Alexandre Duret-Lutz





reply via email to

[Prev in Thread] Current Thread [Next in Thread]