1 #!/bin/ksh -p
   2 #
   3 # CDDL HEADER START
   4 #
   5 # The contents of this file are subject to the terms of the
   6 # Common Development and Distribution License (the "License").
   7 # You may not use this file except in compliance with the License.
   8 #
   9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
  10 # or http://www.opensolaris.org/os/licensing.
  11 # See the License for the specific language governing permissions
  12 # and limitations under the License.
  13 #
  14 # When distributing Covered Code, include this CDDL HEADER in each
  15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  16 # If applicable, add the following below this CDDL HEADER, with the
  17 # fields enclosed by brackets "[]" replaced with your own identifying
  18 # information: Portions Copyright [yyyy] [name of copyright owner]
  19 #
  20 # CDDL HEADER END
  21 #
  22 
  23 #
  24 # Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
  25 # Copyright 2008, 2010, Richard Lowe
  26 # Copyright 2011 Nexenta Systems, Inc.  All rights reserved.
  27 # Copyright 2012 Joshua M. Clulow <josh@sysmgr.org>
  28 #
  29 # Based on the nightly script from the integration folks,
  30 # Mostly modified and owned by mike_s.
  31 # Changes also by kjc, dmk.
  32 #
  33 # BRINGOVER_WS may be specified in the env file.
  34 # The default is the old behavior of CLONE_WS
  35 #
  36 # -i on the command line, means fast options, so when it's on the
  37 # command line (only), lint and check builds are skipped no matter what
  38 # the setting of their individual flags are in NIGHTLY_OPTIONS.
  39 #
  40 # LINTDIRS can be set in the env file, format is a list of:
  41 #
  42 #       /dirname-to-run-lint-on flag
  43 #
  44 #       Where flag is:  y - enable lint noise diff output
  45 #                       n - disable lint noise diff output
  46 #
  47 #       For example: LINTDIRS="$SRC/uts n $SRC/stand y $SRC/psm y"
  48 #
  49 # OPTHOME  may be set in the environment to override /opt
  50 #
  51 
  52 #
  53 # The CDPATH variable causes ksh's `cd' builtin to emit messages to stdout
  54 # under certain circumstances, which can really screw things up; unset it.
  55 #
  56 unset CDPATH
  57 
  58 # Get the absolute path of the nightly script that the user invoked.  This
  59 # may be a relative path, and we need to do this before changing directory.
  60 nightly_path=`whence $0`
  61 
  62 #
  63 # Keep track of where we found nightly so we can invoke the matching
  64 # which_scm script.  If that doesn't work, don't go guessing, just rely
  65 # on the $PATH settings, which will generally give us either /opt/onbld
  66 # or the user's workspace.
  67 #
  68 WHICH_SCM=$(dirname $nightly_path)/which_scm
  69 if [[ ! -x $WHICH_SCM ]]; then
  70         WHICH_SCM=which_scm
  71 fi
  72 
  73 function fatal_error
  74 {
  75         print -u2 "nightly: $*"
  76         exit 1
  77 }
  78 
  79 #
  80 # Function to do a DEBUG and non-DEBUG build. Needed because we might
  81 # need to do another for the source build, and since we only deliver DEBUG or
  82 # non-DEBUG packages.
  83 #
  84 # usage: normal_build
  85 #
  86 function normal_build {
  87 
  88         typeset orig_p_FLAG="$p_FLAG"
  89         typeset crypto_signer="$CODESIGN_USER"
  90 
  91         suffix=""
  92 
  93         # non-DEBUG build begins
  94 
  95         if [ "$F_FLAG" = "n" ]; then
  96                 set_non_debug_build_flags
  97                 CODESIGN_USER="$crypto_signer" \
  98                     build "non-DEBUG" "$suffix-nd" "-nd" "$MULTI_PROTO"
  99         else
 100                 echo "\n==== No non-DEBUG $open_only build ====\n" >> "$LOGFILE"
 101         fi
 102 
 103         # non-DEBUG build ends
 104 
 105         # DEBUG build begins
 106 
 107         if [ "$D_FLAG" = "y" ]; then
 108                 set_debug_build_flags
 109                 CODESIGN_USER="$crypto_signer" \
 110                     build "DEBUG" "$suffix" "" "$MULTI_PROTO"
 111         else
 112                 echo "\n==== No DEBUG $open_only build ====\n" >> "$LOGFILE"
 113         fi
 114 
 115         # DEBUG build ends
 116 
 117         p_FLAG="$orig_p_FLAG"
 118 }
 119 
 120 #
 121 # usage: run_hook HOOKNAME ARGS...
 122 #
 123 # If variable "$HOOKNAME" is defined, insert a section header into 
 124 # our logs and then run the command with ARGS
 125 #
 126 function run_hook {
 127         HOOKNAME=$1
 128         eval HOOKCMD=\$$HOOKNAME
 129         shift
 130 
 131         if [ -n "$HOOKCMD" ]; then 
 132                 (
 133                         echo "\n==== Running $HOOKNAME command: $HOOKCMD ====\n"
 134                         ( $HOOKCMD "$@" 2>&1 )
 135                         if [ "$?" -ne 0 ]; then
 136                                 # Let exit status propagate up
 137                                 touch $TMPDIR/abort
 138                         fi
 139                 ) | tee -a $mail_msg_file >> $LOGFILE
 140 
 141                 if [ -f $TMPDIR/abort ]; then
 142                         build_ok=n
 143                         echo "\nAborting at request of $HOOKNAME" |
 144                                 tee -a $mail_msg_file >> $LOGFILE
 145                         exit 1
 146                 fi
 147         fi
 148 }
 149 
 150 # Return library search directive as function of given root.
 151 function myldlibs {
 152         echo "-L$1/lib -L$1/usr/lib"
 153 }
 154 
 155 # Return header search directive as function of given root.
 156 function myheaders {
 157         echo "-I$1/usr/include"
 158 }
 159 
 160 #
 161 # Function to do the build, including package generation.
 162 # usage: build LABEL SUFFIX ND MULTIPROTO
 163 # - LABEL is used to tag build output.
 164 # - SUFFIX is used to distinguish files (e.g., DEBUG vs non-DEBUG,
 165 #   open-only vs full tree).
 166 # - ND is "-nd" (non-DEBUG builds) or "" (DEBUG builds).
 167 # - If MULTIPROTO is "yes", it means to name the proto area according to
 168 #   SUFFIX.  Otherwise ("no"), (re)use the standard proto area.
 169 #
 170 function build {
 171         LABEL=$1
 172         SUFFIX=$2
 173         ND=$3
 174         MULTIPROTO=$4
 175         INSTALLOG=install${SUFFIX}-${MACH}
 176         NOISE=noise${SUFFIX}-${MACH}
 177         PKGARCHIVE=${PKGARCHIVE_ORIG}${SUFFIX}
 178 
 179         ORIGROOT=$ROOT
 180         [ $MULTIPROTO = no ] || export ROOT=$ROOT$SUFFIX
 181 
 182         export ENVLDLIBS1=`myldlibs $ROOT`
 183         export ENVCPPFLAGS1=`myheaders $ROOT`
 184 
 185         this_build_ok=y
 186         #
 187         #       Build OS-Networking source
 188         #
 189         echo "\n==== Building OS-Net source at `date` ($LABEL) ====\n" \
 190                 >> $LOGFILE
 191 
 192         rm -f $SRC/${INSTALLOG}.out
 193         cd $SRC
 194         /bin/time $MAKE -e install 2>&1 | \
 195             tee -a $SRC/${INSTALLOG}.out >> $LOGFILE
 196 
 197         echo "\n==== Build errors ($LABEL) ====\n" >> $mail_msg_file
 198         egrep ":" $SRC/${INSTALLOG}.out |
 199                 egrep -e "(^${MAKE}:|[  ]error[:        \n])" | \
 200                 egrep -v "Ignoring unknown host" | \
 201                 egrep -v "cc .* -o error " | \
 202                 egrep -v "warning" | tee $TMPDIR/build_errs${SUFFIX} \
 203                 >> $mail_msg_file
 204         if [[ -s $TMPDIR/build_errs${SUFFIX} ]]; then
 205                 build_ok=n
 206                 this_build_ok=n
 207         fi
 208         grep "bootblock image is .* bytes too big" $SRC/${INSTALLOG}.out \
 209                 >> $mail_msg_file
 210         if [ "$?" = "0" ]; then
 211                 build_ok=n
 212                 this_build_ok=n
 213         fi
 214 
 215         echo "\n==== Build warnings ($LABEL) ====\n" >>$mail_msg_file
 216         egrep -i warning: $SRC/${INSTALLOG}.out \
 217                 | egrep -v '^tic:' \
 218                 | egrep -v "symbol (\`|')timezone' has differing types:" \
 219                 | egrep -v "parameter <PSTAMP> set to" \
 220                 | egrep -v "Ignoring unknown host" \
 221                 | egrep -v "redefining segment flags attribute for" \
 222                 | tee $TMPDIR/build_warnings${SUFFIX} >> $mail_msg_file
 223         if [[ -s $TMPDIR/build_warnings${SUFFIX} ]]; then
 224                 build_ok=n
 225                 this_build_ok=n
 226         fi
 227 
 228         echo "\n==== Ended OS-Net source build at `date` ($LABEL) ====\n" \
 229                 >> $LOGFILE
 230 
 231         echo "\n==== Elapsed build time ($LABEL) ====\n" >>$mail_msg_file
 232         tail -3  $SRC/${INSTALLOG}.out >>$mail_msg_file
 233 
 234         if [ "$i_FLAG" = "n" ]; then
 235                 rm -f $SRC/${NOISE}.ref
 236                 if [ -f $SRC/${NOISE}.out ]; then
 237                         mv $SRC/${NOISE}.out $SRC/${NOISE}.ref
 238                 fi
 239                 grep : $SRC/${INSTALLOG}.out \
 240                         | egrep -v '^/' \
 241                         | egrep -v '^(Start|Finish|real|user|sys|./bld_awk)' \
 242                         | egrep -v '^tic:' \
 243                         | egrep -v '^mcs' \
 244                         | egrep -v '^LD_LIBRARY_PATH=' \
 245                         | egrep -v 'ar: creating' \
 246                         | egrep -v 'ar: writing' \
 247                         | egrep -v 'conflicts:' \
 248                         | egrep -v ':saved created' \
 249                         | egrep -v '^stty.*c:' \
 250                         | egrep -v '^mfgname.c:' \
 251                         | egrep -v '^uname-i.c:' \
 252                         | egrep -v '^volumes.c:' \
 253                         | egrep -v '^lint library construction:' \
 254                         | egrep -v 'tsort: INFORM:' \
 255                         | egrep -v 'stripalign:' \
 256                         | egrep -v 'chars, width' \
 257                         | egrep -v "symbol (\`|')timezone' has differing types:" \
 258                         | egrep -v 'PSTAMP' \
 259                         | egrep -v '|%WHOANDWHERE%|' \
 260                         | egrep -v '^Manifying' \
 261                         | egrep -v 'Ignoring unknown host' \
 262                         | egrep -v 'Processing method:' \
 263                         | egrep -v '^Writing' \
 264                         | egrep -v 'spellin1:' \
 265                         | egrep -v '^adding:' \
 266                         | egrep -v "^echo 'msgid" \
 267                         | egrep -v '^echo ' \
 268                         | egrep -v '\.c:$' \
 269                         | egrep -v '^Adding file:' \
 270                         | egrep -v 'CLASSPATH=' \
 271                         | egrep -v '\/var\/mail\/:saved' \
 272                         | egrep -v -- '-DUTS_VERSION=' \
 273                         | egrep -v '^Running Mkbootstrap' \
 274                         | egrep -v '^Applet length read:' \
 275                         | egrep -v 'bytes written:' \
 276                         | egrep -v '^File:SolarisAuthApplet.bin' \
 277                         | egrep -v -i 'jibversion' \
 278                         | egrep -v '^Output size:' \
 279                         | egrep -v '^Solo size statistics:' \
 280                         | egrep -v '^Using ROM API Version' \
 281                         | egrep -v '^Zero Signature length:' \
 282                         | egrep -v '^Note \(probably harmless\):' \
 283                         | egrep -v '::' \
 284                         | egrep -v -- '-xcache' \
 285                         | egrep -v '^\+' \
 286                         | egrep -v '^cc1: note: -fwritable-strings' \
 287                         | egrep -v 'svccfg-native -s svc:/' \
 288                         | sort | uniq >$SRC/${NOISE}.out
 289                 if [ ! -f $SRC/${NOISE}.ref ]; then
 290                         cp $SRC/${NOISE}.out $SRC/${NOISE}.ref
 291                 fi
 292                 echo "\n==== Build noise differences ($LABEL) ====\n" \
 293                         >>$mail_msg_file
 294                 diff $SRC/${NOISE}.ref $SRC/${NOISE}.out >>$mail_msg_file
 295         fi
 296 
 297         #
 298         #       Re-sign selected binaries using signing server
 299         #       (gatekeeper builds only)
 300         #
 301         if [ -n "$CODESIGN_USER" -a "$this_build_ok" = "y" ]; then
 302                 echo "\n==== Signing proto area at `date` ====\n" >> $LOGFILE
 303                 signing_file="${TMPDIR}/signing"
 304                 rm -f ${signing_file}
 305                 export CODESIGN_USER
 306                 signproto $SRC/tools/codesign/creds 2>&1 | \
 307                         tee -a ${signing_file} >> $LOGFILE
 308                 echo "\n==== Finished signing proto area at `date` ====\n" \
 309                     >> $LOGFILE
 310                 echo "\n==== Crypto module signing errors ($LABEL) ====\n" \
 311                     >> $mail_msg_file
 312                 egrep 'WARNING|ERROR' ${signing_file} >> $mail_msg_file
 313                 if (( $? == 0 )) ; then
 314                         build_ok=n
 315                         this_build_ok=n
 316                 fi
 317         fi
 318 
 319         #
 320         #       Building Packages
 321         #
 322         if [ "$p_FLAG" = "y" -a "$this_build_ok" = "y" ]; then
 323                 if [ -d $SRC/pkg ]; then
 324                         echo "\n==== Creating $LABEL packages at `date` ====\n" \
 325                                 >> $LOGFILE
 326                         echo "Clearing out $PKGARCHIVE ..." >> $LOGFILE
 327                         rm -rf $PKGARCHIVE >> "$LOGFILE" 2>&1
 328                         mkdir -p $PKGARCHIVE >> "$LOGFILE" 2>&1
 329 
 330                         rm -f $SRC/pkg/${INSTALLOG}.out
 331                         cd $SRC/pkg
 332                         /bin/time $MAKE -e install 2>&1 | \
 333                             tee -a $SRC/pkg/${INSTALLOG}.out >> $LOGFILE
 334 
 335                         echo "\n==== package build errors ($LABEL) ====\n" \
 336                                 >> $mail_msg_file
 337 
 338                         egrep "${MAKE}|ERROR|WARNING" $SRC/pkg/${INSTALLOG}.out | \
 339                                 grep ':' | \
 340                                 grep -v PSTAMP | \
 341                                 egrep -v "Ignoring unknown host" | \
 342                                 tee $TMPDIR/package >> $mail_msg_file
 343                         if [[ -s $TMPDIR/package ]]; then
 344                                 build_extras_ok=n
 345                                 this_build_ok=n
 346                         fi
 347                 else
 348                         #
 349                         # Handle it gracefully if -p was set but there so
 350                         # no pkg directory.
 351                         #
 352                         echo "\n==== No $LABEL packages to build ====\n" \
 353                                 >> $LOGFILE
 354                 fi
 355         else
 356                 echo "\n==== Not creating $LABEL packages ====\n" >> $LOGFILE
 357         fi
 358 
 359         ROOT=$ORIGROOT
 360 }
 361 
 362 # Usage: dolint /dir y|n
 363 # Arg. 2 is a flag to turn on/off the lint diff output
 364 function dolint {
 365         if [ ! -d "$1" ]; then
 366                 echo "dolint error: $1 is not a directory"
 367                 exit 1
 368         fi
 369 
 370         if [ "$2" != "y" -a "$2" != "n" ]; then
 371                 echo "dolint internal error: $2 should be 'y' or 'n'"
 372                 exit 1
 373         fi
 374 
 375         lintdir=$1
 376         dodiff=$2
 377         base=`basename $lintdir`
 378         LINTOUT=$lintdir/lint-${MACH}.out
 379         LINTNOISE=$lintdir/lint-noise-${MACH}
 380         export ENVLDLIBS1=`myldlibs $ROOT`
 381         export ENVCPPFLAGS1=`myheaders $ROOT`
 382 
 383         set_debug_build_flags
 384 
 385         #
 386         #       '$MAKE lint' in $lintdir
 387         #
 388         echo "\n==== Begin '$MAKE lint' of $base at `date` ====\n" >> $LOGFILE
 389 
 390         # remove old lint.out
 391         rm -f $lintdir/lint.out $lintdir/lint-noise.out
 392         if [ -f $lintdir/lint-noise.ref ]; then
 393                 mv $lintdir/lint-noise.ref ${LINTNOISE}.ref
 394         fi
 395 
 396         rm -f $LINTOUT
 397         cd $lintdir
 398         #
 399         # Remove all .ln files to ensure a full reference file
 400         #
 401         rm -f Nothing_to_remove \
 402             `find . \( -name SCCS -o -name .hg -o -name .svn -o -name .git \) \
 403                 -prune -o -type f -name '*.ln' -print `
 404 
 405         /bin/time $MAKE -ek lint 2>&1 | \
 406             tee -a $LINTOUT >> $LOGFILE
 407 
 408         echo "\n==== '$MAKE lint' of $base ERRORS ====\n" >> $mail_msg_file
 409 
 410         grep "$MAKE:" $LINTOUT |
 411                 egrep -v "Ignoring unknown host" | \
 412                 tee $TMPDIR/lint_errs >> $mail_msg_file
 413         if [[ -s $TMPDIR/lint_errs ]]; then
 414                 build_extras_ok=n
 415         fi
 416 
 417         echo "\n==== Ended '$MAKE lint' of $base at `date` ====\n" >> $LOGFILE
 418 
 419         echo "\n==== Elapsed time of '$MAKE lint' of $base ====\n" \
 420                 >>$mail_msg_file
 421         tail -3  $LINTOUT >>$mail_msg_file
 422 
 423         rm -f ${LINTNOISE}.ref
 424         if [ -f ${LINTNOISE}.out ]; then
 425                 mv ${LINTNOISE}.out ${LINTNOISE}.ref
 426         fi
 427         grep : $LINTOUT | \
 428                 egrep -v '^(real|user|sys)' |
 429                 egrep -v '(library construction)' | \
 430                 egrep -v ': global crosschecks' | \
 431                 egrep -v 'Ignoring unknown host' | \
 432                 egrep -v '\.c:$' | \
 433                 sort | uniq > ${LINTNOISE}.out
 434         if [ ! -f ${LINTNOISE}.ref ]; then
 435                 cp ${LINTNOISE}.out ${LINTNOISE}.ref
 436         fi
 437 
 438         if [ "$dodiff" != "n" ]; then
 439                 echo "\n==== lint warnings $base ====\n" \
 440                         >>$mail_msg_file
 441                 # should be none, though there are a few that were filtered out
 442                 # above
 443                 egrep -i '(warning|lint):' ${LINTNOISE}.out \
 444                         | sort | uniq | tee $TMPDIR/lint_warns >> $mail_msg_file
 445                 if [[ -s $TMPDIR/lint_warns ]]; then
 446                         build_extras_ok=n
 447                 fi
 448                 echo "\n==== lint noise differences $base ====\n" \
 449                         >> $mail_msg_file
 450                 diff ${LINTNOISE}.ref ${LINTNOISE}.out \
 451                         >> $mail_msg_file
 452         fi
 453 }
 454 
 455 #
 456 # Build and install the onbld tools.
 457 #
 458 # usage: build_tools DESTROOT
 459 #
 460 # returns non-zero status if the build was successful.
 461 #
 462 function build_tools {
 463         DESTROOT=$1
 464 
 465         INSTALLOG=install-${MACH}
 466 
 467         echo "\n==== Building tools at `date` ====\n" \
 468                 >> $LOGFILE
 469 
 470         rm -f ${TOOLS}/${INSTALLOG}.out
 471         cd ${TOOLS}
 472         /bin/time $MAKE TOOLS_PROTO=${DESTROOT} -e install 2>&1 | \
 473             tee -a ${TOOLS}/${INSTALLOG}.out >> $LOGFILE
 474 
 475         echo "\n==== Tools build errors ====\n" >> $mail_msg_file
 476 
 477         egrep ":" ${TOOLS}/${INSTALLOG}.out |
 478                 egrep -e "(${MAKE}:|[   ]error[:        \n])" | \
 479                 egrep -v "Ignoring unknown host" | \
 480                 egrep -v warning | tee $TMPDIR/tools_errors >> $mail_msg_file
 481 
 482         if [[ -s $TMPDIR/tools_errors ]]; then
 483                 return 1
 484         fi
 485         return 0
 486 }
 487 
 488 #
 489 # Set up to use locally installed tools.
 490 #
 491 # usage: use_tools TOOLSROOT
 492 #
 493 function use_tools {
 494         TOOLSROOT=$1
 495 
 496         #
 497         # If we're not building ON workspace, then the TOOLSROOT
 498         # settings here are clearly ignored by the workspace
 499         # makefiles, prepending nonexistent directories to PATH is
 500         # harmless, and we clearly do not wish to override
 501         # ONBLD_TOOLS.
 502         #
 503         # If we're building an ON workspace, then the prepended PATH
 504         # elements should supercede the preexisting ONBLD_TOOLS paths,
 505         # and we want to override ONBLD_TOOLS to catch the tools that
 506         # don't have specific path env vars here.
 507         #
 508         # So the only conditional behavior is overriding ONBLD_TOOLS,
 509         # and we check for "an ON workspace" by looking for
 510         # ${TOOLSROOT}/opt/onbld.
 511         #
 512 
 513         STABS=${TOOLSROOT}/opt/onbld/bin/${MACH}/stabs
 514         export STABS
 515         CTFSTABS=${TOOLSROOT}/opt/onbld/bin/${MACH}/ctfstabs
 516         export CTFSTABS
 517         GENOFFSETS=${TOOLSROOT}/opt/onbld/bin/genoffsets
 518         export GENOFFSETS
 519 
 520         CTFCONVERT=${TOOLSROOT}/opt/onbld/bin/${MACH}/ctfconvert
 521         export CTFCONVERT
 522         CTFMERGE=${TOOLSROOT}/opt/onbld/bin/${MACH}/ctfmerge
 523         export CTFMERGE
 524 
 525         if [ "$VERIFY_ELFSIGN" = "y" ]; then
 526                 ELFSIGN=${TOOLSROOT}/opt/onbld/bin/elfsigncmp
 527         else
 528                 ELFSIGN=${TOOLSROOT}/opt/onbld/bin/${MACH}/elfsign
 529         fi
 530         export ELFSIGN
 531 
 532         PATH="${TOOLSROOT}/opt/onbld/bin/${MACH}:${PATH}"
 533         PATH="${TOOLSROOT}/opt/onbld/bin:${PATH}"
 534         export PATH
 535 
 536         if [ -d "${TOOLSROOT}/opt/onbld" ]; then
 537                 ONBLD_TOOLS=${TOOLSROOT}/opt/onbld
 538                 export ONBLD_TOOLS
 539         fi
 540 
 541         echo "\n==== New environment settings. ====\n" >> $LOGFILE
 542         echo "STABS=${STABS}" >> $LOGFILE
 543         echo "CTFSTABS=${CTFSTABS}" >> $LOGFILE
 544         echo "CTFCONVERT=${CTFCONVERT}" >> $LOGFILE
 545         echo "CTFMERGE=${CTFMERGE}" >> $LOGFILE
 546         echo "ELFSIGN=${ELFSIGN}" >> $LOGFILE
 547         echo "PATH=${PATH}" >> $LOGFILE
 548         echo "ONBLD_TOOLS=${ONBLD_TOOLS}" >> $LOGFILE
 549 }
 550 
 551 function staffer {
 552         if [ $ISUSER -ne 0 ]; then
 553                 "$@"
 554         else
 555                 arg="\"$1\""
 556                 shift
 557                 for i
 558                 do
 559                         arg="$arg \"$i\""
 560                 done
 561                 eval su $STAFFER -c \'$arg\'
 562         fi
 563 }
 564 
 565 #
 566 # Verify that the closed bins are present
 567 #
 568 function check_closed_bins {
 569         if [[ ! -d "$ON_CLOSED_BINS" ]]; then
 570                 echo "ON_CLOSED_BINS must point to the closed binaries tree."
 571                 build_ok=n
 572                 exit 1
 573         fi
 574 }
 575 
 576 #
 577 # wrapper over wsdiff.
 578 # usage: do_wsdiff LABEL OLDPROTO NEWPROTO
 579 #
 580 function do_wsdiff {
 581         label=$1
 582         oldproto=$2
 583         newproto=$3
 584 
 585         wsdiff="wsdiff"
 586         [ "$t_FLAG" = y ] && wsdiff="wsdiff -t"
 587 
 588         echo "\n==== Getting object changes since last build at `date`" \
 589             "($label) ====\n" | tee -a $LOGFILE >> $mail_msg_file
 590         $wsdiff -s -r ${TMPDIR}/wsdiff.results $oldproto $newproto 2>&1 | \
 591                     tee -a $LOGFILE >> $mail_msg_file
 592         echo "\n==== Object changes determined at `date` ($label) ====\n" | \
 593             tee -a $LOGFILE >> $mail_msg_file
 594 }
 595 
 596 #
 597 # Functions for setting build flags (DEBUG/non-DEBUG).  Keep them
 598 # together.
 599 #
 600 
 601 function set_non_debug_build_flags {
 602         export RELEASE_BUILD ; RELEASE_BUILD=
 603         unset EXTRA_OPTIONS
 604         unset EXTRA_CFLAGS
 605 }
 606 
 607 function set_debug_build_flags {
 608         unset RELEASE_BUILD
 609         unset EXTRA_OPTIONS
 610         unset EXTRA_CFLAGS
 611 }
 612 
 613 
 614 MACH=`uname -p`
 615 
 616 if [ "$OPTHOME" = "" ]; then
 617         OPTHOME=/opt
 618         export OPTHOME
 619 fi
 620 
 621 USAGE='Usage: nightly [-in] [+t] [-V VERS ] <env_file>
 622 
 623 Where:
 624         -i      Fast incremental options (no clobber, lint, check)
 625         -n      Do not do a bringover
 626         +t      Use the build tools in $ONBLD_TOOLS/bin
 627         -V VERS set the build version string to VERS
 628 
 629         <env_file>  file in Bourne shell syntax that sets and exports
 630         variables that configure the operation of this script and many of
 631         the scripts this one calls. If <env_file> does not exist,
 632         it will be looked for in $OPTHOME/onbld/env.
 633 
 634 non-DEBUG is the default build type. Build options can be set in the
 635 NIGHTLY_OPTIONS variable in the <env_file> as follows:
 636 
 637         -A      check for ABI differences in .so files
 638         -C      check for cstyle/hdrchk errors
 639         -D      do a build with DEBUG on
 640         -F      do _not_ do a non-DEBUG build
 641         -G      gate keeper default group of options (-au)
 642         -I      integration engineer default group of options (-ampu)
 643         -M      do not run pmodes (safe file permission checker)
 644         -N      do not run protocmp
 645         -R      default group of options for building a release (-mp)
 646         -U      update proto area in the parent
 647         -V VERS set the build version string to VERS
 648         -f      find unreferenced files
 649         -i      do an incremental build (no "make clobber")
 650         -l      do "make lint" in $LINTDIRS (default: $SRC y)
 651         -m      send mail to $MAILTO at end of build
 652         -n      do not do a bringover
 653         -p      create packages
 654         -r      check ELF runtime attributes in the proto area
 655         -t      build and use the tools in $SRC/tools (default setting)
 656         +t      Use the build tools in $ONBLD_TOOLS/bin
 657         -u      update proto_list_$MACH and friends in the parent workspace;
 658                 when used with -f, also build an unrefmaster.out in the parent
 659         -w      report on differences between previous and current proto areas
 660 '
 661 #
 662 #       A log file will be generated under the name $LOGFILE
 663 #       for partially completed build and log.`date '+%F'`
 664 #       in the same directory for fully completed builds.
 665 #
 666 
 667 # default values for low-level FLAGS; G I R are group FLAGS
 668 A_FLAG=n
 669 C_FLAG=n
 670 D_FLAG=n
 671 F_FLAG=n
 672 f_FLAG=n
 673 i_FLAG=n; i_CMD_LINE_FLAG=n
 674 l_FLAG=n
 675 M_FLAG=n
 676 m_FLAG=n
 677 N_FLAG=n
 678 n_FLAG=n
 679 p_FLAG=n
 680 r_FLAG=n
 681 t_FLAG=y
 682 U_FLAG=n
 683 u_FLAG=n
 684 V_FLAG=n
 685 w_FLAG=n
 686 W_FLAG=n
 687 #
 688 build_ok=y
 689 build_extras_ok=y
 690 
 691 #
 692 # examine arguments
 693 #
 694 
 695 OPTIND=1
 696 while getopts +intV:W FLAG
 697 do
 698         case $FLAG in
 699           i )   i_FLAG=y; i_CMD_LINE_FLAG=y
 700                 ;;
 701           n )   n_FLAG=y
 702                 ;;
 703          +t )   t_FLAG=n
 704                 ;;
 705           V )   V_FLAG=y
 706                 V_ARG="$OPTARG"
 707                 ;;
 708           W )   W_FLAG=y
 709                 ;;
 710          \? )   echo "$USAGE"
 711                 exit 1
 712                 ;;
 713         esac
 714 done
 715 
 716 # correct argument count after options
 717 shift `expr $OPTIND - 1`
 718 
 719 # test that the path to the environment-setting file was given
 720 if [ $# -ne 1 ]; then
 721         echo "$USAGE"
 722         exit 1
 723 fi
 724 
 725 # check if user is running nightly as root
 726 # ISUSER is set non-zero if an ordinary user runs nightly, or is zero
 727 # when root invokes nightly.
 728 /usr/bin/id | grep '^uid=0(' >/dev/null 2>&1
 729 ISUSER=$?;      export ISUSER
 730 
 731 #
 732 # force locale to C
 733 LANG=C;         export LANG
 734 LC_ALL=C;       export LC_ALL
 735 LC_COLLATE=C;   export LC_COLLATE
 736 LC_CTYPE=C;     export LC_CTYPE
 737 LC_MESSAGES=C;  export LC_MESSAGES
 738 LC_MONETARY=C;  export LC_MONETARY
 739 LC_NUMERIC=C;   export LC_NUMERIC
 740 LC_TIME=C;      export LC_TIME
 741 
 742 # clear environment variables we know to be bad for the build
 743 unset LD_OPTIONS
 744 unset LD_AUDIT          LD_AUDIT_32             LD_AUDIT_64
 745 unset LD_BIND_NOW       LD_BIND_NOW_32          LD_BIND_NOW_64
 746 unset LD_BREADTH        LD_BREADTH_32           LD_BREADTH_64
 747 unset LD_CONFIG         LD_CONFIG_32            LD_CONFIG_64
 748 unset LD_DEBUG          LD_DEBUG_32             LD_DEBUG_64
 749 unset LD_DEMANGLE       LD_DEMANGLE_32          LD_DEMANGLE_64
 750 unset LD_FLAGS          LD_FLAGS_32             LD_FLAGS_64
 751 unset LD_LIBRARY_PATH   LD_LIBRARY_PATH_32      LD_LIBRARY_PATH_64
 752 unset LD_LOADFLTR       LD_LOADFLTR_32          LD_LOADFLTR_64
 753 unset LD_NOAUDIT        LD_NOAUDIT_32           LD_NOAUDIT_64
 754 unset LD_NOAUXFLTR      LD_NOAUXFLTR_32         LD_NOAUXFLTR_64
 755 unset LD_NOCONFIG       LD_NOCONFIG_32          LD_NOCONFIG_64
 756 unset LD_NODIRCONFIG    LD_NODIRCONFIG_32       LD_NODIRCONFIG_64
 757 unset LD_NODIRECT       LD_NODIRECT_32          LD_NODIRECT_64
 758 unset LD_NOLAZYLOAD     LD_NOLAZYLOAD_32        LD_NOLAZYLOAD_64
 759 unset LD_NOOBJALTER     LD_NOOBJALTER_32        LD_NOOBJALTER_64
 760 unset LD_NOVERSION      LD_NOVERSION_32         LD_NOVERSION_64
 761 unset LD_ORIGIN         LD_ORIGIN_32            LD_ORIGIN_64
 762 unset LD_PRELOAD        LD_PRELOAD_32           LD_PRELOAD_64
 763 unset LD_PROFILE        LD_PROFILE_32           LD_PROFILE_64
 764 
 765 unset CONFIG
 766 unset GROUP
 767 unset OWNER
 768 unset REMOTE
 769 unset ENV
 770 unset ARCH
 771 unset CLASSPATH
 772 unset NAME
 773 
 774 #
 775 # To get ONBLD_TOOLS from the environment, it must come from the env file.
 776 # If it comes interactively, it is generally TOOLS_PROTO, which will be
 777 # clobbered before the compiler version checks, which will therefore fail.
 778 #
 779 unset ONBLD_TOOLS
 780 
 781 #
 782 #       Setup environmental variables
 783 #
 784 if [ -f /etc/nightly.conf ]; then
 785         . /etc/nightly.conf
 786 fi    
 787 
 788 if [ -f $1 ]; then
 789         if [[ $1 = */* ]]; then
 790                 . $1
 791         else
 792                 . ./$1
 793         fi
 794 else
 795         if [ -f $OPTHOME/onbld/env/$1 ]; then
 796                 . $OPTHOME/onbld/env/$1
 797         else
 798                 echo "Cannot find env file as either $1 or $OPTHOME/onbld/env/$1"
 799                 exit 1
 800         fi
 801 fi
 802 
 803 # contents of stdenv.sh inserted after next line:
 804 # STDENV_START
 805 # STDENV_END
 806 
 807 # Check if we have sufficient data to continue...
 808 [[ -v CODEMGR_WS ]] || fatal_error "Error: Variable CODEMGR_WS not set."
 809 if  [[ "${NIGHTLY_OPTIONS}" == ~(F)n ]] ; then
 810         # Check if the gate data are valid if we don't do a "bringover" below
 811         [[ -d "${CODEMGR_WS}" ]] || \
 812                 fatal_error "Error: ${CODEMGR_WS} is not a directory."
 813         [[ -f "${CODEMGR_WS}/usr/src/Makefile" ]] || \
 814                 fatal_error "Error: ${CODEMGR_WS}/usr/src/Makefile not found."
 815 fi
 816 
 817 #
 818 # place ourselves in a new task, respecting BUILD_PROJECT if set.
 819 #
 820 if [ -z "$BUILD_PROJECT" ]; then
 821         /usr/bin/newtask -c $$
 822 else
 823         /usr/bin/newtask -c $$ -p $BUILD_PROJECT
 824 fi
 825 
 826 ps -o taskid= -p $$ | read build_taskid
 827 ps -o project= -p $$ | read build_project
 828 
 829 #
 830 # See if NIGHTLY_OPTIONS is set
 831 #
 832 if [ "$NIGHTLY_OPTIONS" = "" ]; then
 833         NIGHTLY_OPTIONS="-aBm"
 834 fi
 835 
 836 #
 837 # If BRINGOVER_WS was not specified, let it default to CLONE_WS
 838 #
 839 if [ "$BRINGOVER_WS" = "" ]; then
 840         BRINGOVER_WS=$CLONE_WS
 841 fi
 842 
 843 #
 844 # If BRINGOVER_FILES was not specified, default to usr
 845 #
 846 if [ "$BRINGOVER_FILES" = "" ]; then
 847         BRINGOVER_FILES="usr"
 848 fi
 849 
 850 check_closed_bins
 851 
 852 #
 853 # Note: changes to the option letters here should also be applied to the
 854 #       bldenv script.  `d' is listed for backward compatibility.
 855 #
 856 NIGHTLY_OPTIONS=-${NIGHTLY_OPTIONS#-}
 857 OPTIND=1
 858 while getopts +ABCDdFfGIilMmNnpRrtUuwW FLAG $NIGHTLY_OPTIONS
 859 do
 860         case $FLAG in
 861           A )   A_FLAG=y
 862                 ;;
 863           B )   D_FLAG=y
 864                 ;; # old version of D
 865           C )   C_FLAG=y
 866                 ;;
 867           D )   D_FLAG=y
 868                 ;;
 869           F )   F_FLAG=y
 870                 ;;
 871           f )   f_FLAG=y
 872                 ;;
 873           G )   u_FLAG=y
 874                 ;;
 875           I )   m_FLAG=y
 876                 p_FLAG=y
 877                 u_FLAG=y
 878                 ;;
 879           i )   i_FLAG=y
 880                 ;;
 881           l )   l_FLAG=y
 882                 ;;
 883           M )   M_FLAG=y
 884                 ;;
 885           m )   m_FLAG=y
 886                 ;;
 887           N )   N_FLAG=y
 888                 ;;
 889           n )   n_FLAG=y
 890                 ;;
 891           p )   p_FLAG=y
 892                 ;;
 893           R )   m_FLAG=y
 894                 p_FLAG=y
 895                 ;;
 896           r )   r_FLAG=y
 897                 ;;
 898          +t )   t_FLAG=n
 899                 ;;
 900           U )   if [ -z "${PARENT_ROOT}" ]; then
 901                         echo "PARENT_ROOT must be set if the U flag is" \
 902                             "present in NIGHTLY_OPTIONS."
 903                         exit 1
 904                 fi
 905                 NIGHTLY_PARENT_ROOT=$PARENT_ROOT
 906                 if [ -n "${PARENT_TOOLS_ROOT}" ]; then
 907                         NIGHTLY_PARENT_TOOLS_ROOT=$PARENT_TOOLS_ROOT
 908                 fi
 909                 U_FLAG=y
 910                 ;;
 911           u )   u_FLAG=y
 912                 ;;
 913           w )   w_FLAG=y
 914                 ;;
 915           W )   W_FLAG=y
 916                 ;;
 917          \? )   echo "$USAGE"
 918                 exit 1
 919                 ;;
 920         esac
 921 done
 922 
 923 if [ $ISUSER -ne 0 ]; then
 924         # Set default value for STAFFER, if needed.
 925         if [ -z "$STAFFER" -o "$STAFFER" = "nobody" ]; then
 926                 STAFFER=`/usr/xpg4/bin/id -un`
 927                 export STAFFER
 928         fi
 929 fi
 930 
 931 if [ -z "$MAILTO" -o "$MAILTO" = "nobody" ]; then
 932         MAILTO=$STAFFER
 933         export MAILTO
 934 fi
 935 
 936 PATH="$OPTHOME/onbld/bin:$OPTHOME/onbld/bin/${MACH}:/usr/ccs/bin"
 937 PATH="$PATH:$OPTHOME/SUNWspro/bin:/usr/bin:/usr/sbin:/usr/ucb"
 938 PATH="$PATH:/usr/openwin/bin:/usr/sfw/bin:/opt/sfw/bin:."
 939 export PATH
 940 
 941 # roots of source trees, both relative to $SRC and absolute.
 942 relsrcdirs="."
 943 abssrcdirs="$SRC"
 944 
 945 PROTOCMPTERSE="protocmp.terse -gu"
 946 POUND_SIGN="#"
 947 # have we set RELEASE_DATE in our env file?
 948 if [ -z "$RELEASE_DATE" ]; then
 949         RELEASE_DATE=$(LC_ALL=C date +"%B %Y")
 950 fi
 951 BUILD_DATE=$(LC_ALL=C date +%Y-%b-%d)
 952 BASEWSDIR=$(basename $CODEMGR_WS)
 953 DEV_CM="\"@(#)SunOS Internal Development: $LOGNAME $BUILD_DATE [$BASEWSDIR]\""
 954 
 955 # we export POUND_SIGN, RELEASE_DATE and DEV_CM to speed up the build process
 956 # by avoiding repeated shell invocations to evaluate Makefile.master
 957 # definitions.
 958 export POUND_SIGN RELEASE_DATE DEV_CM
 959 
 960 maketype="distributed"
 961 if [[ -z "$MAKE" ]]; then
 962         MAKE=dmake
 963 elif [[ ! -x "$MAKE" ]]; then
 964         echo "\$MAKE is set to garbage in the environment"
 965         exit 1  
 966 fi
 967 export PATH
 968 export MAKE
 969 
 970 if [ "${SUNWSPRO}" != "" ]; then
 971         PATH="${SUNWSPRO}/bin:$PATH"
 972         export PATH
 973 fi
 974 
 975 hostname=$(uname -n)
 976 if [[ $DMAKE_MAX_JOBS != +([0-9]) || $DMAKE_MAX_JOBS -eq 0 ]]
 977 then
 978         maxjobs=
 979         if [[ -f $HOME/.make.machines ]]
 980         then
 981                 # Note: there is a hard tab and space character in the []s
 982                 # below.
 983                 egrep -i "^[    ]*$hostname[    \.]" \
 984                         $HOME/.make.machines | read host jobs
 985                 maxjobs=${jobs##*=}
 986         fi
 987 
 988         if [[ $maxjobs != +([0-9]) || $maxjobs -eq 0 ]]
 989         then
 990                 # default
 991                 maxjobs=4
 992         fi
 993 
 994         export DMAKE_MAX_JOBS=$maxjobs
 995 fi
 996 
 997 DMAKE_MODE=parallel;
 998 export DMAKE_MODE
 999 
1000 if [ -z "${ROOT}" ]; then
1001         echo "ROOT must be set."
1002         exit 1
1003 fi
1004 
1005 #
1006 # if -V flag was given, reset VERSION to V_ARG
1007 #
1008 if [ "$V_FLAG" = "y" ]; then
1009         VERSION=$V_ARG
1010 fi
1011 
1012 TMPDIR="/tmp/nightly.tmpdir.$$"
1013 export TMPDIR
1014 rm -rf ${TMPDIR}
1015 mkdir -p $TMPDIR || exit 1
1016 chmod 777 $TMPDIR
1017 
1018 #
1019 # Keep elfsign's use of pkcs11_softtoken from looking in the user home
1020 # directory, which doesn't always work.   Needed until all build machines
1021 # have the fix for 6271754
1022 #
1023 SOFTTOKEN_DIR=$TMPDIR
1024 export SOFTTOKEN_DIR
1025 
1026 #
1027 # Tools should only be built non-DEBUG.  Keep track of the tools proto
1028 # area path relative to $TOOLS, because the latter changes in an
1029 # export build.
1030 #
1031 # TOOLS_PROTO is included below for builds other than usr/src/tools
1032 # that look for this location.  For usr/src/tools, this will be
1033 # overridden on the $MAKE command line in build_tools().
1034 #
1035 TOOLS=${SRC}/tools
1036 TOOLS_PROTO_REL=proto/root_${MACH}-nd
1037 TOOLS_PROTO=${TOOLS}/${TOOLS_PROTO_REL};        export TOOLS_PROTO
1038 
1039 unset   CFLAGS LD_LIBRARY_PATH LDFLAGS
1040 
1041 # create directories that are automatically removed if the nightly script
1042 # fails to start correctly
1043 function newdir {
1044         dir=$1
1045         toadd=
1046         while [ ! -d $dir ]; do
1047                 toadd="$dir $toadd"
1048                 dir=`dirname $dir`
1049         done
1050         torm=
1051         newlist=
1052         for dir in $toadd; do
1053                 if staffer mkdir $dir; then
1054                         newlist="$ISUSER $dir $newlist"
1055                         torm="$dir $torm"
1056                 else
1057                         [ -z "$torm" ] || staffer rmdir $torm
1058                         return 1
1059                 fi
1060         done
1061         newdirlist="$newlist $newdirlist"
1062         return 0
1063 }
1064 newdirlist=
1065 
1066 [ -d $CODEMGR_WS ] || newdir $CODEMGR_WS || exit 1
1067 
1068 # since this script assumes the build is from full source, it nullifies
1069 # variables likely to have been set by a "ws" script; nullification
1070 # confines the search space for headers and libraries to the proto area
1071 # built from this immediate source.
1072 ENVLDLIBS1=
1073 ENVLDLIBS2=
1074 ENVLDLIBS3=
1075 ENVCPPFLAGS1=
1076 ENVCPPFLAGS2=
1077 ENVCPPFLAGS3=
1078 ENVCPPFLAGS4=
1079 PARENT_ROOT=
1080 
1081 export ENVLDLIBS3 ENVCPPFLAGS1 ENVCPPFLAGS2 ENVCPPFLAGS3 ENVCPPFLAGS4 \
1082         ENVLDLIBS1 ENVLDLIBS2 PARENT_ROOT
1083 
1084 PKGARCHIVE_ORIG=$PKGARCHIVE
1085 
1086 #
1087 # Juggle the logs and optionally send mail on completion.
1088 #
1089 
1090 function logshuffle {
1091         LLOG="$ATLOG/log.`date '+%F.%H:%M'`"
1092         if [ -f $LLOG -o -d $LLOG ]; then
1093                 LLOG=$LLOG.$$
1094         fi
1095         mkdir $LLOG
1096         export LLOG
1097 
1098         if [ "$build_ok" = "y" ]; then
1099                 mv $ATLOG/proto_list_${MACH} $LLOG
1100 
1101                 if [ -f $ATLOG/proto_list_tools_${MACH} ]; then
1102                         mv $ATLOG/proto_list_tools_${MACH} $LLOG
1103                 fi
1104 
1105                 if [ -f $TMPDIR/wsdiff.results ]; then
1106                         mv $TMPDIR/wsdiff.results $LLOG
1107                 fi
1108 
1109                 if [ -f $TMPDIR/wsdiff-nd.results ]; then
1110                         mv $TMPDIR/wsdiff-nd.results $LLOG
1111                 fi
1112         fi
1113 
1114         #
1115         # Now that we're about to send mail, it's time to check the noise
1116         # file.  In the event that an error occurs beyond this point, it will
1117         # be recorded in the nightly.log file, but nowhere else.  This would
1118         # include only errors that cause the copying of the noise log to fail
1119         # or the mail itself not to be sent.
1120         #
1121 
1122         exec >>$LOGFILE 2>&1
1123         if [ -s $build_noise_file ]; then
1124                 echo "\n==== Nightly build noise ====\n" |
1125                     tee -a $LOGFILE >>$mail_msg_file
1126                 cat $build_noise_file >>$LOGFILE
1127                 cat $build_noise_file >>$mail_msg_file
1128                 echo | tee -a $LOGFILE >>$mail_msg_file
1129         fi
1130         rm -f $build_noise_file
1131 
1132         case "$build_ok" in
1133                 y)
1134                         state=Completed
1135                         ;;
1136                 i)
1137                         state=Interrupted
1138                         ;;
1139                 *)
1140                         state=Failed
1141                         ;;
1142         esac
1143 
1144         if [[ $state != "Interrupted" && $build_extras_ok != "y" ]]; then
1145                 state=Failed
1146         fi
1147 
1148         NIGHTLY_STATUS=$state
1149         export NIGHTLY_STATUS
1150 
1151         run_hook POST_NIGHTLY $state
1152         run_hook SYS_POST_NIGHTLY $state
1153 
1154         #
1155         # mailx(1) sets From: based on the -r flag
1156         # if it is given.
1157         #
1158         mailx_r=
1159         if [[ -n "${MAILFROM}" ]]; then
1160                 mailx_r="-r ${MAILFROM}"
1161         fi
1162 
1163         cat $build_time_file $build_environ_file $mail_msg_file \
1164             > ${LLOG}/mail_msg
1165         if [ "$m_FLAG" = "y" ]; then
1166                 cat ${LLOG}/mail_msg | /usr/bin/mailx ${mailx_r} -s \
1167         "Nightly ${MACH} Build of `basename ${CODEMGR_WS}` ${state}." \
1168                         ${MAILTO}
1169         fi
1170 
1171         if [ "$u_FLAG" = "y" -a "$build_ok" = "y" ]; then
1172                 staffer cp ${LLOG}/mail_msg $PARENT_WS/usr/src/mail_msg-${MACH}
1173                 staffer cp $LOGFILE $PARENT_WS/usr/src/nightly-${MACH}.log
1174         fi
1175 
1176         mv $LOGFILE $LLOG
1177 }
1178 
1179 #
1180 #       Remove the locks and temporary files on any exit
1181 #
1182 function cleanup {
1183         logshuffle
1184 
1185         [ -z "$lockfile" ] || staffer rm -f $lockfile
1186         [ -z "$atloglockfile" ] || rm -f $atloglockfile
1187         [ -z "$ulockfile" ] || staffer rm -f $ulockfile
1188         [ -z "$Ulockfile" ] || rm -f $Ulockfile
1189 
1190         set -- $newdirlist
1191         while [ $# -gt 0 ]; do
1192                 ISUSER=$1 staffer rmdir $2
1193                 shift; shift
1194         done
1195         rm -rf $TMPDIR
1196 }
1197 
1198 function cleanup_signal {
1199         build_ok=i
1200         # this will trigger cleanup(), above.
1201         exit 1
1202 }
1203 
1204 trap cleanup 0
1205 trap cleanup_signal 1 2 3 15
1206 
1207 #
1208 # Generic lock file processing -- make sure that the lock file doesn't
1209 # exist.  If it does, it should name the build host and PID.  If it
1210 # doesn't, then make sure we can create it.  Clean up locks that are
1211 # known to be stale (assumes host name is unique among build systems
1212 # for the workspace).
1213 #
1214 function create_lock {
1215         lockf=$1
1216         lockvar=$2
1217 
1218         ldir=`dirname $lockf`
1219         [ -d $ldir ] || newdir $ldir || exit 1
1220         eval $lockvar=$lockf
1221 
1222         while ! staffer ln -s $hostname.$STAFFER.$$ $lockf 2> /dev/null; do
1223                 basews=`basename $CODEMGR_WS`
1224                 ls -l $lockf | nawk '{print $NF}' | IFS=. read host user pid
1225                 if [ "$host" != "$hostname" ]; then
1226                         echo "$MACH build of $basews apparently" \
1227                             "already started by $user on $host as $pid."
1228                         exit 1
1229                 elif kill -s 0 $pid 2>/dev/null; then
1230                         echo "$MACH build of $basews already started" \
1231                             "by $user as $pid."
1232                         exit 1
1233                 else
1234                         # stale lock; clear it out and try again
1235                         rm -f $lockf
1236                 fi
1237         done
1238 }
1239 
1240 #
1241 # Return the list of interesting proto areas, depending on the current
1242 # options.
1243 #
1244 function allprotos {
1245         typeset roots="$ROOT"
1246 
1247         if [[ "$F_FLAG" = n && "$MULTI_PROTO" = yes ]]; then
1248                 roots="$roots $ROOT-nd"
1249         fi
1250 
1251         echo $roots
1252 }
1253 
1254 # Ensure no other instance of this script is running on this host.
1255 # LOCKNAME can be set in <env_file>, and is by default, but is not
1256 # required due to the use of $ATLOG below.
1257 if [ -n "$LOCKNAME" ]; then
1258         create_lock /tmp/$LOCKNAME "lockfile"
1259 fi
1260 #
1261 # Create from one, two, or three other locks:
1262 #       $ATLOG/nightly.lock
1263 #               - protects against multiple builds in same workspace
1264 #       $PARENT_WS/usr/src/nightly.$MACH.lock
1265 #               - protects against multiple 'u' copy-backs
1266 #       $NIGHTLY_PARENT_ROOT/nightly.lock
1267 #               - protects against multiple 'U' copy-backs
1268 #
1269 # Overriding ISUSER to 1 causes the lock to be created as root if the
1270 # script is run as root.  The default is to create it as $STAFFER.
1271 ISUSER=1 create_lock $ATLOG/nightly.lock "atloglockfile"
1272 if [ "$u_FLAG" = "y" ]; then
1273         create_lock $PARENT_WS/usr/src/nightly.$MACH.lock "ulockfile"
1274 fi
1275 if [ "$U_FLAG" = "y" ]; then
1276         # NIGHTLY_PARENT_ROOT is written as root if script invoked as root.
1277         ISUSER=1 create_lock $NIGHTLY_PARENT_ROOT/nightly.lock "Ulockfile"
1278 fi
1279 
1280 # Locks have been taken, so we're doing a build and we're committed to
1281 # the directories we may have created so far.
1282 newdirlist=
1283 
1284 #
1285 # Create mail_msg_file
1286 #
1287 mail_msg_file="${TMPDIR}/mail_msg"
1288 touch $mail_msg_file
1289 build_time_file="${TMPDIR}/build_time"
1290 build_environ_file="${TMPDIR}/build_environ"
1291 touch $build_environ_file
1292 #
1293 #       Move old LOGFILE aside
1294 #       ATLOG directory already made by 'create_lock' above
1295 #
1296 if [ -f $LOGFILE ]; then
1297         mv -f $LOGFILE ${LOGFILE}-
1298 fi
1299 #
1300 #       Build OsNet source
1301 #
1302 START_DATE=`date`
1303 SECONDS=0
1304 echo "\n==== Nightly $maketype build started:   $START_DATE ====" \
1305     | tee -a $LOGFILE > $build_time_file
1306 
1307 echo "\nBuild project:  $build_project\nBuild taskid:   $build_taskid" | \
1308     tee -a $mail_msg_file >> $LOGFILE
1309 
1310 # make sure we log only to the nightly build file
1311 build_noise_file="${TMPDIR}/build_noise"
1312 exec </dev/null >$build_noise_file 2>&1
1313 
1314 run_hook SYS_PRE_NIGHTLY
1315 run_hook PRE_NIGHTLY
1316 
1317 echo "\n==== list of environment variables ====\n" >> $LOGFILE
1318 env >> $LOGFILE
1319 
1320 echo "\n==== Nightly argument issues ====\n" | tee -a $mail_msg_file >> $LOGFILE
1321 
1322 if [ "$N_FLAG" = "y" ]; then
1323         if [ "$p_FLAG" = "y" ]; then
1324                 cat <<EOF | tee -a $mail_msg_file >> $LOGFILE
1325 WARNING: the p option (create packages) is set, but so is the N option (do
1326          not run protocmp); this is dangerous; you should unset the N option
1327 EOF
1328         else
1329                 cat <<EOF | tee -a $mail_msg_file >> $LOGFILE
1330 Warning: the N option (do not run protocmp) is set; it probably shouldn't be
1331 EOF
1332         fi
1333         echo "" | tee -a $mail_msg_file >> $LOGFILE
1334 fi
1335 
1336 if [ "$D_FLAG" = "n" -a "$l_FLAG" = "y" ]; then
1337         #
1338         # In the past we just complained but went ahead with the lint
1339         # pass, even though the proto area was built non-DEBUG.  It's
1340         # unlikely that non-DEBUG headers will make a difference, but
1341         # rather than assuming it's a safe combination, force the user
1342         # to specify a DEBUG build.
1343         #
1344         echo "WARNING: DEBUG build not requested; disabling lint.\n" \
1345             | tee -a $mail_msg_file >> $LOGFILE
1346         l_FLAG=n
1347 fi
1348 
1349 if [ "$f_FLAG" = "y" ]; then
1350         if [ "$i_FLAG" = "y" ]; then
1351                 echo "WARNING: the -f flag cannot be used during incremental" \
1352                     "builds; ignoring -f\n" | tee -a $mail_msg_file >> $LOGFILE
1353                 f_FLAG=n
1354         fi
1355         if [ "${l_FLAG}${p_FLAG}" != "yy" ]; then
1356                 echo "WARNING: the -f flag requires -l, and -p;" \
1357                     "ignoring -f\n" | tee -a $mail_msg_file >> $LOGFILE
1358                 f_FLAG=n
1359         fi
1360 fi
1361 
1362 if [ "$w_FLAG" = "y" -a ! -d $ROOT ]; then
1363         echo "WARNING: -w specified, but $ROOT does not exist;" \
1364             "ignoring -w\n" | tee -a $mail_msg_file >> $LOGFILE
1365         w_FLAG=n
1366 fi
1367 
1368 if [ "$t_FLAG" = "n" ]; then
1369         #
1370         # We're not doing a tools build, so make sure elfsign(1) is
1371         # new enough to safely sign non-crypto binaries.  We test
1372         # debugging output from elfsign to detect the old version.
1373         #
1374         newelfsigntest=`SUNW_CRYPTO_DEBUG=stderr /usr/bin/elfsign verify \
1375             -e /usr/lib/security/pkcs11_softtoken.so.1 2>&1 \
1376             | egrep algorithmOID`
1377         if [ -z "$newelfsigntest" ]; then
1378                 echo "WARNING: /usr/bin/elfsign out of date;" \
1379                     "will only sign crypto modules\n" | \
1380                     tee -a $mail_msg_file >> $LOGFILE
1381                 export ELFSIGN_OBJECT=true
1382         elif [ "$VERIFY_ELFSIGN" = "y" ]; then
1383                 echo "WARNING: VERIFY_ELFSIGN=y requires" \
1384                     "the -t flag; ignoring VERIFY_ELFSIGN\n" | \
1385                     tee -a $mail_msg_file >> $LOGFILE
1386         fi
1387 fi
1388 
1389 case $MULTI_PROTO in
1390 yes|no) ;;
1391 *)
1392         echo "WARNING: MULTI_PROTO is \"$MULTI_PROTO\"; " \
1393             "should be \"yes\" or \"no\"." | tee -a $mail_msg_file >> $LOGFILE
1394         echo "Setting MULTI_PROTO to \"no\".\n" | \
1395             tee -a $mail_msg_file >> $LOGFILE
1396         export MULTI_PROTO=no
1397         ;;
1398 esac
1399 
1400 echo "\n==== Build version ====\n" | tee -a $mail_msg_file >> $LOGFILE
1401 echo $VERSION | tee -a $mail_msg_file >> $LOGFILE
1402 
1403 # Save the current proto area if we're comparing against the last build
1404 if [ "$w_FLAG" = "y" -a -d "$ROOT" ]; then
1405     if [ -d "$ROOT.prev" ]; then
1406         rm -rf $ROOT.prev
1407     fi
1408     mv $ROOT $ROOT.prev
1409 fi
1410 
1411 # Same for non-DEBUG proto area
1412 if [ "$w_FLAG" = "y" -a "$MULTI_PROTO" = yes -a -d "$ROOT-nd" ]; then
1413         if [ -d "$ROOT-nd.prev" ]; then
1414                 rm -rf $ROOT-nd.prev
1415         fi
1416         mv $ROOT-nd $ROOT-nd.prev
1417 fi
1418 
1419 #
1420 # Echo the SCM type of the parent workspace, this can't just be which_scm
1421 # as that does not know how to identify various network repositories.
1422 #
1423 function parent_wstype {
1424         typeset scm_type junk
1425 
1426         CODEMGR_WS="$BRINGOVER_WS" "$WHICH_SCM" 2>/dev/null \
1427             | read scm_type junk
1428         if [[ -z "$scm_type" || "$scm_type" == unknown ]]; then
1429                 # Probe BRINGOVER_WS to determine its type
1430                 if [[ $BRINGOVER_WS == ssh://* ]]; then
1431                         scm_type="mercurial"
1432                 elif [[ $BRINGOVER_WS == http://* ]] && \
1433                     wget -q -O- --save-headers "$BRINGOVER_WS/?cmd=heads" | \
1434                     egrep -s "application/mercurial" 2> /dev/null; then
1435                         scm_type="mercurial"
1436                 else
1437                         scm_type="none"
1438                 fi
1439         fi    
1440 
1441         # fold both unsupported and unrecognized results into "none"
1442         case "$scm_type" in
1443         mercurial)
1444                 ;;
1445         *)      scm_type=none
1446                 ;;
1447         esac
1448 
1449         echo $scm_type
1450 }
1451 
1452 # Echo the SCM types of $CODEMGR_WS and $BRINGOVER_WS
1453 function child_wstype {
1454         typeset scm_type junk
1455 
1456         # Probe CODEMGR_WS to determine its type
1457         if [[ -d $CODEMGR_WS ]]; then
1458                 $WHICH_SCM | read scm_type junk || exit 1
1459         fi
1460 
1461         case "$scm_type" in
1462         none|git|mercurial)
1463                 ;;
1464         *)      scm_type=none
1465                 ;;
1466         esac
1467 
1468         echo $scm_type
1469 }
1470 
1471 SCM_TYPE=$(child_wstype)
1472 
1473 #
1474 #       Decide whether to clobber
1475 #
1476 if [ "$i_FLAG" = "n" -a -d "$SRC" ]; then
1477         echo "\n==== Make clobber at `date` ====\n" >> $LOGFILE
1478 
1479         cd $SRC
1480         # remove old clobber file
1481         rm -f $SRC/clobber.out
1482         rm -f $SRC/clobber-${MACH}.out
1483 
1484         # Remove all .make.state* files, just in case we are restarting
1485         # the build after having interrupted a previous 'make clobber'.
1486         find . \( -name SCCS -o -name .hg -o -name .svn -o -name .git \
1487                 -o -name 'interfaces.*' \) -prune \
1488                 -o -name '.make.*' -print | xargs rm -f
1489 
1490         $MAKE -ek clobber 2>&1 | tee -a $SRC/clobber-${MACH}.out >> $LOGFILE
1491         echo "\n==== Make clobber ERRORS ====\n" >> $mail_msg_file
1492         grep "$MAKE:" $SRC/clobber-${MACH}.out |
1493                 egrep -v "Ignoring unknown host" | \
1494                 tee $TMPDIR/clobber_errs >> $mail_msg_file
1495 
1496         if [[ -s $TMPDIR/clobber_errs ]]; then
1497                 build_extras_ok=n
1498         fi
1499 
1500         if [[ "$t_FLAG" = "y" ]]; then
1501                 echo "\n==== Make tools clobber at `date` ====\n" >> $LOGFILE
1502                 cd ${TOOLS}
1503                 rm -f ${TOOLS}/clobber-${MACH}.out
1504                 $MAKE TOOLS_PROTO=$TOOLS_PROTO -ek clobber 2>&1 | \
1505                         tee -a ${TOOLS}/clobber-${MACH}.out >> $LOGFILE
1506                 echo "\n==== Make tools clobber ERRORS ====\n" \
1507                         >> $mail_msg_file
1508                 grep "$MAKE:" ${TOOLS}/clobber-${MACH}.out \
1509                         >> $mail_msg_file
1510                 if (( $? == 0 )); then
1511                         build_extras_ok=n
1512                 fi
1513                 rm -rf ${TOOLS_PROTO}
1514                 mkdir -p ${TOOLS_PROTO}
1515         fi
1516 
1517         typeset roots=$(allprotos)
1518         echo "\n\nClearing $roots" >> "$LOGFILE"
1519         rm -rf $roots
1520 
1521         # Get back to a clean workspace as much as possible to catch
1522         # problems that only occur on fresh workspaces.
1523         # Remove all .make.state* files, libraries, and .o's that may
1524         # have been omitted from clobber.  A couple of libraries are
1525         # under source code control, so leave them alone.
1526         # We should probably blow away temporary directories too.
1527         cd $SRC
1528         find $relsrcdirs \( -name SCCS -o -name .hg -o -name .svn \
1529             -o -name .git -o -name 'interfaces.*' \) -prune -o \
1530             \( -name '.make.*' -o -name 'lib*.a' -o -name 'lib*.so*' -o \
1531                -name '*.o' \) -print | \
1532             grep -v 'tools/ctf/dwarf/.*/libdwarf' | xargs rm -f
1533 else
1534         echo "\n==== No clobber at `date` ====\n" >> $LOGFILE
1535 fi
1536 
1537 type bringover_mercurial > /dev/null 2>&1 || function bringover_mercurial {
1538         typeset -x PATH=$PATH
1539 
1540         # If the repository doesn't exist yet, then we want to populate it.
1541         if [[ ! -d $CODEMGR_WS/.hg ]]; then
1542                 staffer hg init $CODEMGR_WS
1543                 staffer echo "[paths]" > $CODEMGR_WS/.hg/hgrc
1544                 staffer echo "default=$BRINGOVER_WS" >> $CODEMGR_WS/.hg/hgrc
1545                 touch $TMPDIR/new_repository
1546         fi
1547 
1548         typeset -x HGMERGE="/bin/false"
1549 
1550         #
1551         # If the user has changes, regardless of whether those changes are
1552         # committed, and regardless of whether those changes conflict, then
1553         # we'll attempt to merge them either implicitly (uncommitted) or
1554         # explicitly (committed).
1555         #
1556         # These are the messages we'll use to help clarify mercurial output
1557         # in those cases.
1558         #
1559         typeset mergefailmsg="\
1560 ***\n\
1561 *** nightly was unable to automatically merge your changes.  You should\n\
1562 *** redo the full merge manually, following the steps outlined by mercurial\n\
1563 *** above, then restart nightly.\n\
1564 ***\n"
1565         typeset mergepassmsg="\
1566 ***\n\
1567 *** nightly successfully merged your changes.  This means that your working\n\
1568 *** directory has been updated, but those changes are not yet committed.\n\
1569 *** After nightly completes, you should validate the results of the merge,\n\
1570 *** then use hg commit manually.\n\
1571 ***\n"
1572 
1573         #
1574         # For each repository in turn:
1575         #
1576         # 1. Do the pull.  If this fails, dump the output and bail out.
1577         #
1578         # 2. If the pull resulted in an extra head, do an explicit merge.
1579         #    If this fails, dump the output and bail out.
1580         #
1581         # Because we can't rely on Mercurial to exit with a failure code
1582         # when a merge fails (Mercurial issue #186), we must grep the
1583         # output of pull/merge to check for attempted and/or failed merges.
1584         #
1585         # 3. If a merge failed, set the message and fail the bringover.
1586         #
1587         # 4. Otherwise, if a merge succeeded, set the message
1588         #
1589         # 5. Dump the output, and any message from step 3 or 4.
1590         #
1591 
1592         typeset HG_SOURCE=$BRINGOVER_WS
1593         if [ ! -f $TMPDIR/new_repository ]; then
1594                 HG_SOURCE=$TMPDIR/open_bundle.hg
1595                 staffer hg --cwd $CODEMGR_WS incoming --bundle $HG_SOURCE \
1596                     -v $BRINGOVER_WS > $TMPDIR/incoming_open.out
1597 
1598                 #
1599                 # If there are no incoming changesets, then incoming will
1600                 # fail, and there will be no bundle file.  Reset the source,
1601                 # to allow the remaining logic to complete with no false
1602                 # negatives.  (Unlike incoming, pull will return success
1603                 # for the no-change case.)
1604                 #
1605                 if (( $? != 0 )); then
1606                         HG_SOURCE=$BRINGOVER_WS
1607                 fi
1608         fi
1609 
1610         staffer hg --cwd $CODEMGR_WS pull -u $HG_SOURCE \
1611             > $TMPDIR/pull_open.out 2>&1
1612         if (( $? != 0 )); then
1613                 printf "%s: pull failed as follows:\n\n" "$CODEMGR_WS"
1614                 cat $TMPDIR/pull_open.out
1615                 if grep "^merging.*failed" $TMPDIR/pull_open.out > /dev/null 2>&1; then
1616                         printf "$mergefailmsg"
1617                 fi
1618                 touch $TMPDIR/bringover_failed
1619                 return
1620         fi
1621 
1622         if grep "not updating" $TMPDIR/pull_open.out > /dev/null 2>&1; then
1623                 staffer hg --cwd $CODEMGR_WS merge \
1624                     >> $TMPDIR/pull_open.out 2>&1
1625                 if (( $? != 0 )); then
1626                         printf "%s: merge failed as follows:\n\n" \
1627                             "$CODEMGR_WS"
1628                         cat $TMPDIR/pull_open.out
1629                         if grep "^merging.*failed" $TMPDIR/pull_open.out \
1630                             > /dev/null 2>&1; then
1631                                 printf "$mergefailmsg"
1632                         fi
1633                         touch $TMPDIR/bringover_failed
1634                         return
1635                 fi
1636         fi
1637 
1638         printf "updated %s with the following results:\n" "$CODEMGR_WS"
1639         cat $TMPDIR/pull_open.out
1640         if grep "^merging" $TMPDIR/pull_open.out >/dev/null 2>&1; then
1641                 printf "$mergepassmsg"
1642         fi
1643         printf "\n"
1644 
1645         #
1646         # Per-changeset output is neither useful nor manageable for a
1647         # newly-created repository.
1648         #
1649         if [ -f $TMPDIR/new_repository ]; then
1650                 return
1651         fi
1652 
1653         printf "\nadded the following changesets to open repository:\n"
1654         cat $TMPDIR/incoming_open.out
1655 }
1656 
1657 type bringover_none > /dev/null 2>&1 || function bringover_none {
1658         echo "Couldn't figure out what kind of SCM to use for $BRINGOVER_WS."
1659         touch $TMPDIR/bringover_failed
1660 }
1661 
1662 #
1663 #       Decide whether to bringover to the codemgr workspace
1664 #
1665 if [ "$n_FLAG" = "n" ]; then
1666         PARENT_SCM_TYPE=$(parent_wstype)
1667 
1668         if [[ $SCM_TYPE != none && $SCM_TYPE != $PARENT_SCM_TYPE ]]; then
1669                 echo "cannot bringover from $PARENT_SCM_TYPE to $SCM_TYPE, " \
1670                     "quitting at `date`." | tee -a $mail_msg_file >> $LOGFILE
1671                 exit 1
1672         fi
1673 
1674         run_hook PRE_BRINGOVER
1675 
1676         echo "\n==== bringover to $CODEMGR_WS at `date` ====\n" >> $LOGFILE
1677         echo "\n==== BRINGOVER LOG ====\n" >> $mail_msg_file
1678 
1679         eval "bringover_${PARENT_SCM_TYPE}" 2>&1 |
1680                 tee -a $mail_msg_file >> $LOGFILE
1681 
1682         if [ -f $TMPDIR/bringover_failed ]; then
1683                 rm -f $TMPDIR/bringover_failed
1684                 build_ok=n
1685                 echo "trouble with bringover, quitting at `date`." |
1686                         tee -a $mail_msg_file >> $LOGFILE
1687                 exit 1
1688         fi
1689 
1690         #
1691         # It's possible that we used the bringover above to create
1692         # $CODEMGR_WS.  If so, then SCM_TYPE was previously "none,"
1693         # but should now be the same as $BRINGOVER_WS.
1694         #
1695         [[ $SCM_TYPE = none ]] && SCM_TYPE=$PARENT_SCM_TYPE
1696 
1697         run_hook POST_BRINGOVER
1698 
1699         check_closed_bins
1700 
1701 else
1702         echo "\n==== No bringover to $CODEMGR_WS ====\n" >> $LOGFILE
1703 fi
1704 
1705 # Safeguards
1706 [[ -v CODEMGR_WS ]] || fatal_error "Error: Variable CODEMGR_WS not set."
1707 [[ -d "${CODEMGR_WS}" ]] || fatal_error "Error: ${CODEMGR_WS} is not a directory."
1708 [[ -f "${CODEMGR_WS}/usr/src/Makefile" ]] || fatal_error "Error: ${CODEMGR_WS}/usr/src/Makefile not found."
1709 
1710 echo "\n==== Build environment ====\n" | tee -a $build_environ_file >> $LOGFILE
1711 
1712 # System
1713 whence uname | tee -a $build_environ_file >> $LOGFILE
1714 uname -a 2>&1 | tee -a $build_environ_file >> $LOGFILE
1715 echo | tee -a $build_environ_file >> $LOGFILE
1716 
1717 # make
1718 whence $MAKE | tee -a $build_environ_file >> $LOGFILE
1719 $MAKE -v | tee -a $build_environ_file >> $LOGFILE
1720 echo "number of concurrent jobs = $DMAKE_MAX_JOBS" |
1721     tee -a $build_environ_file >> $LOGFILE
1722 
1723 #
1724 # Report the compiler versions.
1725 #
1726 
1727 if [[ ! -f $SRC/Makefile ]]; then
1728         build_ok=n
1729         echo "\nUnable to find \"Makefile\" in $SRC." | \
1730             tee -a $build_environ_file >> $LOGFILE
1731         exit 1
1732 fi
1733 
1734 ( cd $SRC
1735   for target in cc-version cc64-version java-version; do
1736         echo
1737         #
1738         # Put statefile somewhere we know we can write to rather than trip
1739         # over a read-only $srcroot.
1740         #
1741         rm -f $TMPDIR/make-state
1742         export SRC
1743         if $MAKE -K $TMPDIR/make-state -e $target 2>/dev/null; then
1744                 continue
1745         fi
1746         touch $TMPDIR/nocompiler
1747   done
1748   echo
1749 ) | tee -a $build_environ_file >> $LOGFILE
1750 
1751 if [ -f $TMPDIR/nocompiler ]; then
1752         rm -f $TMPDIR/nocompiler
1753         build_ok=n
1754         echo "Aborting due to missing compiler." |
1755                 tee -a $build_environ_file >> $LOGFILE
1756         exit 1
1757 fi
1758 
1759 # as
1760 whence as | tee -a $build_environ_file >> $LOGFILE
1761 as -V 2>&1 | head -1 | tee -a $build_environ_file >> $LOGFILE
1762 echo | tee -a $build_environ_file >> $LOGFILE
1763 
1764 # Check that we're running a capable link-editor
1765 whence ld | tee -a $build_environ_file >> $LOGFILE
1766 LDVER=`ld -V 2>&1`
1767 echo $LDVER | tee -a $build_environ_file >> $LOGFILE
1768 LDVER=`echo $LDVER | sed -e "s/.*-1\.\([0-9]*\).*/\1/"`
1769 if [ `expr $LDVER \< 422` -eq 1 ]; then
1770         echo "The link-editor needs to be at version 422 or higher to build" | \
1771             tee -a $build_environ_file >> $LOGFILE
1772         echo "the latest stuff.  Hope your build works." | \
1773             tee -a $build_environ_file >> $LOGFILE
1774 fi
1775 
1776 #
1777 # Build and use the workspace's tools if requested
1778 #
1779 if [[ "$t_FLAG" = "y" ]]; then
1780         set_non_debug_build_flags
1781 
1782         build_tools ${TOOLS_PROTO}
1783         if (( $? != 0 )); then
1784                 build_ok=n
1785         else
1786                 use_tools $TOOLS_PROTO
1787         fi
1788 fi
1789 
1790 # timestamp the start of the normal build; the findunref tool uses it.
1791 touch $SRC/.build.tstamp
1792 
1793 normal_build
1794 
1795 ORIG_SRC=$SRC
1796 BINARCHIVE=${CODEMGR_WS}/bin-${MACH}.cpio.Z
1797 
1798 
1799 #
1800 # There are several checks that need to look at the proto area, but
1801 # they only need to look at one, and they don't care whether it's
1802 # DEBUG or non-DEBUG.
1803 #
1804 if [[ "$MULTI_PROTO" = yes && "$D_FLAG" = n ]]; then
1805         checkroot=$ROOT-nd
1806 else
1807         checkroot=$ROOT
1808 fi
1809 
1810 if [ "$build_ok" = "y" ]; then
1811         echo "\n==== Creating protolist system file at `date` ====" \
1812                 >> $LOGFILE
1813         protolist $checkroot > $ATLOG/proto_list_${MACH}
1814         echo "==== protolist system file created at `date` ====\n" \
1815                 >> $LOGFILE
1816 
1817         if [ "$N_FLAG" != "y" ]; then
1818 
1819                 E1=
1820                 f1=
1821                 for f in $f1; do
1822                         if [ -f "$f" ]; then
1823                                 E1="$E1 -e $f"
1824                         fi
1825                 done
1826 
1827                 E2=
1828                 f2=
1829                 if [ -d "$SRC/pkg" ]; then
1830                         f2="$f2 exceptions/packaging"
1831                 fi
1832 
1833                 for f in $f2; do
1834                         if [ -f "$f" ]; then
1835                                 E2="$E2 -e $f"
1836                         fi
1837                 done
1838         fi
1839 
1840         if [ "$N_FLAG" != "y" -a -d $SRC/pkg ]; then
1841                 echo "\n==== Validating manifests against proto area ====\n" \
1842                     >> $mail_msg_file
1843                 ( cd $SRC/pkg ; $MAKE -e protocmp ROOT="$checkroot" ) | \
1844                     tee $TMPDIR/protocmp_noise >> $mail_msg_file
1845                 if [[ -s $TMPDIR/protocmp_noise ]]; then
1846                         build_extras_ok=n
1847                 fi
1848         fi
1849 
1850         if [ "$N_FLAG" != "y" -a -f "$REF_PROTO_LIST" ]; then
1851                 echo "\n==== Impact on proto area ====\n" >> $mail_msg_file
1852                 if [ -n "$E2" ]; then
1853                         ELIST=$E2
1854                 else
1855                         ELIST=$E1
1856                 fi
1857                 $PROTOCMPTERSE \
1858                         "Files in yesterday's proto area, but not today's:" \
1859                         "Files in today's proto area, but not yesterday's:" \
1860                         "Files that changed between yesterday and today:" \
1861                         ${ELIST} \
1862                         -d $REF_PROTO_LIST \
1863                         $ATLOG/proto_list_${MACH} \
1864                         >> $mail_msg_file
1865         fi
1866 fi
1867 
1868 if [[ "$u_FLAG" == "y" && "$build_ok" == "y" && \
1869     "$build_extras_ok" == "y" ]]; then
1870         staffer cp $ATLOG/proto_list_${MACH} \
1871                 $PARENT_WS/usr/src/proto_list_${MACH}
1872 fi
1873 
1874 # Update parent proto area if necessary. This is done now
1875 # so that the proto area has either DEBUG or non-DEBUG kernels.
1876 # Note that this clears out the lock file, so we can dispense with
1877 # the variable now.
1878 if [ "$U_FLAG" = "y" -a "$build_ok" = "y" ]; then
1879         echo "\n==== Copying proto area to $NIGHTLY_PARENT_ROOT ====\n" | \
1880             tee -a $LOGFILE >> $mail_msg_file
1881         rm -rf $NIGHTLY_PARENT_ROOT/*
1882         unset Ulockfile
1883         mkdir -p $NIGHTLY_PARENT_ROOT
1884         if [[ "$MULTI_PROTO" = no || "$D_FLAG" = y ]]; then
1885                 ( cd $ROOT; tar cf - . |
1886                     ( cd $NIGHTLY_PARENT_ROOT;  umask 0; tar xpf - ) ) 2>&1 |
1887                     tee -a $mail_msg_file >> $LOGFILE
1888         fi
1889         if [[ "$MULTI_PROTO" = yes && "$F_FLAG" = n ]]; then
1890                 rm -rf $NIGHTLY_PARENT_ROOT-nd/*
1891                 mkdir -p $NIGHTLY_PARENT_ROOT-nd
1892                 cd $ROOT-nd
1893                 ( tar cf - . |
1894                     ( cd $NIGHTLY_PARENT_ROOT-nd; umask 0; tar xpf - ) ) 2>&1 |
1895                     tee -a $mail_msg_file >> $LOGFILE
1896         fi
1897         if [ -n "${NIGHTLY_PARENT_TOOLS_ROOT}" ]; then
1898                 echo "\n==== Copying tools proto area to $NIGHTLY_PARENT_TOOLS_ROOT ====\n" | \
1899                     tee -a $LOGFILE >> $mail_msg_file
1900                 rm -rf $NIGHTLY_PARENT_TOOLS_ROOT/*
1901                 mkdir -p $NIGHTLY_PARENT_TOOLS_ROOT
1902                 if [[ "$MULTI_PROTO" = no || "$D_FLAG" = y ]]; then
1903                         ( cd $TOOLS_PROTO; tar cf - . |
1904                             ( cd $NIGHTLY_PARENT_TOOLS_ROOT; 
1905                             umask 0; tar xpf - ) ) 2>&1 |
1906                             tee -a $mail_msg_file >> $LOGFILE
1907                 fi
1908         fi
1909 fi
1910 
1911 #
1912 # ELF verification: ABI (-A) and runtime (-r) checks
1913 #
1914 if [[ ($build_ok = y) && (($A_FLAG = y) || ($r_FLAG = y)) ]]; then
1915         # Directory ELF-data.$MACH holds the files produced by these tests.
1916         elf_ddir=$SRC/ELF-data.$MACH
1917 
1918         # If there is a previous ELF-data backup directory, remove it. Then,
1919         # rotate current ELF-data directory into its place and create a new
1920         # empty directory
1921         rm -rf $elf_ddir.ref
1922         if [[ -d $elf_ddir ]]; then
1923                 mv $elf_ddir $elf_ddir.ref
1924         fi
1925         mkdir -p $elf_ddir
1926 
1927         # Call find_elf to produce a list of the ELF objects in the proto area.
1928         # This list is passed to check_rtime and interface_check, preventing
1929         # them from separately calling find_elf to do the same work twice.
1930         find_elf -fr $checkroot > $elf_ddir/object_list
1931 
1932         if [[ $A_FLAG = y ]]; then
1933                 echo "\n==== Check versioning and ABI information ====\n"  | \
1934                     tee -a $LOGFILE >> $mail_msg_file
1935 
1936                 # Produce interface description for the proto. Report errors.
1937                 interface_check -o -w $elf_ddir -f object_list \
1938                         -i interface -E interface.err
1939                 if [[ -s $elf_ddir/interface.err ]]; then
1940                         tee -a $LOGFILE < $elf_ddir/interface.err \
1941                             >> $mail_msg_file
1942                         build_extras_ok=n
1943                 fi
1944 
1945                 # If ELF_DATA_BASELINE_DIR is defined, compare the new interface
1946                 # description file to that from the baseline gate. Issue a
1947                 # warning if the baseline is not present, and keep going.
1948                 if [[ "$ELF_DATA_BASELINE_DIR" != '' ]]; then
1949                         base_ifile="$ELF_DATA_BASELINE_DIR/interface"
1950 
1951                         echo "\n==== Compare versioning and ABI information" \
1952                             "to baseline ====\n"  | \
1953                             tee -a $LOGFILE >> $mail_msg_file
1954                         echo "Baseline:  $base_ifile\n" >> $LOGFILE
1955 
1956                         if [[ -f $base_ifile ]]; then
1957                                 interface_cmp -d -o $base_ifile \
1958                                     $elf_ddir/interface > $elf_ddir/interface.cmp
1959                                 if [[ -s $elf_ddir/interface.cmp ]]; then
1960                                         echo | tee -a $LOGFILE >> $mail_msg_file
1961                                         tee -a $LOGFILE < \
1962                                             $elf_ddir/interface.cmp \
1963                                             >> $mail_msg_file
1964                                         build_extras_ok=n
1965                                 fi
1966                         else
1967                                 echo "baseline not available. comparison" \
1968                                     "skipped" | \
1969                                     tee -a $LOGFILE >> $mail_msg_file
1970                         fi
1971 
1972                 fi
1973         fi
1974 
1975         if [[ $r_FLAG = y ]]; then
1976                 echo "\n==== Check ELF runtime attributes ====\n" | \
1977                     tee -a $LOGFILE >> $mail_msg_file
1978 
1979                 # If we're doing a DEBUG build the proto area will be left
1980                 # with debuggable objects, thus don't assert -s.
1981                 if [[ $D_FLAG = y ]]; then
1982                         rtime_sflag=""
1983                 else
1984                         rtime_sflag="-s"
1985                 fi
1986                 check_rtime -i -m -v $rtime_sflag -o -w $elf_ddir \
1987                         -D object_list  -f object_list -E runtime.err \
1988                         -I runtime.attr.raw
1989                 if (( $? != 0 )); then
1990                         build_extras_ok=n
1991                 fi
1992 
1993                 # check_rtime -I output needs to be sorted in order to 
1994                 # compare it to that from previous builds.
1995                 sort $elf_ddir/runtime.attr.raw > $elf_ddir/runtime.attr
1996                 rm $elf_ddir/runtime.attr.raw
1997 
1998                 # Report errors
1999                 if [[ -s $elf_ddir/runtime.err ]]; then
2000                         tee -a $LOGFILE < $elf_ddir/runtime.err \
2001                                 >> $mail_msg_file
2002                         build_extras_ok=n
2003                 fi
2004 
2005                 # If there is an ELF-data directory from a previous build,
2006                 # then diff the attr files. These files contain information
2007                 # about dependencies, versioning, and runpaths. There is some
2008                 # overlap with the ABI checking done above, but this also
2009                 # flushes out non-ABI interface differences along with the
2010                 # other information.
2011                 echo "\n==== Diff ELF runtime attributes" \
2012                     "(since last build) ====\n" | \
2013                     tee -a $LOGFILE >> $mail_msg_file >> $mail_msg_file
2014 
2015                 if [[ -f $elf_ddir.ref/runtime.attr ]]; then
2016                         diff $elf_ddir.ref/runtime.attr \
2017                                 $elf_ddir/runtime.attr \
2018                                 >> $mail_msg_file
2019                 fi
2020         fi
2021 
2022         # If -u set, copy contents of ELF-data.$MACH to the parent workspace.
2023         if [[ "$u_FLAG" = "y" ]]; then
2024                 p_elf_ddir=$PARENT_WS/usr/src/ELF-data.$MACH
2025 
2026                 # If parent lacks the ELF-data.$MACH directory, create it
2027                 if [[ ! -d $p_elf_ddir ]]; then
2028                         staffer mkdir -p $p_elf_ddir
2029                 fi
2030 
2031                 # These files are used asynchronously by other builds for ABI
2032                 # verification, as above for the -A option. As such, we require
2033                 # the file replacement to be atomic. Copy the data to a temp
2034                 # file in the same filesystem and then rename into place. 
2035                 (
2036                         cd $elf_ddir
2037                         for elf_dfile in *; do
2038                                 staffer cp $elf_dfile \
2039                                     ${p_elf_ddir}/${elf_dfile}.new
2040                                 staffer mv -f ${p_elf_ddir}/${elf_dfile}.new \
2041                                     ${p_elf_ddir}/${elf_dfile}
2042                         done
2043                 )
2044         fi
2045 fi
2046 
2047 # DEBUG lint of kernel begins
2048 
2049 if [ "$i_CMD_LINE_FLAG" = "n" -a "$l_FLAG" = "y" ]; then
2050         if [ "$LINTDIRS" = "" ]; then
2051                 # LINTDIRS="$SRC/uts y $SRC/stand y $SRC/psm y"
2052                 LINTDIRS="$SRC y"
2053         fi
2054         set $LINTDIRS
2055         while [ $# -gt 0 ]; do
2056                 dolint $1 $2; shift; shift
2057         done
2058 else
2059         echo "\n==== No '$MAKE lint' ====\n" >> $LOGFILE
2060 fi
2061 
2062 # "make check" begins
2063 
2064 if [ "$i_CMD_LINE_FLAG" = "n" -a "$C_FLAG" = "y" ]; then
2065         # remove old check.out
2066         rm -f $SRC/check.out
2067 
2068         rm -f $SRC/check-${MACH}.out
2069         cd $SRC
2070         $MAKE -ek check ROOT="$checkroot" 2>&1 | tee -a $SRC/check-${MACH}.out \
2071             >> $LOGFILE
2072         echo "\n==== cstyle/hdrchk errors ====\n" >> $mail_msg_file
2073 
2074         grep ":" $SRC/check-${MACH}.out |
2075                 egrep -v "Ignoring unknown host" | \
2076                 sort | uniq | tee $TMPDIR/check_errors >> $mail_msg_file
2077 
2078         if [[ -s $TMPDIR/check_errors ]]; then
2079                 build_extras_ok=n
2080         fi
2081 else
2082         echo "\n==== No '$MAKE check' ====\n" >> $LOGFILE
2083 fi
2084 
2085 echo "\n==== Find core files ====\n" | \
2086     tee -a $LOGFILE >> $mail_msg_file
2087 
2088 find $abssrcdirs -name core -a -type f -exec file {} \; | \
2089         tee -a $LOGFILE >> $mail_msg_file
2090 
2091 if [ "$f_FLAG" = "y" -a "$build_ok" = "y" ]; then
2092         echo "\n==== Diff unreferenced files (since last build) ====\n" \
2093             | tee -a $LOGFILE >>$mail_msg_file
2094         rm -f $SRC/unref-${MACH}.ref
2095         if [ -f $SRC/unref-${MACH}.out ]; then
2096                 mv $SRC/unref-${MACH}.out $SRC/unref-${MACH}.ref
2097         fi
2098 
2099         findunref -S $SCM_TYPE -t $SRC/.build.tstamp -s usr $CODEMGR_WS \
2100             ${TOOLS}/findunref/exception_list 2>> $mail_msg_file | \
2101             sort > $SRC/unref-${MACH}.out
2102 
2103         if [ ! -f $SRC/unref-${MACH}.ref ]; then
2104                 cp $SRC/unref-${MACH}.out $SRC/unref-${MACH}.ref
2105         fi
2106 
2107         diff $SRC/unref-${MACH}.ref $SRC/unref-${MACH}.out >>$mail_msg_file
2108 fi
2109 
2110 # Verify that the usual lists of files, such as exception lists,
2111 # contain only valid references to files.  If the build has failed,
2112 # then don't check the proto area.
2113 CHECK_PATHS=${CHECK_PATHS:-y}
2114 if [ "$CHECK_PATHS" = y -a "$N_FLAG" != y ]; then
2115         echo "\n==== Check lists of files ====\n" | tee -a $LOGFILE \
2116                 >>$mail_msg_file
2117         arg=-b
2118         [ "$build_ok" = y ] && arg=
2119         checkpaths $arg $checkroot > $SRC/check-paths.out 2>&1
2120         if [[ -s $SRC/check-paths.out ]]; then
2121                 tee -a $LOGFILE < $SRC/check-paths.out >> $mail_msg_file
2122                 build_extras_ok=n
2123         fi
2124 fi
2125 
2126 if [ "$M_FLAG" != "y" -a "$build_ok" = y ]; then
2127         echo "\n==== Impact on file permissions ====\n" \
2128                 >> $mail_msg_file
2129 
2130         abspkg=
2131         for d in $abssrcdirs; do
2132                 if [ -d "$d/pkg" ]; then
2133                         abspkg="$abspkg $d"
2134                 fi
2135         done
2136 
2137         if [ -n "$abspkg" ]; then
2138                 for d in "$abspkg"; do
2139                         ( cd $d/pkg ; $MAKE -e pmodes ) >> $mail_msg_file
2140                 done
2141         fi
2142 fi
2143 
2144 if [ "$w_FLAG" = "y" -a "$build_ok" = "y" ]; then
2145         if [[ "$MULTI_PROTO" = no || "$D_FLAG" = y ]]; then
2146                 do_wsdiff DEBUG $ROOT.prev $ROOT
2147         fi
2148 
2149         if [[ "$MULTI_PROTO" = yes && "$F_FLAG" = n ]]; then
2150                 do_wsdiff non-DEBUG $ROOT-nd.prev $ROOT-nd
2151         fi
2152 fi
2153 
2154 END_DATE=`date`
2155 echo "==== Nightly $maketype build completed: $END_DATE ====" | \
2156     tee -a $LOGFILE >> $build_time_file
2157 
2158 typeset -i10 hours
2159 typeset -Z2 minutes
2160 typeset -Z2 seconds
2161 
2162 elapsed_time=$SECONDS
2163 ((hours = elapsed_time / 3600 ))
2164 ((minutes = elapsed_time / 60  % 60))
2165 ((seconds = elapsed_time % 60))
2166 
2167 echo "\n==== Total build time ====" | \
2168     tee -a $LOGFILE >> $build_time_file
2169 echo "\nreal    ${hours}:${minutes}:${seconds}" | \
2170     tee -a $LOGFILE >> $build_time_file
2171 
2172 if [ "$u_FLAG" = "y" -a "$f_FLAG" = "y" -a "$build_ok" = "y" ]; then
2173         staffer cp ${SRC}/unref-${MACH}.out $PARENT_WS/usr/src/
2174 
2175         #
2176         # Produce a master list of unreferenced files -- ideally, we'd
2177         # generate the master just once after all of the nightlies
2178         # have finished, but there's no simple way to know when that
2179         # will be.  Instead, we assume that we're the last nightly to
2180         # finish and merge all of the unref-${MACH}.out files in
2181         # $PARENT_WS/usr/src/.  If we are in fact the final ${MACH} to
2182         # finish, then this file will be the authoritative master
2183         # list.  Otherwise, another ${MACH}'s nightly will eventually
2184         # overwrite ours with its own master, but in the meantime our
2185         # temporary "master" will be no worse than any older master
2186         # which was already on the parent.
2187         #
2188 
2189         set -- $PARENT_WS/usr/src/unref-*.out
2190         cp "$1" ${TMPDIR}/unref.merge
2191         shift
2192 
2193         for unreffile; do
2194                 comm -12 ${TMPDIR}/unref.merge "$unreffile" > ${TMPDIR}/unref.$$
2195                 mv ${TMPDIR}/unref.$$ ${TMPDIR}/unref.merge
2196         done
2197 
2198         staffer cp ${TMPDIR}/unref.merge $PARENT_WS/usr/src/unrefmaster.out
2199 fi
2200 
2201 #
2202 # All done save for the sweeping up.
2203 # (whichever exit we hit here will trigger the "cleanup" trap which
2204 # optionally sends mail on completion).
2205 #
2206 if [[ "$build_ok" == "y" ]]; then
2207         if [[ "$W_FLAG" == "y" || "$build_extras_ok" == "y" ]]; then
2208                 exit 0
2209         fi
2210 fi
2211 
2212 exit 1