build.sh revision 1.173
1#! /usr/bin/env sh
2#	$NetBSD: build.sh,v 1.173 2007/09/01 08:15:27 jnemeth Exp $
3#
4# Copyright (c) 2001-2005 The NetBSD Foundation, Inc.
5# All rights reserved.
6#
7# This code is derived from software contributed to The NetBSD Foundation
8# by Todd Vierling and Luke Mewburn.
9#
10# Redistribution and use in source and binary forms, with or without
11# modification, are permitted provided that the following conditions
12# are met:
13# 1. Redistributions of source code must retain the above copyright
14#    notice, this list of conditions and the following disclaimer.
15# 2. Redistributions in binary form must reproduce the above copyright
16#    notice, this list of conditions and the following disclaimer in the
17#    documentation and/or other materials provided with the distribution.
18# 3. All advertising materials mentioning features or use of this software
19#    must display the following acknowledgement:
20#        This product includes software developed by the NetBSD
21#        Foundation, Inc. and its contributors.
22# 4. Neither the name of The NetBSD Foundation nor the names of its
23#    contributors may be used to endorse or promote products derived
24#    from this software without specific prior written permission.
25#
26# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36# POSSIBILITY OF SUCH DAMAGE.
37#
38#
39# Top level build wrapper, for a system containing no tools.
40#
41# This script should run on any POSIX-compliant shell.  If the
42# first "sh" found in the PATH is a POSIX-compliant shell, then
43# you should not need to take any special action.  Otherwise, you
44# should set the environment variable HOST_SH to a POSIX-compliant
45# shell, and invoke build.sh with that shell.  (Depending on your
46# system, one of /bin/ksh, /usr/local/bin/bash, or /usr/xpg4/bin/sh
47# might be a suitable shell.)
48#
49
50progname=${0##*/}
51toppid=$$
52results=/dev/null
53trap "exit 1" 1 2 3 15
54
55bomb()
56{
57	cat >&2 <<ERRORMESSAGE
58
59ERROR: $@
60*** BUILD ABORTED ***
61ERRORMESSAGE
62	kill ${toppid}		# in case we were invoked from a subshell
63	exit 1
64}
65
66
67statusmsg()
68{
69	${runcmd} echo "===> $@" | tee -a "${results}"
70}
71
72warning()
73{
74	statusmsg "Warning: $@"
75}
76
77# Find a program in the PATH, and print the result.  If not found,
78# print a default.  If $2 is defined (even if it is an empty string),
79# then that is the default; otherwise, $1 is used as the default.
80find_in_PATH()
81{
82	local prog="$1"
83	local result="${2-"$1"}"
84	local oldIFS="${IFS}"
85	local dir
86	IFS=":"
87	for dir in ${PATH}; do
88		if [ -x "${dir}/${prog}" ]; then
89			result="${dir}/${prog}"
90			break
91		fi
92	done
93	IFS="${oldIFS}"
94	echo "${result}"
95}
96
97# Try to find a working POSIX shell, and set HOST_SH to refer to it.
98# Assumes that uname_s, uname_m, and PWD have been set.
99set_HOST_SH()
100{
101	# Even if ${HOST_SH} is already defined, we still do the
102	# sanity checks at the end.
103
104	# Solaris has /usr/xpg4/bin/sh.
105	#
106	[ -z "${HOST_SH}" ] && [ x"${uname_s}" = x"SunOS" ] && \
107		[ -x /usr/xpg4/bin/sh ] && HOST_SH="/usr/xpg4/bin/sh"
108
109	# Try to get the name of the shell that's running this script,
110	# by parsing the output from "ps".  We assume that, if the host
111	# system's ps command supports -o comm at all, it will do so
112	# in the usual way: a one-line header followed by a one-line
113	# result, possibly including trailing white space.  And if the
114	# host system's ps command doesn't support -o comm, we assume
115	# that we'll get an error message on stderr and nothing on
116	# stdout.  (We don't try to use ps -o 'comm=' to suppress the
117	# header line, because that is less widely supported.)
118	#
119	# If we get the wrong result here, the user can override it by
120	# specifying HOST_SH in the environment.
121	#
122	[ -z "${HOST_SH}" ] && HOST_SH="$(
123		(ps -p $$ -o comm | sed -ne '2s/[ \t]*$//p') 2>/dev/null )"
124
125	# If nothing above worked, use "sh".  We will later find the
126	# first directory in the PATH that has a "sh" program.
127	#
128	[ -z "${HOST_SH}" ] && HOST_SH="sh"
129
130	# If the result so far is not an absolute path, try to prepend
131	# PWD or search the PATH.
132	#
133	case "${HOST_SH}" in
134	/*)	:
135		;;
136	*/*)	HOST_SH="${PWD}/${HOST_SH}"
137		;;
138	*)	HOST_SH="$(find_in_PATH "${HOST_SH}")"
139		;;
140	esac
141
142	# If we don't have an absolute path by now, bomb.
143	#
144	case "${HOST_SH}" in
145	/*)	:
146		;;
147	*)	bomb "HOST_SH=\"${HOST_SH}\" is not an absolute path."
148		;;
149	esac
150
151	# If HOST_SH is not executable, bomb.
152	#
153	[ -x "${HOST_SH}" ] ||
154	    bomb "HOST_SH=\"${HOST_SH}\" is not executable."
155}
156
157initdefaults()
158{
159	makeenv=
160	makewrapper=
161	makewrappermachine=
162	runcmd=
163	operations=
164	removedirs=
165
166	[ -d usr.bin/make ] || cd "$(dirname $0)"
167	[ -d usr.bin/make ] ||
168	    bomb "build.sh must be run from the top source level"
169	[ -f share/mk/bsd.own.mk ] ||
170	    bomb "src/share/mk is missing; please re-fetch the source tree"
171
172	# Find information about the build platform.  Note that "uname -p"
173	# is not part of POSIX, but NetBSD's uname -p prints MACHINE_ARCH,
174	# while uname -m prints MACHINE.
175	#
176	uname_s=$(uname -s 2>/dev/null)
177	uname_r=$(uname -r 2>/dev/null)
178	uname_m=$(uname -m 2>/dev/null)
179	uname_p=$(uname -p 2>/dev/null || uname -m 2>/dev/null)
180
181	# If $PWD is a valid name of the current directory, POSIX mandates
182	# that pwd return it by default which causes problems in the
183	# presence of symlinks.  Unsetting PWD is simpler than changing
184	# every occurrence of pwd to use -P.
185	#
186	# XXX Except that doesn't work on Solaris. Or many Linuces.
187	#
188	unset PWD
189	TOP=$(/bin/pwd -P 2>/dev/null || /bin/pwd 2>/dev/null)
190
191	# The user can set HOST_SH in the environment, or we try to
192	# guess an appropriate value.  Then we set several other
193	# variables from HOST_SH.
194	#
195	set_HOST_SH
196	setmakeenv HOST_SH "${HOST_SH}"
197	setmakeenv BSHELL "${HOST_SH}"
198	setmakeenv CONFIG_SHELL "${HOST_SH}"
199
200	# Set defaults.
201	#
202	toolprefix=nb
203
204	# Some systems have a small ARG_MAX.  -X prevents make(1) from
205	# exporting variables in the environment redundantly.
206	#
207	case "${uname_s}" in
208	Darwin | FreeBSD | CYGWIN*)
209		MAKEFLAGS=-X
210		;;
211	*)
212		MAKEFLAGS=
213		;;
214	esac
215
216	# do_{operation}=true if given operation is requested.
217	#
218	do_expertmode=false
219	do_rebuildmake=false
220	do_removedirs=false
221	do_tools=false
222	do_obj=false
223	do_build=false
224	do_distribution=false
225	do_release=false
226	do_kernel=false
227	do_releasekernel=false
228	do_install=false
229	do_sets=false
230	do_sourcesets=false
231	do_syspkgs=false
232	do_iso_image=false
233	do_iso_image_source=false
234	do_iso_dir=false
235	do_params=false
236
237	# Create scratch directory
238	#
239	tmpdir="${TMPDIR-/tmp}/nbbuild$$"
240	mkdir "${tmpdir}" || bomb "Cannot mkdir: ${tmpdir}"
241	trap "cd /; rm -r -f \"${tmpdir}\"" 0
242	results="${tmpdir}/build.sh.results"
243
244	# Set source directories
245	#
246	setmakeenv NETBSDSRCDIR "${TOP}"
247
248	# Find the version of NetBSD
249	#
250	DISTRIBVER="$(${HOST_SH} ${TOP}/sys/conf/osrelease.sh)"
251
252	# Set various environment variables to known defaults,
253	# to minimize (cross-)build problems observed "in the field".
254	#
255	unsetmakeenv INFODIR
256	unsetmakeenv LESSCHARSET
257	setmakeenv LC_ALL C
258}
259
260getarch()
261{
262	# Translate some MACHINE name aliases (known only to build.sh)
263	# into proper MACHINE and MACHINE_ARCH names.  Save the alias
264	# name in makewrappermachine.
265	#
266	case "${MACHINE}" in
267
268	evbarm-e[bl])
269		makewrappermachine=${MACHINE}
270		# MACHINE_ARCH is "arm" or "armeb", not "armel"
271		MACHINE_ARCH=arm${MACHINE##*-}
272		MACHINE_ARCH=${MACHINE_ARCH%el}
273		MACHINE=${MACHINE%-e[bl]}
274		;;
275
276	evbmips-e[bl]|sbmips-e[bl])
277		makewrappermachine=${MACHINE}
278		MACHINE_ARCH=mips${MACHINE##*-}
279		MACHINE=${MACHINE%-e[bl]}
280		;;
281
282	evbmips64-e[bl]|sbmips64-e[bl])
283		makewrappermachine=${MACHINE}
284		MACHINE_ARCH=mips64${MACHINE##*-}
285		MACHINE=${MACHINE%64-e[bl]}
286		;;
287
288	evbsh3-e[bl])
289		makewrappermachine=${MACHINE}
290		MACHINE_ARCH=sh3${MACHINE##*-}
291		MACHINE=${MACHINE%-e[bl]}
292		;;
293
294	esac
295
296	# Translate a MACHINE into a default MACHINE_ARCH.
297	#
298	case "${MACHINE}" in
299
300	acorn26|acorn32|cats|hpcarm|iyonix|netwinder|shark|zaurus)
301		MACHINE_ARCH=arm
302		;;
303
304	evbarm)		# unspecified MACHINE_ARCH gets LE
305		MACHINE_ARCH=${MACHINE_ARCH:=arm}
306		;;
307
308	hp700)
309		MACHINE_ARCH=hppa
310		;;
311
312	sun2)
313		MACHINE_ARCH=m68000
314		;;
315
316	amiga|atari|cesfic|hp300|luna68k|mac68k|mvme68k|news68k|next68k|sun3|x68k)
317		MACHINE_ARCH=m68k
318		;;
319
320	evbmips|sbmips)		# no default MACHINE_ARCH
321		;;
322
323	ews4800mips|mipsco|newsmips|sgimips)
324		MACHINE_ARCH=mipseb
325		;;
326
327	algor|arc|cobalt|hpcmips|playstation2|pmax)
328		MACHINE_ARCH=mipsel
329		;;
330
331	pc532)
332		MACHINE_ARCH=ns32k
333		;;
334
335	evbppc64|macppc64)
336		makewrappermachine=${MACHINE}
337		MACHINE=${MACHINE%64}
338		MACHINE_ARCH=powerpc64
339		;;
340
341	amigappc|bebox|evbppc|ibmnws|macppc|mvmeppc|ofppc|pmppc|prep|sandpoint)
342		MACHINE_ARCH=powerpc
343		;;
344
345	evbsh3)			# no default MACHINE_ARCH
346		;;
347
348	mmeye)
349		MACHINE_ARCH=sh3eb
350		;;
351
352	dreamcast|hpcsh|landisk)
353		MACHINE_ARCH=sh3el
354		;;
355
356	amd64)
357		MACHINE_ARCH=x86_64
358		;;
359
360	alpha|i386|sparc|sparc64|vax|ia64)
361		MACHINE_ARCH=${MACHINE}
362		;;
363
364	*)
365		bomb "Unknown target MACHINE: ${MACHINE}"
366		;;
367
368	esac
369}
370
371validatearch()
372{
373	# Ensure that the MACHINE_ARCH exists (and is supported by build.sh).
374	#
375	case "${MACHINE_ARCH}" in
376
377	alpha|arm|armeb|hppa|i386|m68000|m68k|mipse[bl]|mips64e[bl]|ns32k|powerpc|powerpc64|sh[35]e[bl]|sparc|sparc64|vax|x86_64|ia64)
378		;;
379
380	"")
381		bomb "No MACHINE_ARCH provided"
382		;;
383
384	*)
385		bomb "Unknown target MACHINE_ARCH: ${MACHINE_ARCH}"
386		;;
387
388	esac
389
390	# Determine valid MACHINE_ARCHs for MACHINE
391	#
392	case "${MACHINE}" in
393
394	evbarm)
395		arches="arm armeb"
396		;;
397
398	evbmips|sbmips)
399		arches="mipseb mipsel mips64eb mips64el"
400		;;
401
402	sgimips)
403		arches="mipseb mips64eb"
404		;;
405
406	evbsh3)
407		arches="sh3eb sh3el"
408		;;
409
410	macppc|evbppc)
411		arches="powerpc powerpc64"
412		;;
413	*)
414		oma="${MACHINE_ARCH}"
415		getarch
416		arches="${MACHINE_ARCH}"
417		MACHINE_ARCH="${oma}"
418		;;
419
420	esac
421
422	# Ensure that MACHINE_ARCH supports MACHINE
423	#
424	archok=false
425	for a in ${arches}; do
426		if [ "${a}" = "${MACHINE_ARCH}" ]; then
427			archok=true
428			break
429		fi
430	done
431	${archok} ||
432	    bomb "MACHINE_ARCH '${MACHINE_ARCH}' does not support MACHINE '${MACHINE}'"
433}
434
435nobomb_getmakevar()
436{
437	[ -x "${make}" ] || return 1
438	"${make}" -m ${TOP}/share/mk -s -B -f- _x_ <<EOF || return 1
439_x_:
440	echo \${$1}
441.include <bsd.prog.mk>
442.include <bsd.kernobj.mk>
443EOF
444}
445
446raw_getmakevar()
447{
448	[ -x "${make}" ] || bomb "raw_getmakevar $1: ${make} is not executable"
449	nobomb_getmakevar "$1" || bomb "raw_getmakevar $1: ${make} failed"
450}
451
452getmakevar()
453{
454	# raw_getmakevar() doesn't work properly if $make hasn't yet been
455	# built, which can happen when running with the "-n" option.
456	# getmakevar() deals with this by emitting a literal '$'
457	# followed by the variable name, instead of trying to find the
458	# variable's value.
459	#
460	if [ -x "${make}" ]; then
461		raw_getmakevar "$1"
462	else
463		echo "\$$1"
464	fi
465}
466
467setmakeenv()
468{
469	eval "$1='$2'; export $1"
470	makeenv="${makeenv} $1"
471}
472
473unsetmakeenv()
474{
475	eval "unset $1"
476	makeenv="${makeenv} $1"
477}
478
479# Convert possibly-relative path to absolute path by prepending
480# ${TOP} if necessary.  Also delete trailing "/", if any.
481resolvepath()
482{
483	case "${OPTARG}" in
484	/)
485		;;
486	/*)
487		OPTARG="${OPTARG%/}"
488		;;
489	*)
490		OPTARG="${TOP}/${OPTARG%/}"
491		;;
492	esac
493}
494
495usage()
496{
497	if [ -n "$*" ]; then
498		echo ""
499		echo "${progname}: $*"
500	fi
501	cat <<_usage_
502
503Usage: ${progname} [-EnorUux] [-a arch] [-B buildid] [-D dest] [-j njob]
504		[-M obj] [-m mach] [-N noisy] [-O obj] [-R release] [-T tools]
505		[-V var=[value]] [-w wrapper] [-X x11src] [-Z var]
506		operation [...]
507
508 Build operations (all imply "obj" and "tools"):
509    build               Run "make build".
510    distribution        Run "make distribution" (includes DESTDIR/etc/ files).
511    release             Run "make release" (includes kernels & distrib media).
512
513 Other operations:
514    help                Show this message and exit.
515    makewrapper         Create ${toolprefix}make-\${MACHINE} wrapper and ${toolprefix}make.
516                        Always performed.
517    obj                 Run "make obj".  [Default unless -o is used]
518    tools               Build and install tools.
519    install=idir        Run "make installworld" to \`idir' to install all sets
520			except \`etc'.  Useful after "distribution" or "release"
521    kernel=conf         Build kernel with config file \`conf'
522    releasekernel=conf  Install kernel built by kernel=conf to RELEASEDIR.
523    sets                Create binary sets in RELEASEDIR/MACHINE/binary/sets.
524			DESTDIR should be populated beforehand.
525    sourcesets          Create source sets in RELEASEDIR/source/sets.
526    syspkgs             Create syspkgs in RELEASEDIR/MACHINE/binary/syspkgs.
527    iso-image           Create CD-ROM image in RELEASEDIR/iso.
528    iso-image-source    Create CD-ROM image with source in RELEASEDIR/iso.
529    iso-dir=cddir	Add the contents of \`cddir' to an CD-ROM image.
530    params              Display various make(1) parameters.
531
532 Options:
533    -a arch     Set MACHINE_ARCH to arch.  [Default: deduced from MACHINE]
534    -B buildId  Set BUILDID to buildId.
535    -D dest     Set DESTDIR to dest.  [Default: destdir.MACHINE]
536    -E          Set "expert" mode; disables various safety checks.
537                Should not be used without expert knowledge of the build system.
538    -h          Print this help message.
539    -j njob     Run up to njob jobs in parallel; see make(1) -j.
540    -M obj      Set obj root directory to obj; sets MAKEOBJDIRPREFIX.
541                Unsets MAKEOBJDIR.
542    -m mach     Set MACHINE to mach; not required if NetBSD native.
543    -N noisy	Set the noisyness (MAKEVERBOSE) level of the build:
544		    0	Quiet
545		    1	Operations are described, commands are suppressed
546		    2	Full output
547		[Default: 2]
548    -n          Show commands that would be executed, but do not execute them.
549    -O obj      Set obj root directory to obj; sets a MAKEOBJDIR pattern.
550                Unsets MAKEOBJDIRPREFIX.
551    -o          Set MKOBJDIRS=no; do not create objdirs at start of build.
552    -R release  Set RELEASEDIR to release.  [Default: releasedir]
553    -r          Remove contents of TOOLDIR and DESTDIR before building.
554    -T tools    Set TOOLDIR to tools.  If unset, and TOOLDIR is not set in
555                the environment, ${toolprefix}make will be (re)built unconditionally.
556    -U          Set MKUNPRIVED=yes; build without requiring root privileges,
557    		install from an UNPRIVED build with proper file permissions.
558    -u          Set MKUPDATE=yes; do not run "make clean" first.
559		Without this, everything is rebuilt, including the tools.
560    -V v=[val]  Set variable \`v' to \`val'.
561    -w wrapper  Create ${toolprefix}make script as wrapper.
562                [Default: \${TOOLDIR}/bin/${toolprefix}make-\${MACHINE}]
563    -X x11src   Set X11SRCDIR to x11src.  [Default: /usr/xsrc]
564    -x          Set MKX11=yes; build X11R6 from X11SRCDIR
565    -Z v        Unset ("zap") variable \`v'.
566
567_usage_
568	exit 1
569}
570
571parseoptions()
572{
573	opts='a:B:bD:dEhi:j:k:M:m:N:nO:oR:rT:tUuV:w:xX:Z:'
574	opt_a=no
575
576	if type getopts >/dev/null 2>&1; then
577		# Use POSIX getopts.
578		#
579		getoptcmd='getopts ${opts} opt && opt=-${opt}'
580		optargcmd=':'
581		optremcmd='shift $((${OPTIND} -1))'
582	else
583		type getopt >/dev/null 2>&1 ||
584		    bomb "/bin/sh shell is too old; try ksh or bash"
585
586		# Use old-style getopt(1) (doesn't handle whitespace in args).
587		#
588		args="$(getopt ${opts} $*)"
589		[ $? = 0 ] || usage
590		set -- ${args}
591
592		getoptcmd='[ $# -gt 0 ] && opt="$1" && shift'
593		optargcmd='OPTARG="$1"; shift'
594		optremcmd=':'
595	fi
596
597	# Parse command line options.
598	#
599	while eval ${getoptcmd}; do
600		case ${opt} in
601
602		-a)
603			eval ${optargcmd}
604			MACHINE_ARCH=${OPTARG}
605			opt_a=yes
606			;;
607
608		-B)
609			eval ${optargcmd}
610			BUILDID=${OPTARG}
611			;;
612
613		-b)
614			usage "'-b' has been replaced by 'makewrapper'"
615			;;
616
617		-D)
618			eval ${optargcmd}; resolvepath
619			setmakeenv DESTDIR "${OPTARG}"
620			;;
621
622		-d)
623			usage "'-d' has been replaced by 'distribution'"
624			;;
625
626		-E)
627			do_expertmode=true
628			;;
629
630		-i)
631			usage "'-i idir' has been replaced by 'install=idir'"
632			;;
633
634		-j)
635			eval ${optargcmd}
636			parallel="-j ${OPTARG}"
637			;;
638
639		-k)
640			usage "'-k conf' has been replaced by 'kernel=conf'"
641			;;
642
643		-M)
644			eval ${optargcmd}; resolvepath
645			makeobjdir="${OPTARG}"
646			unsetmakeenv MAKEOBJDIR
647			setmakeenv MAKEOBJDIRPREFIX "${OPTARG}"
648			;;
649
650			# -m overrides MACHINE_ARCH unless "-a" is specified
651		-m)
652			eval ${optargcmd}
653			MACHINE="${OPTARG}"
654			[ "${opt_a}" != "yes" ] && getarch
655			;;
656
657		-N)
658			eval ${optargcmd}
659			case "${OPTARG}" in
660			0|1|2)
661				setmakeenv MAKEVERBOSE "${OPTARG}"
662				;;
663			*)
664				usage "'${OPTARG}' is not a valid value for -N"
665				;;
666			esac
667			;;
668
669		-n)
670			runcmd=echo
671			;;
672
673		-O)
674			eval ${optargcmd}; resolvepath
675			makeobjdir="${OPTARG}"
676			unsetmakeenv MAKEOBJDIRPREFIX
677			setmakeenv MAKEOBJDIR "\${.CURDIR:C,^$TOP,$OPTARG,}"
678			;;
679
680		-o)
681			MKOBJDIRS=no
682			;;
683
684		-R)
685			eval ${optargcmd}; resolvepath
686			setmakeenv RELEASEDIR "${OPTARG}"
687			;;
688
689		-r)
690			do_removedirs=true
691			do_rebuildmake=true
692			;;
693
694		-T)
695			eval ${optargcmd}; resolvepath
696			TOOLDIR="${OPTARG}"
697			export TOOLDIR
698			;;
699
700		-t)
701			usage "'-t' has been replaced by 'tools'"
702			;;
703
704		-U)
705			setmakeenv MKUNPRIVED yes
706			;;
707
708		-u)
709			setmakeenv MKUPDATE yes
710			;;
711
712		-V)
713			eval ${optargcmd}
714			case "${OPTARG}" in
715		    # XXX: consider restricting which variables can be changed?
716			[a-zA-Z_][a-zA-Z_0-9]*=*)
717				setmakeenv "${OPTARG%%=*}" "${OPTARG#*=}"
718				;;
719			*)
720				usage "-V argument must be of the form 'var=[value]'"
721				;;
722			esac
723			;;
724
725		-w)
726			eval ${optargcmd}; resolvepath
727			makewrapper="${OPTARG}"
728			;;
729
730		-X)
731			eval ${optargcmd}; resolvepath
732			setmakeenv X11SRCDIR "${OPTARG}"
733			;;
734
735		-x)
736			setmakeenv MKX11 yes
737			;;
738
739		-Z)
740			eval ${optargcmd}
741		    # XXX: consider restricting which variables can be unset?
742			unsetmakeenv "${OPTARG}"
743			;;
744
745		--)
746			break
747			;;
748
749		-'?'|-h)
750			usage
751			;;
752
753		esac
754	done
755
756	# Validate operations.
757	#
758	eval ${optremcmd}
759	while [ $# -gt 0 ]; do
760		op=$1; shift
761		operations="${operations} ${op}"
762
763		case "${op}" in
764
765		help)
766			usage
767			;;
768
769		makewrapper|obj|tools|build|distribution|release|sets|sourcesets|syspkgs|params)
770			;;
771
772		iso-image)
773			op=iso_image	# used as part of a variable name
774			;;
775
776		iso-image-source)
777			op=iso_image_source   # used as part of a variable name
778			;;
779
780		iso-dir=*)
781			arg=${op#*=}
782			op=iso_dir	# used as part of a variable name
783			[ -n "${arg}" ] ||
784			    bomb "Must supply a directory with \`${op}=...'"
785			OPTARG=$arg; resolvepath
786			iso_dir=$OPTARG
787			;;
788
789		kernel=*|releasekernel=*)
790			arg=${op#*=}
791			op=${op%%=*}
792			[ -n "${arg}" ] ||
793			    bomb "Must supply a kernel name with \`${op}=...'"
794			;;
795
796		install=*)
797			arg=${op#*=}
798			op=${op%%=*}
799			[ -n "${arg}" ] ||
800			    bomb "Must supply a directory with \`install=...'"
801			;;
802
803		*)
804			usage "Unknown operation \`${op}'"
805			;;
806
807		esac
808		eval do_${op}=true
809	done
810	[ -n "${operations}" ] || usage "Missing operation to perform."
811
812	# Set up MACHINE*.  On a NetBSD host, these are allowed to be unset.
813	#
814	if [ -z "${MACHINE}" ]; then
815		[ "${uname_s}" = "NetBSD" ] ||
816		    bomb "MACHINE must be set, or -m must be used, for cross builds."
817		MACHINE=${uname_m}
818	fi
819	[ -n "${MACHINE_ARCH}" ] || getarch
820	validatearch
821
822	# Set up default make(1) environment.
823	#
824	makeenv="${makeenv} TOOLDIR MACHINE MACHINE_ARCH MAKEFLAGS"
825	[ -z "${BUILDID}" ] || makeenv="${makeenv} BUILDID"
826	MAKEFLAGS="-de -m ${TOP}/share/mk ${MAKEFLAGS} MKOBJDIRS=${MKOBJDIRS-yes}"
827	export MAKEFLAGS MACHINE MACHINE_ARCH
828}
829
830sanitycheck()
831{
832	# If the PATH contains any non-absolute components (including,
833	# but not limited to, "." or ""), then complain.  As an exception,
834	# allow "" or "." as the last component of the PATH.  This is fatal
835	# if expert mode is not in effect.
836	#
837	local path="${PATH}"
838	path="${path%:}"	# delete trailing ":"
839	path="${path%:.}"	# delete trailing ":."
840	case ":${path}:/" in
841	*:[!/]*)
842		if ${do_expertmode}; then
843			warning "PATH contains non-absolute components"
844		else
845			bomb "PATH environment variable must not" \
846			     "contain non-absolute components"
847		fi
848		;;
849	esac
850}
851
852# Try to set a value for TOOLDIR.  This is difficult because of a cyclic
853# dependency: TOOLDIR may be affected by settings in /etc/mk.conf, so
854# we would like to use getmakevar to get the value of TOOLDIR, but we
855# can't use getmakevar before we have an up to date version of nbmake;
856# we might already have an up to date version of nbmake in TOOLDIR, but
857# we don't yet know where TOOLDIR is.
858#
859# In principle, we could break the cycle by building a copy of nbmake
860# in a temporary directory.  However, people who use the default value
861# of TOOLDIR do not like to have nbmake rebuilt every time they run
862# build.sh.
863#
864# We try to please everybody as follows:
865#
866# * If TOOLDIR was set in the environment or on the command line, use
867#   that value.
868# * Otherwise try to guess what TOOLDIR would be if not overridden by
869#   /etc/mk.conf, and check whether the resulting directory contains
870#   a copy of ${toolprefix}make (this should work for everybody who
871#   doesn't override TOOLDIR via /etc/mk.conf);
872# * Failing that, search for ${toolprefix}make, nbmake, bmake, or make,
873#   in the PATH (this might accidentally find a non-NetBSD version of
874#   make, which will lead to failure in the next step);
875# * If a copy of make was found above, try to use it with
876#   nobomb_getmakevar to find the correct value for TOOLDIR;
877# * If all else fails, leave TOOLDIR unset.  Our caller is expected to
878#   be able to cope with this.
879#
880try_set_TOOLDIR()
881{
882	[ -n "${TOOLDIR}" ] && return
883
884	# Set guess_TOOLDIR, in the same way that <bsd.own.mk> would set
885	# TOOLDIR if /etc/mk.conf sisn't interfere.
886	local topobjdir="${TOP}"
887	[ -n "${makeobjdir}" ] && topobjdir="${topobjdir}/${makeobjdir}"
888	local host_ostype="${uname_s}-$(
889		echo "${uname_r}" | sed -e 's/([^)]*)//g' -e 's/ /_/g'
890		)$(
891		echo "${uname_p}" | sed -e 's/([^)]*)//g' -e 's/ /_/g'
892		)"
893	local guess_TOOLDIR="${topobjdir}/tooldir.${host_ostype}"
894
895	# Look for a suitable ${toolprefix}make, nbmake, bmake, or make.
896	guess_make="${guess_TOOLDIR}/bin/${toolprefix}make"
897	[ -x "${guess_make}" ] || guess_make=""
898	: ${guess_make:=$(find_in_PATH ${toolprefix}make '')}
899	: ${guess_make:=$(find_in_PATH nbmake '')}
900	: ${guess_make:=$(find_in_PATH bmake '')}
901	: ${guess_make:=$(find_in_PATH make '')}
902
903	# Use ${guess_make} with nobomb_getmakevar
904	if [ -x "${guess_make}" ]; then
905		TOOLDIR=$(make="${guess_make}" nobomb_getmakevar TOOLDIR)
906		[ -n "${TOOLDIR}" ] || unset TOOLDIR
907	fi
908}
909
910rebuildmake()
911{
912	# Test make source file timestamps against installed ${toolprefix}make
913	# binary, if TOOLDIR is pre-set or if try_set_TOOLDIR can set it.
914	#
915	try_set_TOOLDIR
916	make="${TOOLDIR-nonexistent}/bin/${toolprefix}make"
917	if [ -x "${make}" ]; then
918		for f in usr.bin/make/*.[ch] usr.bin/make/lst.lib/*.[ch]; do
919			if [ "${f}" -nt "${make}" ]; then
920				statusmsg "${make} outdated (older than ${f}), needs building."
921				do_rebuildmake=true
922				break
923			fi
924		done
925	else
926		statusmsg "No ${make}, needs building."
927		do_rebuildmake=true
928	fi
929
930	# Build bootstrap ${toolprefix}make if needed.
931	if ${do_rebuildmake}; then
932		statusmsg "Bootstrapping ${toolprefix}make"
933		${runcmd} cd "${tmpdir}"
934		${runcmd} env CC="${HOST_CC-cc}" CPPFLAGS="${HOST_CPPFLAGS}" \
935			CFLAGS="${HOST_CFLAGS--O}" LDFLAGS="${HOST_LDFLAGS}" \
936			${HOST_SH} "${TOP}/tools/make/configure" ||
937		    bomb "Configure of ${toolprefix}make failed"
938		${runcmd} ${HOST_SH} buildmake.sh ||
939		    bomb "Build of ${toolprefix}make failed"
940		make="${tmpdir}/${toolprefix}make"
941		${runcmd} cd "${TOP}"
942		${runcmd} rm -f usr.bin/make/*.o usr.bin/make/lst.lib/*.o
943	fi
944}
945
946validatemakeparams()
947{
948	if [ "${runcmd}" = "echo" ]; then
949		TOOLCHAIN_MISSING=no
950		EXTERNAL_TOOLCHAIN=""
951	else
952		TOOLCHAIN_MISSING=$(raw_getmakevar TOOLCHAIN_MISSING)
953		EXTERNAL_TOOLCHAIN=$(raw_getmakevar EXTERNAL_TOOLCHAIN)
954	fi
955	if [ "${TOOLCHAIN_MISSING}" = "yes" ] && \
956	   [ -z "${EXTERNAL_TOOLCHAIN}" ]; then
957		${runcmd} echo "ERROR: build.sh (in-tree cross-toolchain) is not yet available for"
958		${runcmd} echo "	MACHINE:      ${MACHINE}"
959		${runcmd} echo "	MACHINE_ARCH: ${MACHINE_ARCH}"
960		${runcmd} echo ""
961		${runcmd} echo "All builds for this platform should be done via a traditional make"
962		${runcmd} echo "If you wish to use an external cross-toolchain, set"
963		${runcmd} echo "	EXTERNAL_TOOLCHAIN=<path to toolchain root>"
964		${runcmd} echo "in either the environment or mk.conf and rerun"
965		${runcmd} echo "	${progname} $*"
966		exit 1
967	fi
968
969	# Normalise MKOBJDIRS, MKUNPRIVED, and MKUPDATE
970	# These may be set as build.sh options or in "mk.conf".
971	# Don't export them as they're only used for tests in build.sh.
972	#
973	MKOBJDIRS=$(getmakevar MKOBJDIRS)
974	MKUNPRIVED=$(getmakevar MKUNPRIVED)
975	MKUPDATE=$(getmakevar MKUPDATE)
976
977	if [ "${MKOBJDIRS}" != "no" ]; then
978		# If setting -M or -O to the root of an obj dir, make sure
979		# the base directory is made before continuing as <bsd.own.mk>
980		# will need this to pick up _SRC_TOP_OBJ_
981		#
982		if [ ! -z "${makeobjdir}" ]; then
983			${runcmd} mkdir -p "${makeobjdir}"
984		fi
985
986		# make obj in tools to ensure that the objdir for the top-level
987		# of the source tree and for "tools" is available, in case the
988		# default TOOLDIR setting from <bsd.own.mk> is used, or the
989		# build.sh default DESTDIR and RELEASEDIR is to be used.
990		#
991		${runcmd} cd tools
992		${runcmd} "${make}" -m ${TOP}/share/mk obj NOSUBDIR= ||
993		    bomb "Failed to make obj in tools"
994		${runcmd} cd "${TOP}"
995	fi
996
997	# Find TOOLDIR, DESTDIR, and RELEASEDIR.
998	#
999	TOOLDIR=$(getmakevar TOOLDIR)
1000	statusmsg "TOOLDIR path:     ${TOOLDIR}"
1001	DESTDIR=$(getmakevar DESTDIR)
1002	RELEASEDIR=$(getmakevar RELEASEDIR)
1003	if ! $do_expertmode; then
1004		_SRC_TOP_OBJ_=$(getmakevar _SRC_TOP_OBJ_)
1005		: ${DESTDIR:=${_SRC_TOP_OBJ_}/destdir.${MACHINE}}
1006		: ${RELEASEDIR:=${_SRC_TOP_OBJ_}/releasedir}
1007		makeenv="${makeenv} DESTDIR RELEASEDIR"
1008	fi
1009	export TOOLDIR DESTDIR RELEASEDIR
1010	statusmsg "DESTDIR path:     ${DESTDIR}"
1011	statusmsg "RELEASEDIR path:  ${RELEASEDIR}"
1012
1013	# Check validity of TOOLDIR and DESTDIR.
1014	#
1015	if [ -z "${TOOLDIR}" ] || [ "${TOOLDIR}" = "/" ]; then
1016		bomb "TOOLDIR '${TOOLDIR}' invalid"
1017	fi
1018	removedirs="${TOOLDIR}"
1019
1020	if [ -z "${DESTDIR}" ] || [ "${DESTDIR}" = "/" ]; then
1021		if ${do_build} || ${do_distribution} || ${do_release}; then
1022			if ! ${do_build} || \
1023			   [ "${uname_s}" != "NetBSD" ] || \
1024			   [ "${uname_m}" != "${MACHINE}" ]; then
1025				bomb "DESTDIR must != / for cross builds, or ${progname} 'distribution' or 'release'."
1026			fi
1027			if ! ${do_expertmode}; then
1028				bomb "DESTDIR must != / for non -E (expert) builds"
1029			fi
1030			statusmsg "WARNING: Building to /, in expert mode."
1031			statusmsg "         This may cause your system to break!  Reasons include:"
1032			statusmsg "            - your kernel is not up to date"
1033			statusmsg "            - the libraries or toolchain have changed"
1034			statusmsg "         YOU HAVE BEEN WARNED!"
1035		fi
1036	else
1037		removedirs="${removedirs} ${DESTDIR}"
1038	fi
1039	if ${do_build} || ${do_distribution} || ${do_release}; then
1040		if ! ${do_expertmode} && \
1041		    [ "$(id -u 2>/dev/null)" -ne 0 ] && \
1042		    [ "${MKUNPRIVED}" = "no" ] ; then
1043			bomb "-U or -E must be set for build as an unprivileged user."
1044		fi
1045        fi
1046	if ${do_releasekernel} && [ -z "${RELEASEDIR}" ]; then
1047		bomb "Must set RELEASEDIR with \`releasekernel=...'"
1048	fi
1049}
1050
1051
1052createmakewrapper()
1053{
1054	# Remove the target directories.
1055	#
1056	if ${do_removedirs}; then
1057		for f in ${removedirs}; do
1058			statusmsg "Removing ${f}"
1059			${runcmd} rm -r -f "${f}"
1060		done
1061	fi
1062
1063	# Recreate $TOOLDIR.
1064	#
1065	${runcmd} mkdir -p "${TOOLDIR}/bin" ||
1066	    bomb "mkdir of '${TOOLDIR}/bin' failed"
1067
1068	# Install ${toolprefix}make if it was built.
1069	#
1070	if ${do_rebuildmake}; then
1071		${runcmd} rm -f "${TOOLDIR}/bin/${toolprefix}make"
1072		${runcmd} cp "${make}" "${TOOLDIR}/bin/${toolprefix}make" ||
1073		    bomb "Failed to install \$TOOLDIR/bin/${toolprefix}make"
1074		make="${TOOLDIR}/bin/${toolprefix}make"
1075		statusmsg "Created ${make}"
1076	fi
1077
1078	# Build a ${toolprefix}make wrapper script, usable by hand as
1079	# well as by build.sh.
1080	#
1081	if [ -z "${makewrapper}" ]; then
1082		makewrapper="${TOOLDIR}/bin/${toolprefix}make-${makewrappermachine:-${MACHINE}}"
1083		[ -z "${BUILDID}" ] || makewrapper="${makewrapper}-${BUILDID}"
1084	fi
1085
1086	${runcmd} rm -f "${makewrapper}"
1087	if [ "${runcmd}" = "echo" ]; then
1088		echo 'cat <<EOF >'${makewrapper}
1089		makewrapout=
1090	else
1091		makewrapout=">>\${makewrapper}"
1092	fi
1093
1094	case "${KSH_VERSION:-${SH_VERSION}}" in
1095	*PD\ KSH*|*MIRBSD\ KSH*)
1096		set +o braceexpand
1097		;;
1098	esac
1099
1100	eval cat <<EOF ${makewrapout}
1101#! ${HOST_SH}
1102# Set proper variables to allow easy "make" building of a NetBSD subtree.
1103# Generated from:  \$NetBSD: build.sh,v 1.173 2007/09/01 08:15:27 jnemeth Exp $
1104# with these arguments: ${_args}
1105#
1106EOF
1107	for f in ${makeenv}; do
1108		if eval "[ -z \"\${$f}\" -a \"\${${f}-X}\" = \"X\" ]"; then
1109			eval echo "unset ${f}" ${makewrapout}
1110		else
1111			eval echo "${f}=\'\$$(echo ${f})\'\;\ export\ ${f}" ${makewrapout}
1112		fi
1113	done
1114
1115	eval cat <<EOF ${makewrapout}
1116MAKEWRAPPERMACHINE=${makewrappermachine:-${MACHINE}}; export MAKEWRAPPERMACHINE
1117USETOOLS=yes; export USETOOLS
1118
1119exec "\${TOOLDIR}/bin/${toolprefix}make" \${1+"\$@"}
1120EOF
1121	[ "${runcmd}" = "echo" ] && echo EOF
1122	${runcmd} chmod +x "${makewrapper}"
1123	statusmsg "makewrapper:      ${makewrapper}"
1124	statusmsg "Updated ${makewrapper}"
1125}
1126
1127buildtools()
1128{
1129	if [ "${MKOBJDIRS}" != "no" ]; then
1130		${runcmd} "${makewrapper}" ${parallel} obj-tools ||
1131		    bomb "Failed to make obj-tools"
1132	fi
1133	${runcmd} cd tools
1134	if [ "${MKUPDATE}" = "no" ]; then
1135		${runcmd} "${makewrapper}" ${parallel} cleandir ||
1136		    bomb "Failed to make cleandir tools"
1137	fi
1138	${runcmd} "${makewrapper}" ${parallel} dependall ||
1139	    bomb "Failed to make dependall tools"
1140	${runcmd} "${makewrapper}" ${parallel} install ||
1141	    bomb "Failed to make install tools"
1142	statusmsg "Tools built to ${TOOLDIR}"
1143	${runcmd} cd "${TOP}"
1144}
1145
1146getkernelconf()
1147{
1148	kernelconf="$1"
1149	if [ "${MKOBJDIRS}" != "no" ]; then
1150		# The correct value of KERNOBJDIR might
1151		# depend on a prior "make obj" in
1152		# ${KERNSRCDIR}/${KERNARCHDIR}/compile.
1153		#
1154		KERNSRCDIR="$(getmakevar KERNSRCDIR)"
1155		KERNARCHDIR="$(getmakevar KERNARCHDIR)"
1156		${runcmd} cd "${KERNSRCDIR}/${KERNARCHDIR}/compile"
1157		${runcmd} "${makewrapper}" ${parallel} obj ||
1158		    bomb "Failed to make obj in ${KERNSRCDIR}/${KERNARCHDIR}/compile"
1159		${runcmd} cd "${TOP}"
1160	fi
1161	KERNCONFDIR="$(getmakevar KERNCONFDIR)"
1162	KERNOBJDIR="$(getmakevar KERNOBJDIR)"
1163	case "${kernelconf}" in
1164	*/*)
1165		kernelconfpath="${kernelconf}"
1166		kernelconfname="${kernelconf##*/}"
1167		;;
1168	*)
1169		kernelconfpath="${KERNCONFDIR}/${kernelconf}"
1170		kernelconfname="${kernelconf}"
1171		;;
1172	esac
1173	kernelbuildpath="${KERNOBJDIR}/${kernelconfname}"
1174}
1175
1176buildkernel()
1177{
1178	if ! ${do_tools} && ! ${buildkernelwarned:-false}; then
1179		# Building tools every time we build a kernel is clearly
1180		# unnecessary.  We could try to figure out whether rebuilding
1181		# the tools is necessary this time, but it doesn't seem worth
1182		# the trouble.  Instead, we say it's the user's responsibility
1183		# to rebuild the tools if necessary.
1184		#
1185		statusmsg "Building kernel without building new tools"
1186		buildkernelwarned=true
1187	fi
1188	getkernelconf $1
1189	statusmsg "Building kernel:  ${kernelconf}"
1190	statusmsg "Build directory:  ${kernelbuildpath}"
1191	${runcmd} mkdir -p "${kernelbuildpath}" ||
1192	    bomb "Cannot mkdir: ${kernelbuildpath}"
1193	if [ "${MKUPDATE}" = "no" ]; then
1194		${runcmd} cd "${kernelbuildpath}"
1195		${runcmd} "${makewrapper}" ${parallel} cleandir ||
1196		    bomb "Failed to make cleandir in ${kernelbuildpath}"
1197		${runcmd} cd "${TOP}"
1198	fi
1199	[ -x "${TOOLDIR}/bin/${toolprefix}config" ] \
1200	|| bomb "${TOOLDIR}/bin/${toolprefix}config does not exist. You need to \"$0 tools\" first."
1201	${runcmd} "${TOOLDIR}/bin/${toolprefix}config" -b "${kernelbuildpath}" \
1202		-s "${TOP}/sys" "${kernelconfpath}" ||
1203	    bomb "${toolprefix}config failed for ${kernelconf}"
1204	${runcmd} cd "${kernelbuildpath}"
1205	${runcmd} "${makewrapper}" ${parallel} depend ||
1206	    bomb "Failed to make depend in ${kernelbuildpath}"
1207	${runcmd} "${makewrapper}" ${parallel} all ||
1208	    bomb "Failed to make all in ${kernelbuildpath}"
1209	${runcmd} cd "${TOP}"
1210
1211	if [ "${runcmd}" != "echo" ]; then
1212		statusmsg "Kernels built from ${kernelconf}:"
1213		kernlist=$(awk '$1 == "config" { print $2 }' ${kernelconfpath})
1214		for kern in ${kernlist:-netbsd}; do
1215			[ -f "${kernelbuildpath}/${kern}" ] && \
1216			    echo "  ${kernelbuildpath}/${kern}"
1217		done | tee -a "${results}"
1218	fi
1219}
1220
1221releasekernel()
1222{
1223	getkernelconf $1
1224	kernelreldir="${RELEASEDIR}/${MACHINE}/binary/kernel"
1225	${runcmd} mkdir -p "${kernelreldir}"
1226	kernlist=$(awk '$1 == "config" { print $2 }' ${kernelconfpath})
1227	for kern in ${kernlist:-netbsd}; do
1228		builtkern="${kernelbuildpath}/${kern}"
1229		[ -f "${builtkern}" ] || continue
1230		releasekern="${kernelreldir}/${kern}-${kernelconfname}.gz"
1231		statusmsg "Kernel copy:      ${releasekern}"
1232		${runcmd} gzip -c -9 < "${builtkern}" > "${releasekern}"
1233	done
1234}
1235
1236installworld()
1237{
1238	dir="$1"
1239	${runcmd} "${makewrapper}" INSTALLWORLDDIR="${dir}" installworld ||
1240	    bomb "Failed to make installworld to ${dir}"
1241	statusmsg "Successful installworld to ${dir}"
1242}
1243
1244
1245main()
1246{
1247	initdefaults
1248	_args=$@
1249	parseoptions "$@"
1250
1251	sanitycheck
1252
1253	build_start=$(date)
1254	statusmsg "${progname} command: $0 $@"
1255	statusmsg "${progname} started: ${build_start}"
1256	statusmsg "NetBSD version:   ${DISTRIBVER}"
1257	statusmsg "MACHINE:          ${MACHINE}"
1258	statusmsg "MACHINE_ARCH:     ${MACHINE_ARCH}"
1259	statusmsg "Build platform:   ${uname_s} ${uname_r} ${uname_m}"
1260	statusmsg "HOST_SH:          ${HOST_SH}"
1261
1262	rebuildmake
1263	validatemakeparams
1264	createmakewrapper
1265
1266	# Perform the operations.
1267	#
1268	for op in ${operations}; do
1269		case "${op}" in
1270
1271		makewrapper)
1272			# no-op
1273			;;
1274
1275		tools)
1276			buildtools
1277			;;
1278
1279		sets)
1280			statusmsg "Building sets from pre-populated ${DESTDIR}"
1281			${runcmd} "${makewrapper}" ${parallel} ${op} ||
1282			    bomb "Failed to make ${op}"
1283			statusmsg "Successful make ${op}"
1284			;;
1285
1286		obj|build|distribution|release|sourcesets|syspkgs|params)
1287			${runcmd} "${makewrapper}" ${parallel} ${op} ||
1288			    bomb "Failed to make ${op}"
1289			statusmsg "Successful make ${op}"
1290			;;
1291
1292		iso-image|iso-image-source)
1293			${runcmd} "${makewrapper}" ${parallel} \
1294			    CDEXTRA=$iso_dir ${op} ||
1295			    bomb "Failed to make ${op}"
1296			statusmsg "Successful make ${op}"
1297			;;
1298
1299		iso-dir=*)
1300			# no-op
1301			;;
1302
1303		kernel=*)
1304			arg=${op#*=}
1305			buildkernel "${arg}"
1306			;;
1307
1308		releasekernel=*)
1309			arg=${op#*=}
1310			releasekernel "${arg}"
1311			;;
1312
1313		install=*)
1314			arg=${op#*=}
1315			if [ "${arg}" = "/" ] && \
1316			    (	[ "${uname_s}" != "NetBSD" ] || \
1317				[ "${uname_m}" != "${MACHINE}" ] ); then
1318				bomb "'${op}' must != / for cross builds."
1319			fi
1320			installworld "${arg}"
1321			;;
1322
1323		*)
1324			bomb "Unknown operation \`${op}'"
1325			;;
1326
1327		esac
1328	done
1329
1330	statusmsg "${progname} ended:   $(date)"
1331	if [ -s "${results}" ]; then
1332		echo "===> Summary of results:"
1333		sed -e 's/^===>//;s/^/	/' "${results}"
1334		echo "===> ."
1335	fi
1336}
1337
1338main "$@"
1339