build.sh revision 1.77 1 #! /usr/bin/env sh
2 # $NetBSD: build.sh,v 1.77 2002/12/25 00:42:50 lukem 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 uname_s=$(uname -s 2>/dev/null)
24 uname_m=$(uname -m 2>/dev/null)
25
26 # If $PWD is a valid name of the current directory, POSIX mandates that pwd
27 # return it by default which causes problems in the presence of symlinks.
28 # Unsetting PWD is simpler than changing every occurrence of pwd to use -P.
29 #
30 # XXX Except that doesn't work on Solaris.
31 unset PWD
32 if [ "${uname_s}" = "SunOS" ]; then
33 TOP=`pwd -P`
34 else
35 TOP=`pwd`
36 fi
37
38 getarch () {
39 # Translate a MACHINE into a default MACHINE_ARCH.
40 case $MACHINE in
41 acorn26|acorn32|cats|netwinder|shark|*arm)
42 MACHINE_ARCH=arm;;
43
44 sun2)
45 MACHINE_ARCH=m68000;;
46
47 amiga|atari|cesfic|hp300|sun3|*68k)
48 MACHINE_ARCH=m68k;;
49
50 mipsco|newsmips|sbmips|sgimips)
51 MACHINE_ARCH=mipseb;;
52
53 algor|arc|cobalt|evbmips|hpcmips|playstation2|pmax)
54 MACHINE_ARCH=mipsel;;
55
56 pc532)
57 MACHINE_ARCH=ns32k;;
58
59 bebox|prep|sandpoint|*ppc)
60 MACHINE_ARCH=powerpc;;
61
62 evbsh3|mmeye)
63 MACHINE_ARCH=sh3eb;;
64
65 dreamcast|hpcsh)
66 MACHINE_ARCH=sh3el;;
67
68 hp700)
69 MACHINE_ARCH=hppa;;
70
71 evbsh5)
72 MACHINE_ARCH=sh5el;;
73
74 alpha|i386|sparc|sparc64|vax|x86_64)
75 MACHINE_ARCH=$MACHINE;;
76
77 *) bomb "unknown target MACHINE: $MACHINE";;
78 esac
79 }
80
81 validatearch () {
82 # Ensure that the MACHINE_ARCH exists (and is supported by build.sh).
83 case $MACHINE_ARCH in
84 alpha|arm|armeb|hppa|i386|m68000|m68k|mipse[bl]|ns32k|powerpc|sh[35]e[bl]|sparc|sparc64|vax|x86_64)
85 ;;
86
87 *) bomb "unknown target MACHINE_ARCH: $MACHINE_ARCH";;
88 esac
89 }
90
91 getmakevar () {
92 $make -m ${TOP}/share/mk -s -f- _x_ <<EOF
93 _x_:
94 echo \${$1}
95 .include <bsd.prog.mk>
96 .include <bsd.kernobj.mk>
97 EOF
98 }
99
100 resolvepath () {
101 case $OPTARG in
102 /*) ;;
103 *) OPTARG="$TOP/$OPTARG";;
104 esac
105 }
106
107 usage () {
108 cat <<_usage_
109 Usage:
110 `basename $0` [-bdEnortUu] [-a arch] [-B buildid] [-D dest] [-i idir] [-j njob]
111 [-k kernel] [-M obj] [-m mach] [-O obj] [-R release] [-T tools] [-w wrapper]
112
113 -a arch set MACHINE_ARCH to arch (otherwise deduced from MACHINE)
114 -B buildid set BUILDID to buildid
115 -b build nbmake and nbmake wrapper script, if needed
116 -D dest set DESTDIR to dest
117 -d build a full distribution into DESTDIR (including etc files)
118 -E set "expert" mode; disables some DESTDIR checks
119 -i idir installworld from DESTDIR to idir
120 -j njob run up to njob jobs in parallel; see make(1)
121 -k kernel build a kernel using the named configuration file
122 -M obj set obj root directory to obj (sets MAKEOBJDIRPREFIX)
123 -m mach set MACHINE to mach (not required if NetBSD native)
124 -n show commands that would be executed, but do not execute them
125 -O obj set obj root directory to obj (sets a MAKEOBJDIR pattern)
126 -o set MKOBJDIRS=no (do not create objdirs at start of build)
127 -R release build a release (and set RELEASEDIR to release)
128 -r remove contents of TOOLDIR and DESTDIR before building
129 -T tools set TOOLDIR to tools
130 -t build and install tools only (implies -b)
131 -U set UNPRIVED
132 -u set UPDATE
133 -w wrapper create nbmake script at wrapper
134 (default TOOLDIR/bin/nbmake-MACHINE)
135
136 Note: if -T is unset and TOOLDIR is not set in the environment,
137 nbmake will be [re]built unconditionally.
138 _usage_
139 exit 1
140 }
141
142 # Set defaults.
143 MAKEFLAGS=
144 buildtarget=build
145 do_buildsystem=true
146 do_buildkernel=false
147 do_buildtools=false
148 do_rebuildmake=false
149 do_removedirs=false
150 expert_mode=false
151 makeenv=
152 makewrapper=
153 installworlddir=
154 opt_a=no
155 opts='a:B:bD:dEhi:j:k:M:m:nO:oR:rT:tUuw:'
156 runcmd=
157
158 if type getopts >/dev/null 2>&1; then
159 # Use POSIX getopts.
160 getoptcmd='getopts $opts opt && opt=-$opt'
161 optargcmd=':'
162 else
163 type getopt >/dev/null 2>&1 || bomb "/bin/sh shell is too old; try ksh or bash"
164
165 # Use old-style getopt(1) (doesn't handle whitespace in args).
166 args="`getopt $opts $*`"
167 [ $? = 0 ] || usage
168 set -- $args
169
170 getoptcmd='[ $# -gt 0 ] && opt="$1" && shift'
171 optargcmd='OPTARG="$1"; shift'
172 fi
173
174 # Parse command line options.
175 while eval $getoptcmd; do case $opt in
176 -a) eval $optargcmd
177 MACHINE_ARCH=$OPTARG; opt_a=yes;;
178
179 -B) eval $optargcmd
180 BUILDID=$OPTARG;;
181
182 -b) do_buildsystem=false;;
183
184 -D) eval $optargcmd; resolvepath
185 DESTDIR="$OPTARG"; export DESTDIR
186 makeenv="$makeenv DESTDIR";;
187
188 -d) buildtarget=distribution;;
189
190 -E) expert_mode=true;;
191
192 -i) eval $optargcmd
193 installworlddir=$OPTARG;;
194
195 -j) eval $optargcmd
196 parallel="-j $OPTARG";;
197
198 -k) do_buildkernel=true; do_buildsystem=false
199 eval $optargcmd
200 kernconfname=$OPTARG;;
201
202 -M) eval $optargcmd; resolvepath
203 MAKEOBJDIRPREFIX="$OPTARG"; export MAKEOBJDIRPREFIX
204 makeobjdir=$OPTARG
205 makeenv="$makeenv MAKEOBJDIRPREFIX";;
206
207 # -m overrides MACHINE_ARCH unless "-a" is specified
208 -m) eval $optargcmd
209 MACHINE=$OPTARG; [ "$opt_a" != "yes" ] && getarch;;
210
211 -n) runcmd=echo;;
212
213 -O) eval $optargcmd; resolvepath
214 MAKEOBJDIR="\${.CURDIR:C,^$TOP,$OPTARG,}"; export MAKEOBJDIR
215 makeobjdir=$OPTARG
216 makeenv="$makeenv MAKEOBJDIR";;
217
218 -o) MKOBJDIRS=no;;
219
220 -R) eval $optargcmd; resolvepath
221 RELEASEDIR=$OPTARG; export RELEASEDIR
222 makeenv="$makeenv RELEASEDIR"
223 buildtarget=release;;
224
225 -r) do_removedirs=true; do_rebuildmake=true;;
226
227 -T) eval $optargcmd; resolvepath
228 TOOLDIR="$OPTARG"; export TOOLDIR;;
229
230 -t) do_buildtools=true; do_buildsystem=false;;
231
232 -U) UNPRIVED=yes; export UNPRIVED
233 makeenv="$makeenv UNPRIVED";;
234
235 -u) UPDATE=yes; export UPDATE
236 makeenv="$makeenv UPDATE";;
237
238 -w) eval $optargcmd; resolvepath
239 makewrapper="$OPTARG";;
240
241 --) break;;
242 -'?'|-h) usage;;
243 esac; done
244
245 # Set up MACHINE*. On a NetBSD host, these are allowed to be unset.
246 if [ -z "$MACHINE" ]; then
247 if [ "${uname_s}" != "NetBSD" ]; then
248 echo "MACHINE must be set, or -m must be used, for cross builds."
249 echo ""; usage
250 fi
251 MACHINE=${uname_m}
252 fi
253 [ -n "$MACHINE_ARCH" ] || getarch
254 validatearch
255
256 # Set up default make(1) environment.
257 makeenv="$makeenv TOOLDIR MACHINE MACHINE_ARCH MAKEFLAGS"
258 if [ ! -z "$BUILDID" ]; then
259 makeenv="$makeenv BUILDID"
260 fi
261 MAKEFLAGS="-m $TOP/share/mk $MAKEFLAGS MKOBJDIRS=${MKOBJDIRS-yes}"
262 export MAKEFLAGS MACHINE MACHINE_ARCH
263
264 # Test make source file timestamps against installed nbmake binary,
265 # if TOOLDIR is pre-set.
266 #
267 # Note that we do NOT try to grovel "mk.conf" here to find out if TOOLDIR
268 # is set there, because it can contain make variable expansions and other
269 # stuff only parseable *after* we have a working nbmake. So this logic
270 # can only work if the user has pre-set TOOLDIR in the environment or
271 # used the -T option to build.sh.
272 #
273 make="${TOOLDIR-nonexistent}/bin/nbmake"
274 if [ -x $make ]; then
275 for f in usr.bin/make/*.[ch] usr.bin/make/lst.lib/*.[ch]; do
276 if [ $f -nt $make ]; then
277 do_rebuildmake=true; break
278 fi
279 done
280 else
281 do_rebuildmake=true
282 fi
283
284 # Build bootstrap nbmake if needed.
285 if $do_rebuildmake; then
286 $runcmd echo "===> Bootstrapping nbmake"
287 tmpdir="${TMPDIR-/tmp}/nbbuild$$"
288
289 $runcmd mkdir "$tmpdir" || bomb "cannot mkdir: $tmpdir"
290 trap "cd /; rm -r -f \"$tmpdir\"" 0
291 trap "exit 1" 1 2 3 15
292 $runcmd cd "$tmpdir"
293
294 $runcmd env CC="${HOST_CC-cc}" CPPFLAGS="${HOST_CPPFLAGS}" \
295 CFLAGS="${HOST_CFLAGS--O}" LDFLAGS="${HOST_LDFLAGS}" \
296 "$TOP/tools/make/configure" \
297 || bomb "configure of nbmake failed"
298 $runcmd sh buildmake.sh || bomb "build of nbmake failed"
299
300 make="$tmpdir/nbmake"
301 $runcmd cd "$TOP"
302 $runcmd rm -f usr.bin/make/*.o usr.bin/make/lst.lib/*.o
303 fi
304
305 EXTERNAL_TOOLCHAIN=`getmakevar EXTERNAL_TOOLCHAIN`
306 if [ "$runcmd" = "echo" ]; then
307 TOOLCHAIN_MISSING=no
308 else
309 TOOLCHAIN_MISSING=`getmakevar TOOLCHAIN_MISSING`
310 fi
311 if [ "${TOOLCHAIN_MISSING}" = "yes" -a \
312 "${EXTERNAL_TOOLCHAIN}" = "" ]; then
313 echo "ERROR: build.sh (in-tree cross-toolchain) is not yet available for"
314 echo
315 echo "MACHINE: ${MACHINE}"
316 echo "MACHINE_ARCH: ${MACHINE_ARCH}"
317 echo
318 echo "All builds for this platform should be done via a traditional make"
319 echo
320 echo "If you wish to use an external cross-toolchain, set"
321 echo
322 echo "EXTERNAL_TOOLCHAIN=<path to toolchain root>"
323 echo
324 echo "in either the environment or mk.conf and rerun"
325 echo
326 echo "$0 $*"
327 exit 1
328 fi
329
330 # If TOOLDIR isn't already set, make objdirs in "tools" in case the
331 # default setting from <bsd.own.mk> is used.
332 if [ -z "$TOOLDIR" ] && [ "$MKOBJDIRS" != "no" ]; then
333 $runcmd cd tools
334 $runcmd $make -m ${TOP}/share/mk obj NOSUBDIR= \
335 || bomb "make obj failed in tools"
336 $runcmd cd "$TOP"
337 fi
338
339 #
340 # If setting -M or -O to root an obj dir make sure the base directory is made
341 # before continuing as bsd.own.mk will need this to pick up _SRC_TOP_OBJ_
342 #
343 if [ "$MKOBJDIRS" != "no" ] && [ ! -z "$makeobjdir" ]; then
344 $runcmd mkdir -p "$makeobjdir"
345 fi
346
347 # Find DESTDIR and TOOLDIR.
348 if [ "$runcmd" = "echo" ]; then
349 # shown symbolically with -n because these may come from mk.conf
350 DESTDIR='$DESTDIR'
351 TOOLDIR='$TOOLDIR'
352 else
353 DESTDIR=`getmakevar DESTDIR`;
354 [ $? = 0 ] || bomb "getmakevar DESTDIR failed";
355 $runcmd echo "===> DESTDIR path: $DESTDIR"
356
357 TOOLDIR=`getmakevar TOOLDIR`;
358 [ $? = 0 ] || bomb "getmakevar TOOLDIR failed";
359 $runcmd echo "===> TOOLDIR path: $TOOLDIR"
360
361 export DESTDIR TOOLDIR
362 fi
363
364 # Check validity of TOOLDIR and DESTDIR.
365 if [ -z "$TOOLDIR" ] || [ "$TOOLDIR" = "/" ]; then
366 bomb "TOOLDIR '$TOOLDIR' invalid"
367 fi
368 removedirs="$TOOLDIR"
369
370 if [ -z "$DESTDIR" ] || [ "$DESTDIR" = "/" ]; then
371 if $do_buildsystem; then
372 if [ "$buildtarget" != "build" ] || \
373 [ "${uname_s}" != "NetBSD" ] || \
374 [ "${uname_m}" != "$MACHINE" ]; then
375 bomb "DESTDIR must be set to a non-root path for cross builds or -d or -R."
376 fi
377 if ! $expert_mode; then
378 bomb "DESTDIR must be set to a non-root path for non -E (expert) builds"
379 fi
380 $runcmd echo "===> WARNING: Building to /, in expert mode."
381 $runcmd echo "===> This may cause your system to break! Reasons include:"
382 $runcmd echo "===> - your kernel is not up to date"
383 $runcmd echo "===> - the libraries or toolchain have changed"
384 $runcmd echo "===> YOU HAVE BEEN WARNED!"
385 fi
386 else
387 removedirs="$removedirs $DESTDIR"
388 fi
389
390 if [ "$installworlddir" = "/" ]; then
391 if [ "${uname_s}" != "NetBSD" ] || \
392 [ "${uname_m}" != "$MACHINE" ]; then
393 bomb "-i installworlddir must be set to a non-root path for cross builds."
394 fi
395 fi
396
397 # Remove the target directories.
398 if $do_removedirs; then
399 for f in $removedirs; do
400 $runcmd echo "===> Removing $f"
401 $runcmd rm -r -f $f
402 done
403 fi
404
405 # Recreate $TOOLDIR.
406 $runcmd mkdir -p "$TOOLDIR/bin" || bomb "mkdir of '$TOOLDIR/bin' failed"
407
408 # Install nbmake if it was built.
409 if $do_rebuildmake; then
410 $runcmd rm -f "$TOOLDIR/bin/nbmake"
411 $runcmd cp $make "$TOOLDIR/bin/nbmake" \
412 || bomb "failed to install \$TOOLDIR/bin/nbmake"
413 make="$TOOLDIR/bin/nbmake"
414 $runcmd rm -r -f "$tmpdir"
415 trap 0 1 2 3 15
416 fi
417
418 # Build a nbmake wrapper script, usable by hand as well as by build.sh.
419 if [ -z "$makewrapper" ]; then
420 makewrapper="$TOOLDIR/bin/nbmake-$MACHINE"
421 if [ ! -z "$BUILDID" ]; then
422 makewrapper="$makewrapper-$BUILDID"
423 fi
424 fi
425
426 $runcmd rm -f "$makewrapper"
427 if [ "$runcmd" = "echo" ]; then
428 echo 'cat <<EOF >'$makewrapper
429 makewrapout=
430 else
431 makewrapout=">>\$makewrapper"
432 fi
433
434 eval cat <<EOF $makewrapout
435 #! /bin/sh
436 # Set proper variables to allow easy "make" building of a NetBSD subtree.
437 # Generated from: \$NetBSD: build.sh,v 1.77 2002/12/25 00:42:50 lukem Exp $
438 #
439
440 EOF
441 for f in $makeenv; do
442 eval echo "$f=\'\$`echo $f`\'\;\ export\ $f" $makewrapout
443 done
444 eval echo "USETOOLS=yes\; export USETOOLS" $makewrapout
445
446 eval cat <<'EOF' $makewrapout
447
448 exec "$TOOLDIR/bin/nbmake" ${1+"$@"}
449 EOF
450 [ "$runcmd" = "echo" ] && echo EOF
451 $runcmd chmod +x "$makewrapper"
452
453 if $do_buildsystem; then
454 # Build everything.
455 ${runcmd-exec} "$makewrapper" $parallel $buildtarget \
456 || bomb "failed to make $buildtarget"
457 else
458 # One or more of do_buildtools and do_buildkernel
459 # might be set. Do them in the appropriate order.
460 if $do_buildtools; then
461 if [ "$MKOBJDIRS" != "no" ]; then
462 $runcmd "$makewrapper" $parallel obj-tools \
463 || bomb "failed to make obj-tools"
464 fi
465 $runcmd cd tools
466 if [ "$UPDATE" = "" ]; then
467 $runcmd "$makewrapper" cleandir dependall install \
468 || bomb "failed to make tools"
469 else
470 $runcmd "$makewrapper" dependall install \
471 || bomb "failed to make tools"
472 fi
473 fi
474 if $do_buildkernel; then
475 if ! $do_buildtools; then
476 # Building tools every time we build a kernel
477 # is clearly unnecessary. We could try to
478 # figure out whether rebuilding the tools is
479 # necessary this time, but it doesn't seem
480 # worth the trouble. Instead, we say it's the
481 # user's responsibility to rebuild the tools if
482 # necessary.
483 $runcmd echo "===> Building kernel" \
484 "without building new tools"
485 fi
486 $runcmd echo "===> Building kernel ${kernconfname}"
487 # The correct value of KERNOBJDIR might depend on a
488 # prior "make obj" in TOP/etc.
489 if [ "$MKOBJDIRS" != "no" ] && [ ! -z "$makeobjdir" ]; then
490 $runcmd cd "$TOP/etc"
491 $runcmd "$makewrapper" obj \
492 || bomb "failed to make obj in etc"
493 $runcmd cd "$TOP"
494 fi
495 if [ "$runcmd" = "echo" ]; then
496 # shown symbolically with -n
497 # because getmakevar might not work yet
498 KERNCONFDIR='$KERNCONFDIR'
499 KERNOBJDIR='$KERNOBJDIR'
500 else
501 KERNCONFDIR="$( getmakevar KERNCONFDIR )"
502 [ $? = 0 ] || bomb "getmakevar KERNCONFDIR failed";
503 KERNOBJDIR="$( getmakevar KERNOBJDIR )"
504 [ $? = 0 ] || bomb "getmakevar KERNOBJDIR failed";
505 fi
506 case "${kernconfname}" in
507 */*)
508 kernconfpath="${kernconfname}"
509 kernconfbase="$( basename "${kernconfname}" )"
510 ;;
511 *)
512 kernconfpath="${KERNCONFDIR}/${kernconfname}"
513 kernconfbase="${kernconfname}"
514 ;;
515 esac
516 kernbuilddir="${KERNOBJDIR}/${kernconfbase}"
517 $runcmd echo "===> Kernel build directory: ${kernbuilddir}"
518 $runcmd mkdir -p "${kernbuilddir}" \
519 || bomb "cannot mkdir: ${kernbuilddir}"
520 if [ "$UPDATE" = "" ]; then
521 $runcmd cd "${kernbuilddir}"
522 $runcmd "$makewrapper" cleandir \
523 || bomb "make cleandir failed in " \
524 "${kernbuilddir}"
525 $runcmd cd "$TOP"
526 fi
527 $runcmd "${TOOLDIR}/bin/nbconfig" \
528 -b "${kernbuilddir}" \
529 -s "${TOP}/sys" "${kernconfpath}" \
530 || bomb "nbconfig failed for ${kernconfname}"
531 $runcmd cd "${kernbuilddir}"
532 $runcmd "$makewrapper" depend \
533 || bomb "make depend failed in ${kernbuilddir}"
534 $runcmd "$makewrapper" $parallel all \
535 || bomb "make all failed in ${kernbuilddir}"
536 $runcmd echo "===> New kernel should be in ${kernbuilddir}"
537 fi
538 fi
539
540 if [ -n "$installworlddir" ]; then
541 ${runcmd-exec} "$makewrapper" INSTALLWORLDDIR=${installworlddir} \
542 installworld || bomb "failed to make installworld"
543 fi
544