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