I have some pretty complicated makefiles which do autodependencies, but I
keep getting bitten by what seems to me like it should be a trivial
problem. Looking for suggestions.
The issue is essentially dealing with auto-dependencies, nested-includes
and source-cleaned directories (ie revision control).
A simplified example is demonstrated below.
The auto-dependencies part is that the makefile knows how to analyze
foo.c (gcc -M -MG) to automatically calculate the dependency list
(through foo.d). The -MG functionality is key -- if the .h file doesn't
exist, assume it can be created locally... so just treat it as a local
file.
The nested-includes is essentially that "foo.c" includes "first.h" and
"first.h" includes "second.h"... so that looking at "foo.c" alone does
NOT know anything about "second.h".
The source-clean/revision-control comes in in that I can rm all three
source files and say "make" and the makefile knows how to check them
out and go from there.
The problem is that you have to run make multiple times to get it to work.
Very unclean.
So if you start from scratch, the makefile:
checks out foo.c
makes foo.d (and assumes local "first.h")
rerun's make, which checks out first.h
But here, it knows foo.d depends on first.h, and the makefile is based on
rules in foo.d, which are now out-of-date. As is, it has satisfied all
stated dependencies in the old foo.d (generated before it knew what was
in first.h), so tries to compile before checking out second.h, so fails.
A second run notices that foo.d needs updating because of first.h, so
updates foo.d and _then_ knows to check out second.h.
I'm trying to avoid having to run this a second time... as is, it can take
many iterations for it to get through all of the source files and get
everything right.
Is there any way for me to tell make to pay attention to the fact that a
makefile/include file it's currently using has been updated, which means
that all info gleaned from that makefile is now suspect? I realize that a
blanket "need to regenerate an autodepend file, so stop everything and
remake the makefile" type of action would be devastatingly inefficient, but
is there an alternative?
It looks like I can modify the rule for foo.d to recursively run make until
the update does nothing. Essentially a:
foo.d : foo.c
gcc -M -MG foo.c | sed -e "s/$(notdir $(basename $<)).o *:/$(notdir
$(basename $@)).o $@: /g" > foo.d
$(MAKE) foo.d
But I suspect that'll end up having many more invokations of gmake than is
necessary, and I haven't yet convinced myself that'll work reliably
either.
Does anyone have any thoughts or suggestions on this?
Thanks a lot,
Jonathan
-----
Jonathan Walton GORDIAN
Design Engineer 20361 Irvine Ave.
[EMAIL PROTECTED] Santa Ana Heights, CA 92707
http://www.gordian.com/~jonboy (714)850-0205, Fax:(714)850-0533
Wanna be blacklisted by our spam filter? mail to [EMAIL PROTECTED]
***************************************************************************
simplified example files
> cat makefile
#!gmake
% :: RCS/%,v
co $@
foo.o : foo.c
gcc -c foo.c -o foo.o
foo.d : foo.c
gcc -M -MG foo.c | sed -e "s/$(notdir $(basename $<)).o *:/$(notdir
$(basename $@)).o $@: /g" > foo.d
clean:
rm -f foo.o foo.d foo.c first.h second.h
include foo.d
> cat foo.c
#include "first.h"
main ()
{
return 0;
}
> cat first.h
#include "second.h"
> cat second.h
/* secondary header file */
> make clean
rm -f foo.o foo.d foo.c first.h second.h
> make
makefile:15: foo.d: No such file or directory
co foo.c
RCS/foo.c,v --> foo.c
revision 1.1
done
gcc -M -MG foo.c | sed -e "s/foo.o *:/foo.o foo.d: /g" > foo.d
co first.h
RCS/first.h,v --> first.h
revision 1.1
done
gcc -c foo.c -o foo.o
In file included from foo.c:1:
first.h:1: second.h: No such file or directory
gmake: *** [foo.o] Error 1
> cat foo.d
foo.o foo.d: foo.c first.h
> make
gcc -M -MG foo.c | sed -e "s/foo.o *:/foo.o foo.d: /g" > foo.d
co second.h
RCS/second.h,v --> second.h
revision 1.1
done
gcc -c foo.c -o foo.o
> cat foo.d
foo.o foo.d: foo.c first.h second.h
> make
gmake: `foo.o' is up to date.