Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!purdue!haven!mimsy!chris From: chris@mimsy.UUCP (Chris Torek) Newsgroups: comp.unix.questions Subject: Re: Make dependencies and nested include files Message-ID: <20139@mimsy.UUCP> Date: 12 Oct 89 18:31:33 GMT References: <10115@encore.Encore.COM> Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742 Lines: 240 In article <10115@encore.Encore.COM> corbin@maxzilla.Encore.COM writes: >Does anyone have an idea of how to handle nexted include file >dependencies in make? Given that test includes test.h, test.h >include test1.h and test1.h include test2.h. When test2.h is >touched test.c will not get rebuilt given the follow make dependencies: > >test.c: test.h >test.h: test1.h >test1.h: test2.h Of course not---because this list is wrong. test.h does *not* depend on test1.h, and test1.h does *not* depend on test2.h. To see this, think about what you must do if you change test2.h. You do *not* need to apply some command sequence to rebuild test1.h. You do, however, have to apply some command sequence to build things that include any of test.h, test1.h, or test2.h. Now, if test.c included `tconc.h', and tconc.h were to be built by concatenating test.h and t12conc.h, and t12conc.h were to be built by concatenating test1.h and test2.h, you could correctly write: test.c: tconc.h tconc.h: test.h t12conc.h cat test.h t12conc.h > $@ t12conc.h: test1.h test2.h cat test1.h test2.h > $@ Now if you change test2.h, you really *do* have to apply some command sequence to build t12conc.h, and once you have done that, you again really do have to apply some command sequence to build tconc.h, and then again apply some command sequence to build test.o. >Can this be done in make or is > >test.c: test.h test1.h test2.h > >the only way it will work. > >The problem with the second example is that I'm working on a product >with hundreds of files and maintaining dependencies manuallly is tedious >and error prone. I would like to do automatic dependency generation. If you have `mkdep', this is easy. If not, build mkdep. There are several ways to build it: (best way) apply a C preprocessor to the source code; have it print a list of files included by each source file. On reasonably current BSD releases, `cc -M' does this. (More current releases have `mkdep'.) (next best way) apply the C preprocessor to the source code. Extract `#line' directives from the result, and build a list of files included by each source file. See shell script below. (not as good) use grep to extract all `#include' lines. Transform file names to path names. Recursively extract `#include' lines from these paths. This goofs on `#ifdef/#include/#endif' sequences, e.g. Here are the shell scripts. cat >getdep.sh <<'END' #! /bin/sh # getdep - get dependency lists. # find cpp cpp=unknown for where in /lib /usr/lib /bin /usr/bin; do if test -f $where/cpp; then cpp=$where/cpp; break; fi done if test $cpp = unknown; then echo "I cannot find cpp, sorry" 1>&2; exit 1 fi # handle arguments incl= for i do case "$i" in -I*) incl="$incl $i";; # you may have to add more cases below -O|-c|-M|-D*|-U*) ;; *) # assume source file # put '$dep' in front of dependencies dep=`echo "$i" | sed -e 's,/,\\\\/,g' -e 's/\.c$/.o/'` # Find includes, remove leading numerics, remove ./, # remove double quotes, and remove trailing numerics. # Sort that, discarding duplicates, and add '$dep'. $cpp $incl "$i" | sed -e ' /^#/!d s/# [0-9]* // s,"./,", s/"\(.*\)"/\1/ s/ [ 0-9]*$//' | sort -u | sed -e "s/^/$dep: /";; esac done END cat >mkdep.sh <<'ENDEND' #! /bin/sh - # # Copyright (c) 1987 Regents of the University of California. # All rights reserved. # # Redistribution and use in source and binary forms are permitted # provided that the above copyright notice and this paragraph are # duplicated in all such forms and that any documentation, # advertising materials, and other materials related to such # distribution and use acknowledge that the software was developed # by the University of California, Berkeley. The name of the # University may not be used to endorse or promote products derived # from this software without specific prior written permission. # THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED # WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. # # @(#)mkdep.sh 5.13 (Berkeley) 8/19/88 # # modified at Univ of Maryland # PATH=/bin:/usr/bin:/usr/ucb export PATH D=.depend # default dependency file is .depend while : do case "$1" in # -f allows you to select a makefile name -f) D=$2 shift; shift ;; # the -p flag produces "program: program.c" style dependencies # so .o's don't get produced -p) SED='s;\.o;;' shift ;; *) break ;; esac done if [ $# = 0 ] ; then echo 'usage: mkdep [-p] [-f depend_file] [cc_flags] file ...' exit 1 fi TMP=/tmp/mkdep$$ trap 'rm -f $TMP ; exit 1' 1 2 3 13 15 rm -f $TMP case $D in .depend) style=new;; *) if grep -s "DO NOT DELETE THIS LINE" $D; then style=old elif [ -f $D -a ! -w $D ]; then echo "mkdep: no writeable file \"$D\"" exit 1 fi;; esac exec >$TMP case $style in old) cp $D $D.bak sed -e '/DO NOT DELETE THIS LINE/,$d' < $D cat << _EOF_ # DO NOT DELETE THIS LINE -- mkdep uses it. # DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY. _EOF_ esac # If your compiler has -M, use it here instead of getdep.sh. # cc -M $* | /usr/local/lib/getdep $* | sed " s; \./; ;g $SED" | awk '{ if ($1 != prev) { if (rec != "") print rec; rec = $0; prev = $1; } else { if (length(rec $2) > 78) { print rec; rec = $0; } else rec = rec " " $2 } } END { print rec }' case $style in old) cat << _EOF_ # IF YOU PUT ANYTHING HERE IT WILL GO AWAY _EOF_ esac # copy to preserve permissions cp $TMP $D rm -f $TMP exit 0 ENDEND cat >make.sh <<'END' #! /bin/sh if [ -f .depend ]; then if [ -f makefile ]; then f="-f makefile -f .depend" else f="-f Makefile -f .depend" fi for i do case "$i" in -f*) f=;; esac done else f= fi exec /bin/make $f ${1+"$@"} MACHINE=${MACHINE-`machine`} END -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@cs.umd.edu Path: uunet!mimsy!chris