Import bmake-20121010 to new vendor branch
[dragonfly.git] / contrib / bmake / mkdeps.sh
1 :
2 # NAME:
3 #       mkdeps - generate dependencies
4 #
5 # SYNOPSIS:
6 #       mkdeps [options] file ...
7 #
8 # DESCRIPTION:
9 #       This script updates "makefile" with dependencies for
10 #       "file"(s).  It borrows ideas from various makedepend scripts
11 #       and should be compatible with most.
12 #
13 #       By default we use grep to extract include file names from
14 #       source files.  We source an "rc" file '$Mydir/.${Myname}rc' which
15 #       can contain variable assignments such as:
16 #.nf
17 #   
18 #       cpp_c=/usr/lib/cpp
19 #       cpp_cc=g++ -E
20 #       ...
21 #
22 #.fi
23 #       If the variable 'cpp_$suffix' is set, we use it as our cpp in
24 #       place of grep.  The program referenced by these variables are
25 #       expected to produce output like:
26 #.nf
27 #
28 #       # 10 \"/usr/include/stdio.h\" 1
29 #
30 #.fi
31 #       This allows us to skip most of our processing.  For lex,yacc
32 #       and other source files, grep is probably just as quick and
33 #       certainly more portable.
34 #
35 #       If the "rc" file does not exist, we create it and attempt to
36 #       find cpp or an equivalent cc invocation to assign to 'cpp_c'.
37 #               
38 # AUTHOR:
39 #       Simon J. Gerraty <sjg@zen.void.oz.au>
40 #
41
42 # RCSid:
43 #       $Id: mkdeps.sh,v 1.23 2002/11/29 06:58:59 sjg Exp $
44 #
45 #       @(#) Copyright (c) 1993 Simon J. Gerraty
46 #
47 #       This file is provided in the hope that it will
48 #       be of use.  There is absolutely NO WARRANTY.
49 #       Permission to copy, redistribute or otherwise
50 #       use this file is hereby granted provided that 
51 #       the above copyright notice and this notice are
52 #       left intact. 
53 #      
54 #       Please send copies of changes and bug-fixes to:
55 #       sjg@zen.void.oz.au
56 #
57
58 Myname=`basename $0 .sh`
59 Mydir=`dirname $0`
60
61 case `echo -n .` in
62 -n*)    N=; C="\c";;
63 *)      N=-n; C=;;
64 esac
65
66 cc_include=-I/usr/include
67
68 TF=/tmp/dep.$$
69 EF=/tmp/deperr.$$
70 > $EF
71
72 case "$*" in
73 *-n*)                           # don't use rc file
74   rc=/dev/null
75   norc=yes;;
76 *)
77   rc=$Mydir/.${Myname}rc
78   ;;
79 esac
80
81 update=
82 Include=include
83
84 if [ x"$norc" = x -a -f $rc ]; then
85   . $rc
86 else
87   # if /usr/lib/cpp or equivalent is available it is better than
88   # grepping .c files.
89   # See what (if anything) works on this system...
90   echo : > $rc
91   echo "# pre-processor for .c files" >> $rc
92   # try a couple of sane places first
93   for d in /usr/libexec /usr/lib /usr/bin /lib /usr/ccs/bin
94   do
95     cpp_c=$d/cpp
96     [ -x $cpp_c ] && break
97   done
98   
99   if [ -x $cpp_c ]; then
100     echo cpp_c=$cpp_c >> $rc
101   else
102     cpp_c=
103     # rats see if cc can be used
104     echo "#include <stdio.h>" > /tmp/f$$.c
105     echo "main() { return 0; }" >> /tmp/f$$.c
106     # try some sensible args to cc
107     for arg in -E -P -M
108     do
109       ok=`${REALCC:-${CC:-cc}} $arg /tmp/f$$.c 2>/dev/null | grep '^#.*stdio.h' | tail -1`
110       case "$ok" in
111       "") ;;
112       *)
113         cpp_c="${REALCC:-${CC:-cc}} $arg"
114         echo cpp_c="'$cpp_c'" >> $rc
115         break;;
116       esac
117     done
118     rm -f /tmp/f$$.c
119   fi
120 fi
121
122 clean_up() {
123   trap "" 2 3
124   trap 0
125   if [ -s $EF ]; then
126           egrep -vi "included from|warning" $EF > ${EF}2
127           if [ -s ${EF}2 ]; then
128                   cat $EF >&2
129                   rm -f .depend
130                   ests=1
131           fi
132   fi
133   rm -f $TF $EF*
134   exit ${ests:-0}
135 }
136
137 # this lot does not work on HPsUX - complain to Hp.
138 trap clean_up 0
139 trap exit 2 3
140
141 get_incs() {
142   case "$cpp" in
143   grep)
144     # set IGNORE="<" to skip system includes
145     egrep '^#[  ]*include' $* | egrep -v "$IGNORE" | \
146       sed -e 's/^.*include[^"<]*["<]//' -e 's/[">].*//g';;
147   *)
148     # $cpp (eg. /usr/lib/cpp or cc -E) should produce output like:
149     # 1 "/usr/include/stdio.h" 2
150     # set IGNORE=/usr/include to skip system includes
151     $cpp $cpp_opts $cc_include $* 2>> $EF | egrep '^#.*\.h"' | sed 's,^#.*"\(.*\)".*,\1,' |
152       egrep -v "$IGNORE" | sort -u;;
153   esac
154 }
155
156 gen_deps() {
157   llen=$1
158   shift
159
160   for ifile in $*
161   do
162     case "$cpp" in
163     grep)
164       # this lot is not needed if not using grep.
165       for dir in $srcdir $dirlist /usr/include
166       do
167         [ -f "$dir/$ifile" ] && break
168       done
169
170       if [ ! -f "$dir/$ifile" ]; then
171         # produce a useful error message (useful to emacs or error)
172         iline=`grep -n ".*include.*[\"<]$ifile[\">]" $file | cut -d: -f1`
173         echo "\"$file\", line $iline: cannot find include file \"$ifile\"" >> $EF
174         # no point adding to dependency list as the resulting makefile
175         # would not work anyway...
176         continue
177       fi
178       ifile=$dir/$ifile
179       
180       # check whether we have done it yet
181       case `grep "$ifile" $TF` in
182       "") echo "$ifile" >> $TF;;
183       *)        continue;;              # no repeats...
184       esac
185       ;;
186     esac
187     
188     len=`expr "$ifile " : '.*'`
189     if [ "`expr $llen + $len`" -gt ${width:-76} ]; then
190       echo "\\" >> .depend
191       echo $N " $C" >> .depend
192       llen=8
193     fi
194     echo $N "$ifile $C" >> .depend
195     llen=`expr $llen + $len`
196     
197     case "$cpp" in
198     grep)
199       # this lot is not needed unless using grep.
200       ilist=`get_incs $ifile` # recurse needed?
201       [ "$ilist" ] && llen=`gen_deps $llen $ilist`
202       ;;
203     esac
204   done
205   echo $llen
206 }
207
208 for f in makefile Makefile
209 do
210   test -s $f && { MAKEFILE=$f; break; }
211 done
212
213 MAKEFILE=${MAKEFILE:-makefile}
214 IGNORE=${IGNORE:-"^-"}          # won't happen
215 obj=o
216 cpp_opts=                       # incase cpp != grep
217 vpath=
218 append=
219 progDep=
220
221 set -- `getopt "AanNV:s:w:o:I:D:b:f:i:p" "$@"`
222 for key in "$@"
223 do
224   case $key in
225   --)   shift; break;;
226   -A)   Include=;;              # cat .depend >> $MAKEFILE
227   -a)   append=yes; shift;;
228   -n)   shift;;                 # ignore rc
229   -N)   update=no; shift;;      # don't update $MAKEFILE
230   -I)   cpp_opts="$cpp_opts$1$2 "; dirlist="$dirlist $2"; shift 2;;
231   -o)   obj=$2; shift 2;;
232   -s)   shift 2;;               # can't handle it anyway...
233   -w)   width=$2; shift 2;;
234   -f)   MAKEFILE=$2; shift 2;;
235   -b)   BASEDIR=$2; shift 2;;
236   -i)   IGNORE="$2"; shift 2;;  # ignore headers matching this...
237   -D)   cpp_opts="$cpp_opts$1$2 "; shift 2;;
238   -V)   VPATH="$2"; shift 2;;   # where to look for files
239   -p)   progDep=yes; shift;;
240   esac
241 done
242
243 [ "$VPATH" ] && vpath=`IFS=:; set -- $VPATH; echo $*`
244
245 [ "$append" ] || > .depend
246
247 for file in $*
248 do
249   cpp=
250   suffix=`expr $file : '.*\.\([^.]*\)'`
251
252   eval cpp=\"\${cpp_${suffix}:-grep}\"
253   
254   if [ ! -f $file -a "$vpath" ]; then
255     for d in . $vpath
256     do
257       [ -f $d/$file ] && { file=$d/$file; break; }
258     done
259   fi
260   srcdir=`dirname $file`
261   base=`basename $file .$suffix`
262   
263   ilist=`get_incs $file`
264
265   if [ "$ilist" ]; then
266     > $TF
267     if [ "$progDep" ]; then
268       echo "$base:      $file \\" >> .depend
269     else
270       echo "$base.$obj: $file \\" >> .depend
271     fi
272     echo $N "   $C" >> .depend
273     llen=8
274     llen=`gen_deps $llen $ilist`
275     echo >> .depend
276     echo >> .depend
277   elif [ "$progDep" ]; then
278     echo "$base:        $file" >> .depend
279     echo >> .depend
280   fi
281 done
282
283 if [ -s .depend ]; then
284   # ./foo.h looks ugly
285   mv .depend $TF
286   { test "$BASEDIR" && sed -e "s;$BASEDIR;\$(BASEDIR);g" $TF || cat $TF; } |
287     sed 's;\([^.]\)\./;\1;g' > .depend 
288
289   #
290   # Save the manually updated section of the makefile
291   #
292   if [ x$update != xno ]; then
293     trap "" 2                   # don't die if we got this far
294
295     # if make doesn't support include, then append our deps...
296     depended=`grep 'include.*\.depend' $MAKEFILE`
297     test "$depended" && clean_up
298   
299     sed '/^# DO NOT DELETE.*depend.*$/,$d' < $MAKEFILE > $TF
300     mv $TF $MAKEFILE
301     cat <<! >> $MAKEFILE
302 # DO NOT DELETE THIS LINE -- make depend depends on it
303 # Do not edit anything below, it was added automagically by $Myname.
304
305 !
306   
307     case "$Include" in
308     "") cat .depend >> $MAKEFILE;;
309     .include)   echo '.include ".depend"' >> $MAKEFILE;;
310     include)    echo include .depend >> $MAKEFILE;;
311     esac
312   fi
313 fi
314 clean_up