: # NAME: # mkdeps - generate dependencies # # SYNOPSIS: # mkdeps [options] file ... # # DESCRIPTION: # This script updates "makefile" with dependencies for # "file"(s). It borrows ideas from various makedepend scripts # and should be compatible with most. # # By default we use grep to extract include file names from # source files. We source an "rc" file '$Mydir/.${Myname}rc' which # can contain variable assignments such as: #.nf # # cpp_c=/usr/lib/cpp # cpp_cc=g++ -E # ... # #.fi # If the variable 'cpp_$suffix' is set, we use it as our cpp in # place of grep. The program referenced by these variables are # expected to produce output like: #.nf # # # 10 \"/usr/include/stdio.h\" 1 # #.fi # This allows us to skip most of our processing. For lex,yacc # and other source files, grep is probably just as quick and # certainly more portable. # # If the "rc" file does not exist, we create it and attempt to # find cpp or an equivalent cc invocation to assign to 'cpp_c'. # # AUTHOR: # Simon J. Gerraty # # RCSid: # $Id: mkdeps.sh,v 1.23 2002/11/29 06:58:59 sjg Exp $ # # @(#) Copyright (c) 1993 Simon J. Gerraty # # This file is provided in the hope that it will # be of use. There is absolutely NO WARRANTY. # Permission to copy, redistribute or otherwise # use this file is hereby granted provided that # the above copyright notice and this notice are # left intact. # # Please send copies of changes and bug-fixes to: # sjg@zen.void.oz.au # setglobal Myname = $[basename $0 .sh] setglobal Mydir = $[dirname $0] match $[echo -n .] { with -n* setglobal N = ''; setglobal C = '"\c'" with * setglobal N = '-n'; setglobal C = '' } setglobal cc_include = '-I/usr/include' setglobal TF = "/tmp/dep.$Pid" setglobal EF = "/tmp/deperr.$Pid" > $EF match "$ifsjoin(Argv)" { with *-n* # don't use rc file setglobal rc = '/dev/null' setglobal norc = 'yes' with * setglobal rc = "$Mydir/.$(Myname)rc" } setglobal update = '' setglobal Include = 'include' if test x"$norc" = x -a -f $rc { source $rc } else { # if /usr/lib/cpp or equivalent is available it is better than # grepping .c files. # See what (if anything) works on this system... echo : > $rc echo "# pre-processor for .c files" >> $rc # try a couple of sane places first for d in [/usr/libexec /usr/lib /usr/bin /lib /usr/ccs/bin] { setglobal cpp_c = "$d/cpp" test -x $cpp_c && break } if test -x $cpp_c { echo cpp_c=$cpp_c >> $rc } else { setglobal cpp_c = '' # rats see if cc can be used echo "#include " > /tmp/f$Pid.c echo "main() { return 0; }" >> /tmp/f$Pid.c # try some sensible args to cc for arg in [-E -P -M] { setglobal ok = $[$(REALCC:-${CC:-cc}) $arg /tmp/f$Pid.c !2 >/dev/null | grep '^#.*stdio.h' | tail -1] match $ok { with "" with * setglobal cpp_c = ""$(REALCC:-${CC:-cc}) $arg"" echo cpp_c="'$cpp_c'" >> $rc break } } rm -f /tmp/f$Pid.c } } proc clean_up { trap "" 2 3 trap 0 if test -s $EF { egrep -vi "included from|warning" $EF > $(EF)2 if test -s $(EF)2 { cat $EF > !2 rm -f .depend setglobal ests = '1' } } rm -f $TF $EF* exit ${ests:-0} } # this lot does not work on HPsUX - complain to Hp. trap clean_up 0 trap exit 2 3 proc get_incs { match $cpp { with grep # set IGNORE="<" to skip system includes egrep '^#[ ]*include' $ifsjoin(Argv) | egrep -v $IGNORE | \ sed -e 's/^.*include[^"<]*["<]//' -e 's/[">].*//g' with * # $cpp (eg. /usr/lib/cpp or cc -E) should produce output like: # 1 "/usr/include/stdio.h" 2 # set IGNORE=/usr/include to skip system includes $cpp $cpp_opts $cc_include $ifsjoin(Argv) !2 2>> $EF | egrep '^#.*\.h"' | sed 's,^#.*"\(.*\)".*,\1,' | egrep -v $IGNORE | sort -u } } proc gen_deps { setglobal llen = $1 shift for ifile in [$ifsjoin(Argv)] { match $cpp { with grep # this lot is not needed if not using grep. for dir in [$srcdir $dirlist /usr/include] { test -f "$dir/$ifile" && break } if test ! -f "$dir/$ifile" { # produce a useful error message (useful to emacs or error) setglobal iline = $[grep -n ".*include.*[\"<]$ifile[\">]" $file | cut -d: -f1] echo "\"$file\", line $iline: cannot find include file \"$ifile\"" >> $EF # no point adding to dependency list as the resulting makefile # would not work anyway... continue } setglobal ifile = "$dir/$ifile" # check whether we have done it yet match $[grep $ifile $TF] { with "" echo $ifile >> $TF with * continue # no repeats... } } setglobal len = $[expr "$ifile " : '.*] if test $[expr $llen + $len] -gt $(width:-76) { echo "\\" >> .depend echo $N " $C" >> .depend setglobal llen = '8' } echo $N "$ifile $C" >> .depend setglobal llen = $[expr $llen + $len] match $cpp { with grep # this lot is not needed unless using grep. setglobal ilist = $[get_incs $ifile] # recurse needed? test $ilist && setglobal llen = $[gen_deps $llen $ilist] } } echo $llen } for f in [makefile Makefile] { test -s $f && do { setglobal MAKEFILE = $f; break; } } setglobal MAKEFILE = $(MAKEFILE:-makefile) setglobal IGNORE = $(IGNORE:-"^-") # won't happen setglobal obj = 'o' setglobal cpp_opts = '' # incase cpp != grep setglobal vpath = '' setglobal append = '' setglobal progDep = '' set -- $[getopt "AanNV:s:w:o:I:D:b:f:i:p" @Argv] for key in [@Argv] { match $key { with -- shift; break with -A setglobal Include = '' # cat .depend >> $MAKEFILE with -a setglobal append = 'yes'; shift with -n shift # ignore rc with -N setglobal update = 'no'; shift # don't update $MAKEFILE with -I setglobal cpp_opts = ""$cpp_opts$1$2 ""; setglobal dirlist = ""$dirlist $2""; shift 2 with -o setglobal obj = $2; shift 2 with -s shift 2 # can't handle it anyway... with -w setglobal width = $2; shift 2 with -f setglobal MAKEFILE = $2; shift 2 with -b setglobal BASEDIR = $2; shift 2 with -i setglobal IGNORE = $2; shift 2 # ignore headers matching this... with -D setglobal cpp_opts = ""$cpp_opts$1$2 ""; shift 2 with -V setglobal VPATH = $2; shift 2 # where to look for files with -p setglobal progDep = 'yes'; shift } } test $VPATH && setglobal vpath = $[setglobal IFS = ':'; set -- $VPATH; echo $ifsjoin(Argv)] test $append || > .depend for file in [$ifsjoin(Argv)] { setglobal cpp = '' setglobal suffix = $[expr $file : '.*\.\([^.]*\)] eval cpp='"''$'{cpp_$(suffix):-grep}'"' if test ! -f $file -a $vpath { for d in [. $vpath] { test -f $d/$file && do { setglobal file = "$d/$file"; break; } } } setglobal srcdir = $[dirname $file] setglobal base = $[basename $file .$suffix] setglobal ilist = $[get_incs $file] if test $ilist { > $TF if test $progDep { echo "$base: $file \\" >> .depend } else { echo "$base.$obj: $file \\" >> .depend } echo $N " $C" >> .depend setglobal llen = '8' setglobal llen = $[gen_deps $llen $ilist] echo >> .depend echo >> .depend } elif test $progDep { echo "$base: $file" >> .depend echo >> .depend } } if test -s .depend { # ./foo.h looks ugly mv .depend $TF do { test $BASEDIR && sed -e "s;$BASEDIR;\$(BASEDIR);g" $TF || cat $TF; } | sed 's;\([^.]\)\./;\1;g' > .depend # # Save the manually updated section of the makefile # if test x$update != xno { trap "" 2 # don't die if we got this far # if make doesn't support include, then append our deps... setglobal depended = $[grep 'include.*\.depend' $MAKEFILE] test $depended && clean_up sed '/^# DO NOT DELETE.*depend.*$/,$d' < $MAKEFILE > $TF mv $TF $MAKEFILE cat << """ >> $MAKEFILE # DO NOT DELETE THIS LINE -- make depend depends on it # Do not edit anything below, it was added automagically by $Myname. """ >> $MAKEFILE # DO NOT DELETE THIS LINE -- make depend depends on it # Do not edit anything below, it was added automagically by $Myname. ! match $Include { with "" cat .depend >> $MAKEFILE with .include echo '.include ".depend"' >> $MAKEFILE with include echo include .depend >> $MAKEFILE } } } clean_up