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.

Reply via email to