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