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