Make dependencies and nested include files

Chris Torek chris at mimsy.UUCP
Fri Oct 13 04:31:33 AEST 1989


In article <10115 at encore.Encore.COM> corbin at 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 at cs.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.unix.questions mailing list