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: Matthias Andree
Subject: Re: automake 1.7.1 dependency tracking regression?
Date: Mon, 2 Dec 2002 19:30:32 +0100
User-agent: Mutt/1.5.1i

On Mon, 02 Dec 2002, Alexandre Duret-Lutz wrote:

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

It's exhaustive, but I fear, many people will skip over it because it's
very long.

First of all, I'll let you know how we solved it:

instead of generating .h files, we made static declarations in our .h
files and generated .c files instead. That way, the compilation does not
fail and dependency tracking works fine, even on the first build.

> 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.

Add: "It is NOT built when building any other target explicitly." 

>    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.

Add: "However, this may cause problems with dependency tracking,
building source files (.c for example) is usually simpler and more
robust."

> 
> 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'

This is dangerous. People may copy that code and paste it into their
Makefile.am without reading the "doesn't work" -- even with the comment.

> 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.

Good.

> 
>      % 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

Good.

>    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

This example can be omitted.

>    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

Good.

>      % 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

^ Example can be omitted.

>    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'.

It's "explicitly" (a trailing silent -e is usually dropped when making
an adverb, also in truly, wholly).

>      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

That's an important point, and it throws the question whether this
bindir.$(OBJEXT): bindir.h should be suggested in the first place.

It will be required when someone uses #defines in his .h files that
cannot be made functions, I believe, it's more useful to tell people to
declare a static .h like in

extern const char * const bindir;

and then generate the .c file, like:

bindir.c: Makefile
        echo "const char *const bindir = \"$(bindir)\" >$@ || rm -f $@


>    Another much safer solution to the same problem is to generate
> `bindir.h' from `configure'.

Indeed, but @address@hidden replacements are only valid in Makefile, and
they won't work in configure -- you might find ${prefix} in your output
where you don't expect it.




reply via email to

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