build.sh revision 1.69 1 #! /usr/bin/env sh
2 # $NetBSD: build.sh,v 1.69 2002/10/02 16:57:29 thorpej Exp $
3 #
4 # Top level build wrapper, for a system containing no tools.
5 #
6 # This script should run on any POSIX-compliant shell. For systems
7 # with a strange /bin/sh, "ksh" or "bash" may be an ample alternative.
8 #
9 # Note, however, that due to the way the interpreter is invoked above,
10 # if a POSIX-compliant shell is the first in the PATH, you won't have
11 # to take any further action.
12 #
13
14 bomb () {
15 echo ""
16 echo "ERROR: $@"
17 echo "*** BUILD ABORTED ***"
18 exit 1
19 }
20 [ -d usr.bin/make ] || bomb "build.sh must be run from the top source level"
21 [ -f share/mk/bsd.own.mk ] || bomb "src/share/mk is missing; please re-fetch the source tree"
22
23 # If $PWD is a valid name of the current directory, POSIX mandates that pwd
24 # return it by default which causes problems in the presence of symlinks.
25 # Unsetting PWD is simpler than changing every occurrence of pwd to use -P.
26 #
27 # XXX Except that doesn't work on Solaris.
28 unset PWD
29 if [ "x`uname -s`" = "xSunOS" ]; then
30 TOP=`pwd -P`
31 else
32 TOP=`pwd`
33 fi
34
35 getarch () {
36 # Translate a MACHINE into a default MACHINE_ARCH.
37 case $MACHINE in
38 acorn26|acorn32|cats|netwinder|shark|*arm)
39 MACHINE_ARCH=arm;;
40
41 sun2)
42 MACHINE_ARCH=m68000;;
43
44 amiga|atari|cesfic|hp300|sun3|*68k)
45 MACHINE_ARCH=m68k;;
46
47 mipsco|newsmips|sbmips|sgimips)
48 MACHINE_ARCH=mipseb;;
49
50 algor|arc|cobalt|evbmips|hpcmips|playstation2|pmax)
51 MACHINE_ARCH=mipsel;;
52
53 pc532)
54 MACHINE_ARCH=ns32k;;
55
56 bebox|prep|sandpoint|walnut|*ppc)
57 MACHINE_ARCH=powerpc;;
58
59 evbsh3|mmeye)
60 MACHINE_ARCH=sh3eb;;
61
62 dreamcast|hpcsh)
63 MACHINE_ARCH=sh3el;;
64
65 hp700)
66 MACHINE_ARCH=hppa;;
67
68 evbsh5)
69 MACHINE_ARCH=sh5el;;
70
71 alpha|i386|sparc|sparc64|vax|x86_64)
72 MACHINE_ARCH=$MACHINE;;
73
74 *) bomb "unknown target MACHINE: $MACHINE";;
75 esac
76 }
77
78 validatearch () {
79 # Ensure that the MACHINE_ARCH exists (and is supported by build.sh).
80 case $MACHINE_ARCH in
81 alpha|arm|armeb|hppa|i386|m68000|m68k|mipse[bl]|ns32k|powerpc|sh[35]e[bl]|sparc|sparc64|vax|x86_64)
82 ;;
83
84 *) bomb "unknown target MACHINE_ARCH: $MACHINE_ARCH";;
85 esac
86 }
87
88 getmakevar () {
89 $make -m ${TOP}/share/mk -s -f- _x_ <<EOF
90 _x_:
91 echo \${$1}
92 .include <bsd.prog.mk>
93 EOF
94 }
95
96 resolvepath () {
97 case $OPTARG in
98 /*) ;;
99 *) OPTARG="$TOP/$OPTARG";;
100 esac
101 }
102
103 usage () {
104 echo "Usage:"
105 echo "$0 [-bdorUu] [-a arch] [-B buildid] [-j njob] [-m mach] "
106 echo " [-w wrapper] [-D dest] [-M obj] [-O obj] [-R release] [-T tools]"
107 echo ""
108 echo " -a: set MACHINE_ARCH to arch (otherwise deduced from MACHINE)"
109 echo " -B: set BUILDID to buildid"
110 echo " -b: build nbmake and nbmake wrapper script, if needed"
111 echo " -D: set DESTDIR to dest"
112 echo " -d: build a full distribution into DESTDIR (including etc files)"
113 echo " -j: Run up to njob jobs in parallel; see make(1)"
114 echo " -M: set obj root directory to obj (sets MAKEOBJDIRPREFIX)"
115 echo " -m: set MACHINE to mach (not required if NetBSD native)"
116 echo " -n: show commands that would be executed, but do not execute them"
117 echo " -O: set obj root directory to obj (sets a MAKEOBJDIR pattern)"
118 echo " -o: set MKOBJDIRS=no (do not create objdirs at start of build)"
119 echo " -R: build a release (and set RELEASEDIR to release)"
120 echo " -r: remove contents of TOOLDIR and DESTDIR before building"
121 echo " -T: set TOOLDIR to tools"
122 echo " -t: build and install tools only (implies -b)"
123 echo " -U: set UNPRIVED"
124 echo " -u: set UPDATE"
125 echo " -w: create nbmake script at wrapper (default TOOLDIR/bin/nbmake-MACHINE)"
126 echo ""
127 echo "Note: if -T is unset and TOOLDIR is not set in the environment,"
128 echo " nbmake will be [re]built unconditionally."
129 exit 1
130 }
131
132 # Set defaults.
133 MAKEFLAGS=
134 buildtarget=build
135 do_buildsystem=true
136 do_buildonlytools=false
137 do_rebuildmake=false
138 do_removedirs=false
139 makeenv=
140 makewrapper=
141 opt_a=no
142 opts='a:B:bdhj:m:nortuw:D:M:O:R:T:U'
143 runcmd=
144
145 if type getopts >/dev/null 2>&1; then
146 # Use POSIX getopts.
147 getoptcmd='getopts $opts opt && opt=-$opt'
148 optargcmd=':'
149 else
150 type getopt >/dev/null 2>&1 || bomb "/bin/sh shell is too old; try ksh or bash"
151
152 # Use old-style getopt(1) (doesn't handle whitespace in args).
153 args="`getopt $opts $*`"
154 [ $? = 0 ] || usage
155 set -- $args
156
157 getoptcmd='[ $# -gt 0 ] && opt="$1" && shift'
158 optargcmd='OPTARG="$1"; shift'
159 fi
160
161 # Parse command line options.
162 while eval $getoptcmd; do case $opt in
163 -a) eval $optargcmd
164 MACHINE_ARCH=$OPTARG; opt_a=yes;;
165
166 -B) eval $optargcmd
167 BUILDID=$OPTARG;;
168
169 -b) do_buildsystem=false;;
170
171 -d) buildtarget=distribution;;
172
173 -j) eval $optargcmd
174 parallel="-j $OPTARG";;
175
176 # -m overrides MACHINE_ARCH unless "-a" is specified
177 -m) eval $optargcmd
178 MACHINE=$OPTARG; [ "$opt_a" != "yes" ] && getarch;;
179
180 -n) runcmd=echo;;
181
182 -o) MKOBJDIRS=no;;
183
184 -r) do_removedirs=true; do_rebuildmake=true;;
185
186 -t) do_buildonlytools=true; do_buildsystem=false;;
187
188 -U) UNPRIVED=yes; export UNPRIVED
189 makeenv="$makeenv UNPRIVED";;
190
191 -u) UPDATE=yes; export UPDATE
192 makeenv="$makeenv UPDATE";;
193
194 -w) eval $optargcmd; resolvepath
195 makewrapper="$OPTARG";;
196
197 -D) eval $optargcmd; resolvepath
198 DESTDIR="$OPTARG"; export DESTDIR
199 makeenv="$makeenv DESTDIR";;
200
201 -M) eval $optargcmd; resolvepath
202 MAKEOBJDIRPREFIX="$OPTARG"; export MAKEOBJDIRPREFIX
203 makeobjdir=$OPTARG
204 makeenv="$makeenv MAKEOBJDIRPREFIX";;
205
206 -O) eval $optargcmd; resolvepath
207 MAKEOBJDIR="\${.CURDIR:C,^$TOP,$OPTARG,}"; export MAKEOBJDIR
208 makeobjdir=$OPTARG
209 makeenv="$makeenv MAKEOBJDIR";;
210
211 -R) eval $optargcmd; resolvepath
212 RELEASEDIR=$OPTARG; export RELEASEDIR
213 makeenv="$makeenv RELEASEDIR"
214 buildtarget=release;;
215
216 -T) eval $optargcmd; resolvepath
217 TOOLDIR="$OPTARG"; export TOOLDIR;;
218
219 --) break;;
220 -'?'|-h) usage;;
221 esac; done
222
223 # Set up MACHINE*. On a NetBSD host, these are allowed to be unset.
224 if [ -z "$MACHINE" ]; then
225 if [ "`uname -s 2>/dev/null`" != "NetBSD" ]; then
226 echo "MACHINE must be set, or -m must be used, for cross builds."
227 echo ""; usage
228 fi
229 MACHINE=`uname -m`
230 fi
231 [ -n "$MACHINE_ARCH" ] || getarch
232 validatearch
233
234 # Set up default make(1) environment.
235 makeenv="$makeenv TOOLDIR MACHINE MACHINE_ARCH MAKEFLAGS"
236 if [ ! -z "$BUILDID" ]; then
237 makeenv="$makeenv BUILDID"
238 fi
239 MAKEFLAGS="-m $TOP/share/mk $MAKEFLAGS MKOBJDIRS=${MKOBJDIRS-yes}"
240 export MAKEFLAGS MACHINE MACHINE_ARCH
241
242 # Test make source file timestamps against installed nbmake binary,
243 # if TOOLDIR is pre-set.
244 #
245 # Note that we do NOT try to grovel "mk.conf" here to find out if TOOLDIR
246 # is set there, because it can contain make variable expansions and other
247 # stuff only parseable *after* we have a working nbmake. So this logic
248 # can only work if the user has pre-set TOOLDIR in the environment or
249 # used the -T option to build.sh.
250 #
251 make="${TOOLDIR-nonexistent}/bin/nbmake"
252 if [ -x $make ]; then
253 for f in usr.bin/make/*.[ch] usr.bin/make/lst.lib/*.[ch]; do
254 if [ $f -nt $make ]; then
255 do_rebuildmake=true; break
256 fi
257 done
258 else
259 do_rebuildmake=true
260 fi
261
262 # Build bootstrap nbmake if needed.
263 if $do_rebuildmake; then
264 $runcmd echo "===> Bootstrapping nbmake"
265 tmpdir="${TMPDIR-/tmp}/nbbuild$$"
266
267 $runcmd mkdir "$tmpdir" || bomb "cannot mkdir: $tmpdir"
268 trap "cd /; rm -r -f \"$tmpdir\"" 0
269 trap "exit 1" 1 2 3 15
270 $runcmd cd "$tmpdir"
271
272 $runcmd env CC="${HOST_CC-cc}" CPPFLAGS="${HOST_CPPFLAGS}" CFLAGS="${HOST_CFLAGS--O}" LDFLAGS="${HOST_LDFLAGS}" \
273 "$TOP/tools/make/configure" || bomb "configure of nbmake failed"
274 $runcmd sh buildmake.sh || bomb "build of nbmake failed"
275
276 make="$tmpdir/nbmake"
277 $runcmd cd "$TOP"
278 $runcmd rm -f usr.bin/make/*.o usr.bin/make/lst.lib/*.o
279 fi
280
281 EXTERNAL_TOOLCHAIN=`getmakevar EXTERNAL_TOOLCHAIN`
282 if [ "$runcmd" = "echo" ]; then
283 TOOLCHAIN_MISSING=no
284 else
285 TOOLCHAIN_MISSING=`getmakevar TOOLCHAIN_MISSING`
286 fi
287 if [ "${TOOLCHAIN_MISSING}" = "yes" -a \
288 "${EXTERNAL_TOOLCHAIN}" = "" ]; then
289 echo "ERROR: build.sh (in-tree cross-toolchain) is not yet available for"
290 echo
291 echo "MACHINE: ${MACHINE}"
292 echo "MACHINE_ARCH: ${MACHINE_ARCH}"
293 echo
294 echo "All builds for this platform should be done via a traditional make"
295 echo
296 echo "If you wish to use an external cross-toolchain, set"
297 echo
298 echo "EXTERNAL_TOOLCHAIN=<path to toolchain root>"
299 echo
300 echo "in either the environment or mk.conf and rerun"
301 echo
302 echo "$0 $*"
303 exit 1
304 fi
305
306 # If TOOLDIR isn't already set, make objdirs in "tools" in case the
307 # default setting from <bsd.own.mk> is used.
308 if [ -z "$TOOLDIR" ] && [ "$MKOBJDIRS" != "no" ]; then
309 $runcmd cd tools
310 $runcmd $make -m ${TOP}/share/mk obj NOSUBDIR= || exit 1
311 $runcmd cd ..
312 fi
313
314 #
315 # If setting -M or -O to root an obj dir make sure the base directory is made
316 # before continuing as bsd.own.mk will need this to pick up _SRC_TOP_OBJ_
317 #
318 if [ "$MKOBJDIRS" != "no" ] && [ ! -z "$makeobjdir" ]; then
319 $runcmd mkdir -p "$makeobjdir"
320 fi
321
322 # Find DESTDIR and TOOLDIR.
323 if [ "$runcmd" = "echo" ]; then
324 # shown symbolically with -n because these may come from mk.conf
325 DESTDIR='$DESTDIR'
326 TOOLDIR='$TOOLDIR'
327 else
328 DESTDIR=`getmakevar DESTDIR`;
329 [ $? = 0 ] || bomb "getmakevar DESTDIR failed";
330 echo "===> DESTDIR path: $DESTDIR"
331
332 TOOLDIR=`getmakevar TOOLDIR`;
333 [ $? = 0 ] || bomb "getmakevar TOOLDIR failed";
334 echo "===> TOOLDIR path: $TOOLDIR"
335
336 export DESTDIR TOOLDIR
337 fi
338
339 # Check validity of TOOLDIR and DESTDIR.
340 if [ -z "$TOOLDIR" ] || [ "$TOOLDIR" = "/" ]; then
341 bomb "TOOLDIR '$TOOLDIR' invalid"
342 fi
343 removedirs="$TOOLDIR"
344
345 if [ -z "$DESTDIR" ] || [ "$DESTDIR" = "/" ]; then
346 if $do_buildsystem && \
347 ([ "$buildtarget" != "build" ] || \
348 [ "`uname -s 2>/dev/null`" != "NetBSD" ] || \
349 [ "`uname -m`" != "$MACHINE" ]); then
350 bomb "DESTDIR must be set to a non-root path for cross builds or -d or -R."
351 elif $do_buildsystem; then
352 echo "===> WARNING: Building to /."
353 echo "===> If your kernel is not up to date, this may cause the system to break!"
354 fi
355 else
356 removedirs="$removedirs $DESTDIR"
357 fi
358
359 # Remove the target directories.
360 if $do_removedirs; then
361 for f in $removedirs; do
362 echo "===> Removing $f"
363 $runcmd rm -r -f $f
364 done
365 fi
366
367 # Recreate $TOOLDIR.
368 $runcmd mkdir -p "$TOOLDIR/bin" || bomb "mkdir of '$TOOLDIR/bin' failed"
369
370 # Install nbmake if it was built.
371 if $do_rebuildmake; then
372 $runcmd rm -f "$TOOLDIR/bin/nbmake"
373 $runcmd cp $make "$TOOLDIR/bin/nbmake"
374 $runcmd rm -r -f "$tmpdir"
375 trap 0 1 2 3 15
376 fi
377
378 # Build a nbmake wrapper script, usable by hand as well as by build.sh.
379 if [ -z "$makewrapper" ]; then
380 makewrapper="$TOOLDIR/bin/nbmake-$MACHINE"
381 if [ ! -z "$BUILDID" ]; then
382 makewrapper="$makewrapper-$BUILDID"
383 fi
384 fi
385
386 $runcmd rm -f "$makewrapper"
387 if [ "$runcmd" = "echo" ]; then
388 echo 'cat <<EOF >'$makewrapper
389 makewrapout=
390 else
391 makewrapout=">>\$makewrapper"
392 fi
393
394 eval cat <<EOF $makewrapout
395 #! /bin/sh
396 # Set proper variables to allow easy "make" building of a NetBSD subtree.
397 # Generated from: \$NetBSD: build.sh,v 1.69 2002/10/02 16:57:29 thorpej Exp $
398 #
399
400 EOF
401 for f in $makeenv; do
402 eval echo "$f=\'\$`echo $f`\'\;\ export\ $f" $makewrapout
403 done
404 eval echo "USETOOLS=yes\; export USETOOLS" $makewrapout
405
406 eval cat <<'EOF' $makewrapout
407
408 exec "$TOOLDIR/bin/nbmake" ${1+"$@"}
409 EOF
410 [ "$runcmd" = "echo" ] && echo EOF
411 $runcmd chmod +x "$makewrapper"
412
413 if $do_buildsystem; then
414 ${runcmd-exec} "$makewrapper" $parallel $buildtarget
415 elif $do_buildonlytools; then
416 if [ "$MKOBJDIRS" != "no" ]; then
417 $runcmd "$makewrapper" $parallel obj-tools || exit 1
418 fi
419 $runcmd cd tools
420 if [ "$UPDATE" = "" ]; then
421 ${runcmd-exec} "$makewrapper" cleandir dependall install
422 else
423 ${runcmd-exec} "$makewrapper" dependall install
424 fi
425 fi
426