build.sh revision 1.102 1 #! /usr/bin/env sh
2 # $NetBSD: build.sh,v 1.102 2003/05/12 03:01:16 lukem Exp $
3 #
4 # Copyright (c) 2001-2003 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. For systems
42 # with a strange /bin/sh, "ksh" or "bash" may be an ample alternative.
43 #
44 # Note, however, that due to the way the interpreter is invoked above,
45 # if a POSIX-compliant shell is the first in the PATH, you won't have
46 # to take any further action.
47 #
48
49 progname=${0##*/}
50 toppid=$$
51 results=/dev/null
52 trap "exit 1" 1 2 3 15
53
54 bomb()
55 {
56 cat >&2 <<ERRORMESSAGE
57
58 ERROR: $@
59 *** BUILD ABORTED ***
60 ERRORMESSAGE
61 kill ${toppid} # in case we were invoked from a subshell
62 exit 1
63 }
64
65
66 statusmsg()
67 {
68 ${runcmd} echo "===> $@" | tee -a "${results}"
69 }
70
71 initdefaults()
72 {
73 cd "$(dirname $0)"
74 [ -d usr.bin/make ] ||
75 bomb "build.sh must be run from the top source level"
76 [ -f share/mk/bsd.own.mk ] ||
77 bomb "src/share/mk is missing; please re-fetch the source tree"
78
79 uname_s=$(uname -s 2>/dev/null)
80 uname_m=$(uname -m 2>/dev/null)
81
82 # If $PWD is a valid name of the current directory, POSIX mandates
83 # that pwd return it by default which causes problems in the
84 # presence of symlinks. Unsetting PWD is simpler than changing
85 # every occurrence of pwd to use -P.
86 #
87 # XXX Except that doesn't work on Solaris.
88 #
89 unset PWD
90 if [ "${uname_s}" = "SunOS" ]; then
91 TOP=$(pwd -P)
92 else
93 TOP=$(pwd)
94 fi
95
96 # Set defaults.
97 #
98 toolprefix=nb
99
100 # Some systems have a small ARG_MAX. -X prevents make(1) from
101 # exporting variables in the environment redundantly.
102 #
103 case "${uname_s}" in
104 Darwin | FreeBSD | CYGWIN*)
105 MAKEFLAGS=-X
106 ;;
107 *)
108 MAKEFLAGS=
109 ;;
110 esac
111
112 makeenv=
113 makewrapper=
114 makewrappermachine=
115 runcmd=
116 operations=
117 removedirs=
118 do_expertmode=false
119 do_rebuildmake=false
120 do_removedirs=false
121
122 # do_{operation}=true if given operation is requested.
123 #
124 do_tools=false
125 do_obj=false
126 do_build=false
127 do_distribution=false
128 do_release=false
129 do_kernel=false
130 do_install=false
131 do_sets=false
132 do_sourcesets=false
133
134 # Create scratch directory
135 #
136 tmpdir="${TMPDIR-/tmp}/nbbuild$$"
137 mkdir "${tmpdir}" || bomb "Cannot mkdir: ${tmpdir}"
138 trap "cd /; rm -r -f \"${tmpdir}\"" 0
139 results="${tmpdir}/build.sh.results"
140 }
141
142 getarch()
143 {
144 # Translate a MACHINE into a default MACHINE_ARCH.
145 #
146 case "${MACHINE}" in
147
148 acorn26|acorn32|cats|evbarm|hpcarm|netwinder|shark)
149 MACHINE_ARCH=arm
150 ;;
151
152 hp700)
153 MACHINE_ARCH=hppa
154 ;;
155
156 sun2)
157 MACHINE_ARCH=m68000
158 ;;
159
160 amiga|atari|cesfic|hp300|luna68k|mac68k|mvme68k|news68k|next68k|sun3|x68k)
161 MACHINE_ARCH=m68k
162 ;;
163
164 evbmips-e[bl]|sbmips-e[bl])
165 MACHINE_ARCH=mips${MACHINE##*-}
166 makewrappermachine=${MACHINE}
167 MACHINE=${MACHINE%-e[bl]}
168 ;;
169
170 evbmips|sbmips) # no default MACHINE_ARCH
171 ;;
172
173 mipsco|newsmips|sgimips)
174 MACHINE_ARCH=mipseb
175 ;;
176
177 algor|arc|cobalt|hpcmips|playstation2|pmax)
178 MACHINE_ARCH=mipsel
179 ;;
180
181 pc532)
182 MACHINE_ARCH=ns32k
183 ;;
184
185 amigappc|bebox|evbppc|macppc|mvmeppc|ofppc|pmppc|prep|sandpoint)
186 MACHINE_ARCH=powerpc
187 ;;
188
189 evbsh3|mmeye)
190 MACHINE_ARCH=sh3eb
191 ;;
192
193 dreamcast|hpcsh)
194 MACHINE_ARCH=sh3el
195 ;;
196
197 evbsh5)
198 MACHINE_ARCH=sh5el
199 ;;
200 amd64)
201 MACHINE_ARCH=x86_64
202 ;;
203
204 alpha|i386|sparc|sparc64|vax)
205 MACHINE_ARCH=${MACHINE}
206 ;;
207
208 *)
209 bomb "Unknown target MACHINE: ${MACHINE}"
210 ;;
211
212 esac
213 }
214
215 validatearch()
216 {
217 # Ensure that the MACHINE_ARCH exists (and is supported by build.sh).
218 #
219 case "${MACHINE_ARCH}" in
220
221 alpha|arm|armeb|hppa|i386|m68000|m68k|mipse[bl]|ns32k|powerpc|sh[35]e[bl]|sparc|sparc64|vax|x86_64)
222 ;;
223
224 "")
225 bomb "No MACHINE_ARCH provided"
226 ;;
227
228 *)
229 bomb "Unknown target MACHINE_ARCH: ${MACHINE_ARCH}"
230 ;;
231
232 esac
233
234 # Determine valid MACHINE_ARCHs for MACHINE
235 #
236 case "${MACHINE}" in
237
238 evbarm)
239 arches="arm armeb"
240 ;;
241
242 evbmips|sbmips)
243 arches="mipseb mipsel"
244 ;;
245
246 evbsh3)
247 arches="sh3eb sh3el"
248 ;;
249
250 evbsh5)
251 arches="sh5eb sh5el"
252 ;;
253
254 *)
255 oma="${MACHINE_ARCH}"
256 getarch
257 arches="${MACHINE_ARCH}"
258 MACHINE_ARCH="${oma}"
259 ;;
260
261 esac
262
263 # Ensure that MACHINE_ARCH supports MACHINE
264 #
265 archok=false
266 for a in ${arches}; do
267 if [ "${a}" = "${MACHINE_ARCH}" ]; then
268 archok=true
269 break
270 fi
271 done
272 ${archok} ||
273 bomb "MACHINE_ARCH '${MACHINE_ARCH}' does not support MACHINE '${MACHINE}'"
274 }
275
276 raw_getmakevar()
277 {
278 [ -x "${make}" ] || bomb "raw_getmakevar $1: ${make} is not executable"
279 "${make}" -m ${TOP}/share/mk -s -f- _x_ <<EOF
280 _x_:
281 echo \${$1}
282 .include <bsd.prog.mk>
283 .include <bsd.kernobj.mk>
284 EOF
285 }
286
287 getmakevar()
288 {
289 # raw_getmakevar() doesn't work properly if $make hasn't yet been
290 # built, which can happen when running with the "-n" option.
291 # getmakevar() deals with this by emitting a literal '$'
292 # followed by the variable name, instead of trying to find the
293 # variable's value.
294 #
295 if [ -x "${make}" ]; then
296 raw_getmakevar "$1"
297 else
298 echo "\$$1"
299 fi
300 }
301
302 resolvepath()
303 {
304 case "${OPTARG}" in
305 /*)
306 ;;
307 *)
308 OPTARG="${TOP}/${OPTARG}"
309 ;;
310 esac
311 }
312
313 usage()
314 {
315 if [ -n "$*" ]; then
316 echo ""
317 echo "${progname}: $*"
318 fi
319 cat <<_usage_
320
321 Usage: ${progname} [-EnorUu] [-a arch] [-B buildid] [-D dest] [-j njob] [-M obj]
322 [-m mach] [-O obj] [-R release] [-T tools] [-V var=[value]]
323 [-w wrapper] operation [...]
324
325 Build operations (all imply "obj" and "tools"):
326 build Run "make build"
327 distribution Run "make distribution" (includes DESTDIR/etc/ files)
328 release Run "make release" (includes kernels & distrib media)
329
330 Other operations:
331 help Show this message (and exit)
332 makewrapper Create ${toolprefix}make-\${MACHINE} wrapper and ${toolprefix}make.
333 (Always done)
334 obj Run "make obj" (default unless -o is used)
335 tools Build and install tools
336 kernel=conf Build kernel with config file \`conf'
337 install=idir Run "make installworld" to \`idir'
338 (useful after 'distribution' or 'release')
339 sets Create binary sets in RELEASEDIR/MACHINE/binary/sets
340 sourcesets Create source sets in RELEASEDIR/source/sets
341
342 Options:
343 -a arch Set MACHINE_ARCH to arch (otherwise deduced from MACHINE)
344 -B buildId Set BUILDID to buildId
345 -D dest Set DESTDIR to dest. (Default: destdir.MACHINE)
346 -E Set "expert" mode; disables various safety checks.
347 Should not be used without expert knowledge of the build system
348 -j njob Run up to njob jobs in parallel; see make(1)
349 -M obj Set obj root directory to obj (sets MAKEOBJDIRPREFIX)
350 -m mach Set MACHINE to mach (not required if NetBSD native)
351 -n Show commands that would be executed, but do not execute them
352 -O obj Set obj root directory to obj (sets a MAKEOBJDIR pattern)
353 -o Set MKOBJDIRS=no (do not create objdirs at start of build)
354 -R release Set RELEASEDIR to release. (Default: releasedir)
355 -r Remove contents of TOOLDIR and DESTDIR before building
356 -T tools Set TOOLDIR to tools. If unset, and TOOLDIR is not set in
357 the environment, ${toolprefix}make will be (re)built unconditionally
358 -U Set UNPRIVED (build without requiring root privileges)
359 -u Set UPDATE (do not run "make clean" first).
360 Without this, everything is rebuilt, including the tools.
361 -V v=[val] Set variable \`v' to \`val'
362 -w wrapper Create ${toolprefix}make script as wrapper
363 (Default: \${TOOLDIR}/bin/${toolprefix}make-\${MACHINE})
364
365 _usage_
366 exit 1
367 }
368
369 parseoptions()
370 {
371 opts='a:B:bD:dEhi:j:k:M:m:nO:oR:rT:tUuV:w:'
372 opt_a=no
373
374 if type getopts >/dev/null 2>&1; then
375 # Use POSIX getopts.
376 #
377 getoptcmd='getopts ${opts} opt && opt=-${opt}'
378 optargcmd=':'
379 optremcmd='shift $((${OPTIND} -1))'
380 else
381 type getopt >/dev/null 2>&1 ||
382 bomb "/bin/sh shell is too old; try ksh or bash"
383
384 # Use old-style getopt(1) (doesn't handle whitespace in args).
385 #
386 args="$(getopt ${opts} $*)"
387 [ $? = 0 ] || usage
388 set -- ${args}
389
390 getoptcmd='[ $# -gt 0 ] && opt="$1" && shift'
391 optargcmd='OPTARG="$1"; shift'
392 optremcmd=':'
393 fi
394
395 # Parse command line options.
396 #
397 while eval ${getoptcmd}; do
398 case ${opt} in
399
400 -a)
401 eval ${optargcmd}
402 MACHINE_ARCH=${OPTARG}
403 opt_a=yes
404 ;;
405
406 -B)
407 eval ${optargcmd}
408 BUILDID=${OPTARG}
409 ;;
410
411 -b)
412 usage "'-b' has been replaced by 'makewrapper'"
413 ;;
414
415 -D)
416 eval ${optargcmd}; resolvepath
417 DESTDIR="${OPTARG}"
418 export DESTDIR
419 makeenv="${makeenv} DESTDIR"
420 ;;
421
422 -d)
423 usage "'-d' has been replaced by 'distribution'"
424 ;;
425
426 -E)
427 do_expertmode=true
428 ;;
429
430 -i)
431 usage "'-i idir' has been replaced by 'install=idir'"
432 ;;
433
434 -j)
435 eval ${optargcmd}
436 parallel="-j ${OPTARG}"
437 ;;
438
439 -k)
440 usage "'-k conf' has been replaced by 'kernel=conf'"
441 ;;
442
443 -M)
444 eval ${optargcmd}; resolvepath
445 MAKEOBJDIRPREFIX="${OPTARG}"
446 export MAKEOBJDIRPREFIX
447 makeobjdir="${OPTARG}"
448 makeenv="${makeenv} MAKEOBJDIRPREFIX"
449 ;;
450
451 # -m overrides MACHINE_ARCH unless "-a" is specified
452 -m)
453 eval ${optargcmd}
454 MACHINE="${OPTARG}"
455 [ "${opt_a}" != "yes" ] && getarch
456 ;;
457
458 -n)
459 runcmd=echo
460 ;;
461
462 -O)
463 eval ${optargcmd}; resolvepath
464 MAKEOBJDIR="\${.CURDIR:C,^$TOP,$OPTARG,}"
465 export MAKEOBJDIR
466 makeobjdir="${OPTARG}"
467 makeenv="${makeenv} MAKEOBJDIR"
468 ;;
469
470 -o)
471 MKOBJDIRS=no
472 ;;
473
474 -R)
475 eval ${optargcmd}; resolvepath
476 RELEASEDIR="${OPTARG}"
477 export RELEASEDIR
478 makeenv="${makeenv} RELEASEDIR"
479 ;;
480
481 -r)
482 do_removedirs=true
483 do_rebuildmake=true
484 ;;
485
486 -T)
487 eval ${optargcmd}; resolvepath
488 TOOLDIR="${OPTARG}"
489 export TOOLDIR
490 ;;
491
492 -t)
493 usage "'-t' has been replaced by 'tools'"
494 ;;
495
496 -U)
497 UNPRIVED=yes
498 export UNPRIVED
499 makeenv="${makeenv} UNPRIVED"
500 ;;
501
502 -u)
503 UPDATE=yes
504 export UPDATE
505 makeenv="${makeenv} UPDATE"
506 ;;
507
508 -V)
509 eval ${optargcmd}
510 case "${OPTARG}" in
511 # XXX: consider restricting which variables can be changed?
512 [a-zA-Z_][a-zA-Z_0-9]*=*)
513 var=${OPTARG%%=*}
514 value=${OPTARG#*=}
515 eval "${var}=\"${value}\"; export ${var}"
516 makeenv="${makeenv} ${var}"
517 ;;
518 *)
519 usage "-V argument must be of the form 'var=[value]'"
520 ;;
521 esac
522 ;;
523
524 -w)
525 eval ${optargcmd}; resolvepath
526 makewrapper="${OPTARG}"
527 ;;
528
529 --)
530 break
531 ;;
532
533 -'?'|-h)
534 usage
535 ;;
536
537 esac
538 done
539
540 # Validate operations.
541 #
542 eval ${optremcmd}
543 while [ $# -gt 0 ]; do
544 op=$1; shift
545 operations="${operations} ${op}"
546
547 case "${op}" in
548
549 help)
550 usage
551 ;;
552
553 makewrapper|obj|tools|build|distribution|release|sets|sourcesets)
554 ;;
555
556 kernel=*)
557 arg=${op#*=}
558 op=${op%%=*}
559 [ -n "${arg}" ] ||
560 bomb "Must supply a kernel name with \`kernel=...'"
561 ;;
562
563 install=*)
564 arg=${op#*=}
565 op=${op%%=*}
566 [ -n "${arg}" ] ||
567 bomb "Must supply a directory with \`install=...'"
568 ;;
569
570 *)
571 usage "Unknown operation \`${op}'"
572 ;;
573
574 esac
575 eval do_${op}=true
576 done
577 [ -n "${operations}" ] || usage "Missing operation to perform."
578
579 # Set up MACHINE*. On a NetBSD host, these are allowed to be unset.
580 #
581 if [ -z "${MACHINE}" ]; then
582 [ "${uname_s}" = "NetBSD" ] ||
583 bomb "MACHINE must be set, or -m must be used, for cross builds."
584 MACHINE=${uname_m}
585 fi
586 [ -n "${MACHINE_ARCH}" ] || getarch
587 validatearch
588
589 # Set up default make(1) environment.
590 #
591 makeenv="${makeenv} TOOLDIR MACHINE MACHINE_ARCH MAKEFLAGS"
592 [ -z "${BUILDID}" ] || makeenv="${makeenv} BUILDID"
593 MAKEFLAGS="-m ${TOP}/share/mk ${MAKEFLAGS} MKOBJDIRS=${MKOBJDIRS-yes}"
594 export MAKEFLAGS MACHINE MACHINE_ARCH
595 }
596
597 rebuildmake()
598 {
599 # Test make source file timestamps against installed ${toolprefix}make
600 # binary, if TOOLDIR is pre-set.
601 #
602 # Note that we do NOT try to grovel "mk.conf" here to find out if
603 # TOOLDIR is set there, because it can contain make variable
604 # expansions and other stuff only parseable *after* we have a working
605 # ${toolprefix}make. So this logic can only work if the user has
606 # pre-set TOOLDIR in the environment or used the -T option to build.sh.
607 #
608 make="${TOOLDIR-nonexistent}/bin/${toolprefix}make"
609 if [ -x "${make}" ]; then
610 for f in usr.bin/make/*.[ch] usr.bin/make/lst.lib/*.[ch]; do
611 if [ "${f}" -nt "${make}" ]; then
612 do_rebuildmake=true
613 break
614 fi
615 done
616 else
617 do_rebuildmake=true
618 fi
619
620 # Build bootstrap ${toolprefix}make if needed.
621 if ${do_rebuildmake}; then
622 statusmsg "Bootstrapping ${toolprefix}make"
623 ${runcmd} cd "${tmpdir}"
624 ${runcmd} env CC="${HOST_CC-cc}" CPPFLAGS="${HOST_CPPFLAGS}" \
625 CFLAGS="${HOST_CFLAGS--O}" LDFLAGS="${HOST_LDFLAGS}" \
626 "${TOP}/tools/make/configure" ||
627 bomb "Configure of ${toolprefix}make failed"
628 ${runcmd} sh buildmake.sh ||
629 bomb "Build of ${toolprefix}make failed"
630 make="${tmpdir}/${toolprefix}make"
631 ${runcmd} cd "${TOP}"
632 ${runcmd} rm -f usr.bin/make/*.o usr.bin/make/lst.lib/*.o
633 fi
634 }
635
636 validatemakeparams()
637 {
638 if [ "${runcmd}" = "echo" ]; then
639 TOOLCHAIN_MISSING=no
640 EXTERNAL_TOOLCHAIN=""
641 else
642 TOOLCHAIN_MISSING=$(raw_getmakevar TOOLCHAIN_MISSING)
643 EXTERNAL_TOOLCHAIN=$(raw_getmakevar EXTERNAL_TOOLCHAIN)
644 fi
645 if [ "${TOOLCHAIN_MISSING}" = "yes" ] && \
646 [ -z "${EXTERNAL_TOOLCHAIN}" ]; then
647 ${runcmd} echo "ERROR: build.sh (in-tree cross-toolchain) is not yet available for"
648 ${runcmd} echo " MACHINE: ${MACHINE}"
649 ${runcmd} echo " MACHINE_ARCH: ${MACHINE_ARCH}"
650 ${runcmd} echo ""
651 ${runcmd} echo "All builds for this platform should be done via a traditional make"
652 ${runcmd} echo "If you wish to use an external cross-toolchain, set"
653 ${runcmd} echo " EXTERNAL_TOOLCHAIN=<path to toolchain root>"
654 ${runcmd} echo "in either the environment or mk.conf and rerun"
655 ${runcmd} echo " ${progname} $*"
656 exit 1
657 fi
658
659 # If TOOLDIR isn't already set, make objdirs in "tools" in case the
660 # default setting from <bsd.own.mk> is used.
661 #
662 if [ -z "${TOOLDIR}" ] && [ "${MKOBJDIRS}" != "no" ]; then
663 ${runcmd} cd tools
664 ${runcmd} "${make}" -m ${TOP}/share/mk obj NOSUBDIR= ||
665 bomb "Failed to make obj in tools"
666 ${runcmd} cd "${TOP}"
667 fi
668
669 # If setting -M or -O to root an obj dir make sure the base directory
670 # is made before continuing as bsd.own.mk will need this to pick up
671 # _SRC_TOP_OBJ_
672 #
673 if [ "${MKOBJDIRS}" != "no" ] && [ ! -z "${makeobjdir}" ]; then
674 ${runcmd} mkdir -p "${makeobjdir}"
675 fi
676
677 statusmsg "MACHINE: ${MACHINE}"
678 statusmsg "MACHINE_ARCH: ${MACHINE_ARCH}"
679
680 # Find TOOLDIR, DESTDIR, and RELEASEDIR.
681 #
682 TOOLDIR=$(getmakevar TOOLDIR)
683 statusmsg "TOOLDIR path: ${TOOLDIR}"
684 DESTDIR=$(getmakevar DESTDIR)
685 RELEASEDIR=$(getmakevar RELEASEDIR)
686 if ! $do_expertmode; then
687 _SRCTOPOBJ_=$(getmakevar _SRC_TOP_OBJ_)
688 : ${DESTDIR:=${_SRCTOPOBJ_}/destdir.${MACHINE}}
689 : ${RELEASEDIR:=${_SRCTOPOBJ_}/releasedir}
690 makeenv="${makeenv} DESTDIR RELEASEDIR"
691 fi
692 export TOOLDIR DESTDIR RELEASEDIR
693 statusmsg "DESTDIR path: ${DESTDIR}"
694 statusmsg "RELEASEDIR path: ${RELEASEDIR}"
695
696 # Check validity of TOOLDIR and DESTDIR.
697 #
698 if [ -z "${TOOLDIR}" ] || [ "${TOOLDIR}" = "/" ]; then
699 bomb "TOOLDIR '${TOOLDIR}' invalid"
700 fi
701 removedirs="${TOOLDIR}"
702
703 if [ -z "${DESTDIR}" ] || [ "${DESTDIR}" = "/" ]; then
704 if ${do_build} || ${do_distribution} || ${do_release}; then
705 if ! ${do_build} || \
706 [ "${uname_s}" != "NetBSD" ] || \
707 [ "${uname_m}" != "${MACHINE}" ]; then
708 bomb "DESTDIR must != / for cross builds, or ${progname} 'distribution' or 'release'."
709 fi
710 if ! ${do_expertmode}; then
711 bomb "DESTDIR must != / for non -E (expert) builds"
712 fi
713 statusmsg "WARNING: Building to /, in expert mode."
714 statusmsg " This may cause your system to break! Reasons include:"
715 statusmsg " - your kernel is not up to date"
716 statusmsg " - the libraries or toolchain have changed"
717 statusmsg " YOU HAVE BEEN WARNED!"
718 fi
719 else
720 removedirs="${removedirs} ${DESTDIR}"
721 fi
722 if ${do_build} || ${do_distribution} || ${do_release}; then
723 if ! ${do_expertmode} && \
724 [ $(id -u 2>/dev/null) -ne 0 ] &&\
725 [ -z "${UNPRIVED}" ] ; then
726 bomb "-U or -E must be set for build as an unprivileged user."
727 fi
728 fi
729 }
730
731
732 createmakewrapper()
733 {
734 # Remove the target directories.
735 #
736 if ${do_removedirs}; then
737 for f in ${removedirs}; do
738 statusmsg "Removing ${f}"
739 ${runcmd} rm -r -f "${f}"
740 done
741 fi
742
743 # Recreate $TOOLDIR.
744 #
745 ${runcmd} mkdir -p "${TOOLDIR}/bin" ||
746 bomb "mkdir of '${TOOLDIR}/bin' failed"
747
748 # Install ${toolprefix}make if it was built.
749 #
750 if ${do_rebuildmake}; then
751 ${runcmd} rm -f "${TOOLDIR}/bin/${toolprefix}make"
752 ${runcmd} cp "${make}" "${TOOLDIR}/bin/${toolprefix}make" ||
753 bomb "Failed to install \$TOOLDIR/bin/${toolprefix}make"
754 make="${TOOLDIR}/bin/${toolprefix}make"
755 statusmsg "Created ${make}"
756 fi
757
758 # Build a ${toolprefix}make wrapper script, usable by hand as
759 # well as by build.sh.
760 #
761 if [ -z "${makewrapper}" ]; then
762 makewrapper="${TOOLDIR}/bin/${toolprefix}make-${makewrappermachine:-${MACHINE}}"
763 [ -z "${BUILDID}" ] || makewrapper="${makewrapper}-${BUILDID}"
764 fi
765
766 ${runcmd} rm -f "${makewrapper}"
767 if [ "${runcmd}" = "echo" ]; then
768 echo 'cat <<EOF >'${makewrapper}
769 makewrapout=
770 else
771 makewrapout=">>\${makewrapper}"
772 fi
773
774 eval cat <<EOF ${makewrapout}
775 #! /bin/sh
776 # Set proper variables to allow easy "make" building of a NetBSD subtree.
777 # Generated from: \$NetBSD: build.sh,v 1.102 2003/05/12 03:01:16 lukem Exp $
778 #
779
780 EOF
781 for f in ${makeenv}; do
782 eval echo "${f}=\'\$$(echo ${f})\'\;\ export\ ${f}" ${makewrapout}
783 done
784 eval echo "USETOOLS=yes\; export USETOOLS" ${makewrapout}
785
786 eval cat <<EOF ${makewrapout}
787
788 exec "\${TOOLDIR}/bin/${toolprefix}make" \${1+"\$@"}
789 EOF
790 [ "${runcmd}" = "echo" ] && echo EOF
791 ${runcmd} chmod +x "${makewrapper}"
792 statusmsg "Updated ${makewrapper}"
793 }
794
795 buildtools()
796 {
797 if [ "${MKOBJDIRS}" != "no" ]; then
798 ${runcmd} "${makewrapper}" ${parallel} obj-tools ||
799 bomb "Failed to make obj-tools"
800 fi
801 ${runcmd} cd tools
802 if [ -z "${UPDATE}" ]; then
803 cleandir=cleandir
804 else
805 cleandir=
806 fi
807 ${runcmd} "${makewrapper}" ${cleandir} dependall install ||
808 bomb "Failed to make tools"
809 statusmsg "Tools built to ${TOOLDIR}"
810 }
811
812 buildkernel()
813 {
814 kernconf="$1"
815 if ! ${do_tools}; then
816 # Building tools every time we build a kernel is clearly
817 # unnecessary. We could try to figure out whether rebuilding
818 # the tools is necessary this time, but it doesn't seem worth
819 # the trouble. Instead, we say it's the user's responsibility
820 # to rebuild the tools if necessary.
821 #
822 statusmsg "Building kernel without building new tools"
823 fi
824 statusmsg "Building kernel ${kernconf}"
825 if [ "${MKOBJDIRS}" != "no" ] && [ ! -z "${makeobjdir}" ]; then
826 # The correct value of KERNOBJDIR might
827 # depend on a prior "make obj" in
828 # ${KERNSRCDIR}/${KERNARCHDIR}/compile.
829 #
830 KERNSRCDIR="$(getmakevar KERNSRCDIR)"
831 KERNARCHDIR="$(getmakevar KERNARCHDIR)"
832 ${runcmd} cd "${KERNSRCDIR}/${KERNARCHDIR}/compile"
833 ${runcmd} "${makewrapper}" obj ||
834 bomb "Failed to make obj in ${KERNSRCDIR}/${KERNARCHDIR}/compile"
835 ${runcmd} cd "${TOP}"
836 fi
837 KERNCONFDIR="$(getmakevar KERNCONFDIR)"
838 KERNOBJDIR="$(getmakevar KERNOBJDIR)"
839 case "${kernconf}" in
840 */*)
841 kernconfpath="${kernconf}"
842 kernconfbase="$(basename "${kernconf}")"
843 ;;
844 *)
845 kernconfpath="${KERNCONFDIR}/${kernconf}"
846 kernconfbase="${kernconf}"
847 ;;
848 esac
849 kernbuilddir="${KERNOBJDIR}/${kernconfbase}"
850 statusmsg "Kernel build directory: ${kernbuilddir}"
851 ${runcmd} mkdir -p "${kernbuilddir}" ||
852 bomb "Cannot mkdir: ${kernbuilddir}"
853 if [ -z "${UPDATE}" ]; then
854 ${runcmd} cd "${kernbuilddir}"
855 ${runcmd} "${makewrapper}" cleandir ||
856 bomb "Failed to make cleandir in ${kernbuilddir}"
857 ${runcmd} cd "${TOP}"
858 fi
859 ${runcmd} "${TOOLDIR}/bin/${toolprefix}config" -b "${kernbuilddir}" \
860 -s "${TOP}/sys" "${kernconfpath}" ||
861 bomb "${toolprefix}config failed for ${kernconf}"
862 ${runcmd} cd "${kernbuilddir}"
863 ${runcmd} "${makewrapper}" depend ||
864 bomb "Failed to make depend in ${kernbuilddir}"
865 ${runcmd} "${makewrapper}" ${parallel} all ||
866 bomb "Failed to make all in ${kernbuilddir}"
867 ${runcmd} cd "${TOP}"
868
869 if [ "${runcmd}" != "echo" ]; then
870 statusmsg "Kernels built from ${kernconf}:"
871 kernlist=$(awk '$1 == "config" { print $2 }' ${kernconfpath})
872 for kern in ${kernlist:-netbsd}; do
873 [ -f "${kernbuilddir}/${kern}" ] && \
874 echo " ${kernbuilddir}/${kern}"
875 done | tee -a "${results}"
876 fi
877 }
878
879 installworld()
880 {
881 dir="$1"
882 ${runcmd} "${makewrapper}" INSTALLWORLDDIR="${dir}" installworld ||
883 bomb "Failed to make installworld to ${dir}"
884 statusmsg "Successful installworld to ${dir}"
885 }
886
887
888 main()
889 {
890 initdefaults
891 parseoptions "$@"
892
893 build_start=$(date)
894 statusmsg "${progname} command: $0 $@"
895 statusmsg "${progname} started: ${build_start}"
896
897 rebuildmake
898 validatemakeparams
899 createmakewrapper
900
901 # Perform the operations.
902 #
903 for op in ${operations}; do
904 case "${op}" in
905
906 makewrapper)
907 # no-op
908 ;;
909
910 tools)
911 buildtools
912 ;;
913
914 obj|build|distribution|release|sets|sourcesets)
915 ${runcmd} "${makewrapper}" ${parallel} ${op} ||
916 bomb "Failed to make ${op}"
917 statusmsg "Successful make ${op}"
918 ;;
919
920 kernel=*)
921 arg=${op#*=}
922 buildkernel "${arg}"
923 ;;
924
925 install=*)
926 arg=${op#*=}
927 if [ "${arg}" = "/" ] && \
928 ( [ "${uname_s}" != "NetBSD" ] || \
929 [ "${uname_m}" != "${MACHINE}" ] ); then
930 bomb "'${op}' must != / for cross builds."
931 fi
932 installworld "${arg}"
933 ;;
934
935 *)
936 bomb "Unknown operation \`${op}'"
937 ;;
938
939 esac
940 done
941
942 statusmsg "${progname} ended: $(date)"
943 if [ -s "${results}" ]; then
944 echo "===> Summary of results:"
945 sed -e 's/^===>//;s/^/ /' "${results}"
946 echo "===> ."
947 fi
948 }
949
950 main "$@"
951