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