xref: /freebsd/contrib/bmake/mkdeps.sh (revision c66ec88fed842fbaad62c30d510644ceb7bd2d71)
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
58Myname=`basename $0 .sh`
59Mydir=`dirname $0`
60
61case `echo -n .` in
62-n*)	N=; C="\c";;
63*)	N=-n; C=;;
64esac
65
66cc_include=-I/usr/include
67
68TF=/tmp/dep.$$
69EF=/tmp/deperr.$$
70> $EF
71
72case "$*" in
73*-n*)				# don't use rc file
74  rc=/dev/null
75  norc=yes;;
76*)
77  rc=$Mydir/.${Myname}rc
78  ;;
79esac
80
81update=
82Include=include
83
84if [ x"$norc" = x -a -f $rc ]; then
85  . $rc
86else
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
120fi
121
122clean_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.
138trap clean_up 0
139trap exit 2 3
140
141get_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
156gen_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
208for f in makefile Makefile
209do
210  test -s $f && { MAKEFILE=$f; break; }
211done
212
213MAKEFILE=${MAKEFILE:-makefile}
214IGNORE=${IGNORE:-"^-"}		# won't happen
215obj=o
216cpp_opts=			# incase cpp != grep
217vpath=
218append=
219progDep=
220
221set -- `getopt "AanNV:s:w:o:I:D:b:f:i:p" "$@"`
222for key in "$@"
223do
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
241done
242
243[ "$VPATH" ] && vpath=`IFS=:; set -- $VPATH; echo $*`
244
245[ "$append" ] || > .depend
246
247for file in $*
248do
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
281done
282
283if [ -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
313fi
314clean_up
315