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