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