uboot/MAKEALL
<<
>>
Prefs
   1#!/bin/bash
   2# Tool mainly for U-Boot Quality Assurance: build one or more board
   3# configurations with minimal verbosity, showing only warnings and
   4# errors.
   5
   6usage()
   7{
   8        # if exiting with 0, write to stdout, else write to stderr
   9        local ret=${1:-0}
  10        [ "${ret}" -eq 1 ] && exec 1>&2
  11        cat <<-EOF
  12        Usage: MAKEALL [options] [--] [boards-to-build]
  13
  14        Options:
  15          -a ARCH,   --arch ARCH       Build all boards with arch ARCH
  16          -c CPU,    --cpu CPU         Build all boards with cpu CPU
  17          -v VENDOR, --vendor VENDOR   Build all boards with vendor VENDOR
  18          -s SOC,    --soc SOC         Build all boards with soc SOC
  19          -l,        --list            List all targets to be built
  20          -m,        --maintainers     List all targets and maintainer email
  21          -M,        --mails           List all targets and all affilated emails
  22          -C,        --check           Enable build checking
  23          -n,        --continue        Continue (skip boards already built)
  24          -r,        --rebuild-errors  Rebuild any boards that errored
  25          -h,        --help            This help output
  26
  27        Selections by these options are logically ANDed; if the same option
  28        is used repeatedly, such selections are ORed.  So "-v FOO -v BAR"
  29        will select all configurations where the vendor is either FOO or
  30        BAR.  Any additional arguments specified on the command line are
  31        always build additionally.  See the boards.cfg file for more info.
  32
  33        If no boards are specified, then the default is "powerpc".
  34
  35        Environment variables:
  36          BUILD_NCPUS      number of parallel make jobs (default: auto)
  37          CROSS_COMPILE    cross-compiler toolchain prefix (default: "")
  38          CROSS_COMPILE_<ARCH> cross-compiler toolchain prefix for
  39                           architecture "ARCH".  Substitute "ARCH" for any
  40                           supported architecture (default: "")
  41          MAKEALL_LOGDIR   output all logs to here (default: ./LOG/)
  42          BUILD_DIR        output build directory (default: ./)
  43          BUILD_NBUILDS    number of parallel targets (default: 1)
  44
  45        Examples:
  46          - build all Power Architecture boards:
  47              MAKEALL -a powerpc
  48              MAKEALL --arch powerpc
  49              MAKEALL powerpc
  50          - build all PowerPC boards manufactured by vendor "esd":
  51              MAKEALL -a powerpc -v esd
  52          - build all PowerPC boards manufactured either by "keymile" or "siemens":
  53              MAKEALL -a powerpc -v keymile -v siemens
  54          - build all Freescale boards with MPC83xx CPUs, plus all 4xx boards:
  55              MAKEALL -c mpc83xx -v freescale 4xx
  56        EOF
  57        exit ${ret}
  58}
  59
  60SHORT_OPTS="ha:c:v:s:lmMCnr"
  61LONG_OPTS="help,arch:,cpu:,vendor:,soc:,list,maintainers,mails,check,continue,rebuild-errors"
  62
  63# Option processing based on util-linux-2.13/getopt-parse.bash
  64
  65# Note that we use `"$@"' to let each command-line parameter expand to a
  66# separate word. The quotes around `$@' are essential!
  67# We need TEMP as the `eval set --' would nuke the return value of
  68# getopt.
  69TEMP=`getopt -o ${SHORT_OPTS} --long ${LONG_OPTS} \
  70     -n 'MAKEALL' -- "$@"`
  71
  72[ $? != 0 ] && usage 1
  73
  74# Note the quotes around `$TEMP': they are essential!
  75eval set -- "$TEMP"
  76
  77SELECTED=''
  78ONLY_LIST=''
  79PRINT_MAINTS=''
  80MAINTAINERS_ONLY=''
  81CONTINUE=''
  82REBUILD_ERRORS=''
  83
  84while true ; do
  85        case "$1" in
  86        -a|--arch)
  87                # echo "Option ARCH: argument \`$2'"
  88                if [ "$opt_a" ] ; then
  89                        opt_a="${opt_a%)} || \$2 == \"$2\")"
  90                else
  91                        opt_a="(\$2 == \"$2\")"
  92                fi
  93                SELECTED='y'
  94                shift 2 ;;
  95        -c|--cpu)
  96                # echo "Option CPU: argument \`$2'"
  97                if [ "$opt_c" ] ; then
  98                        opt_c="${opt_c%)} || \$3 == \"$2\" || \$3 ~ /$2:/)"
  99                else
 100                        opt_c="(\$3 == \"$2\" || \$3 ~ /$2:/)"
 101                fi
 102                SELECTED='y'
 103                shift 2 ;;
 104        -s|--soc)
 105                # echo "Option SoC: argument \`$2'"
 106                if [ "$opt_s" ] ; then
 107                        opt_s="${opt_s%)} || \$6 == \"$2\" || \$6 ~ /$2/)"
 108                else
 109                        opt_s="(\$6 == \"$2\" || \$6 ~ /$2/)"
 110                fi
 111                SELECTED='y'
 112                shift 2 ;;
 113        -v|--vendor)
 114                # echo "Option VENDOR: argument \`$2'"
 115                if [ "$opt_v" ] ; then
 116                        opt_v="${opt_v%)} || \$5 == \"$2\")"
 117                else
 118                        opt_v="(\$5 == \"$2\")"
 119                fi
 120                SELECTED='y'
 121                shift 2 ;;
 122        -C|--check)
 123                CHECK='C=1'
 124                shift ;;
 125        -n|--continue)
 126                CONTINUE='y'
 127                shift ;;
 128        -r|--rebuild-errors)
 129                REBUILD_ERRORS='y'
 130                shift ;;
 131        -l|--list)
 132                ONLY_LIST='y'
 133                shift ;;
 134        -m|--maintainers)
 135                ONLY_LIST='y'
 136                PRINT_MAINTS='y'
 137                MAINTAINERS_ONLY='y'
 138                shift ;;
 139        -M|--mails)
 140                ONLY_LIST='y'
 141                PRINT_MAINTS='y'
 142                shift ;;
 143        -h|--help)
 144                usage ;;
 145        --)
 146                shift ; break ;;
 147        *)
 148                echo "Internal error!" >&2 ; exit 1 ;;
 149        esac
 150done
 151# echo "Remaining arguments:"
 152# for arg do echo '--> '"\`$arg'" ; done
 153
 154FILTER="\$1 !~ /^#/"
 155[ "$opt_a" ] && FILTER="${FILTER} && $opt_a"
 156[ "$opt_c" ] && FILTER="${FILTER} && $opt_c"
 157[ "$opt_s" ] && FILTER="${FILTER} && $opt_s"
 158[ "$opt_v" ] && FILTER="${FILTER} && $opt_v"
 159
 160if [ "$SELECTED" ] ; then
 161        SELECTED=$(awk '('"$FILTER"') { print $1 }' boards.cfg)
 162
 163        # Make sure some boards from boards.cfg are actually found
 164        if [ -z "$SELECTED" ] ; then
 165                echo "Error: No boards selected, invalid arguments"
 166                exit 1
 167        fi
 168fi
 169
 170#########################################################################
 171
 172# Print statistics when we exit
 173trap exit 1 2 3 15
 174trap print_stats 0
 175
 176# Determine number of CPU cores if no default was set
 177: ${BUILD_NCPUS:="`getconf _NPROCESSORS_ONLN`"}
 178
 179if [ "$BUILD_NCPUS" -gt 1 ]
 180then
 181        JOBS="-j $((BUILD_NCPUS + 1))"
 182else
 183        JOBS=""
 184fi
 185
 186if [ "${MAKEALL_LOGDIR}" ] ; then
 187        LOG_DIR=${MAKEALL_LOGDIR}
 188else
 189        LOG_DIR="LOG"
 190fi
 191
 192: ${BUILD_NBUILDS:=1}
 193BUILD_MANY=0
 194
 195if [ "${BUILD_NBUILDS}" -gt 1 ] ; then
 196        BUILD_MANY=1
 197        : ${BUILD_DIR:=./build}
 198        mkdir -p "${BUILD_DIR}/ERR"
 199        find "${BUILD_DIR}/ERR/" -type f -exec rm -f {} +
 200fi
 201
 202: ${BUILD_DIR:=.}
 203
 204OUTPUT_PREFIX="${BUILD_DIR}"
 205
 206[ -d ${LOG_DIR} ] || mkdir "${LOG_DIR}" || exit 1
 207if [ "$CONTINUE" != 'y' -a "$REBUILD_ERRORS" != 'y' ] ; then
 208        find "${LOG_DIR}/" -type f -exec rm -f {} +
 209fi
 210
 211LIST=""
 212
 213# Keep track of the number of builds and errors
 214ERR_CNT=0
 215ERR_LIST=""
 216WRN_CNT=0
 217WRN_LIST=""
 218TOTAL_CNT=0
 219SKIP_CNT=0
 220CURRENT_CNT=0
 221OLDEST_IDX=1
 222RC=0
 223
 224# Helper funcs for parsing boards.cfg
 225boards_by_field()
 226{
 227        FS="[ \t]+"
 228        [ -n "$3" ] && FS="$3"
 229        awk \
 230                -v field="$1" \
 231                -v select="$2" \
 232                -F "$FS" \
 233                '($1 !~ /^#/ && $field == select) { print $1 }' \
 234                boards.cfg
 235}
 236boards_by_arch() { boards_by_field 2 "$@" ; }
 237boards_by_cpu()  { boards_by_field 3 "$@" "[: \t]+" ; }
 238boards_by_soc()  { boards_by_field 6 "$@" ; }
 239
 240#########################################################################
 241## MPC5xx Systems
 242#########################################################################
 243
 244LIST_5xx="$(boards_by_cpu mpc5xx)"
 245
 246#########################################################################
 247## MPC5xxx Systems
 248#########################################################################
 249
 250LIST_5xxx="$(boards_by_cpu mpc5xxx)"
 251
 252#########################################################################
 253## MPC512x Systems
 254#########################################################################
 255
 256LIST_512x="$(boards_by_cpu mpc512x)"
 257
 258#########################################################################
 259## MPC8xx Systems
 260#########################################################################
 261
 262LIST_8xx="$(boards_by_cpu mpc8xx)"
 263
 264#########################################################################
 265## PPC4xx Systems
 266#########################################################################
 267
 268LIST_4xx="$(boards_by_cpu ppc4xx)"
 269
 270#########################################################################
 271## MPC824x Systems
 272#########################################################################
 273
 274LIST_824x="$(boards_by_cpu mpc824x)"
 275
 276#########################################################################
 277## MPC8260 Systems (includes 8250, 8255 etc.)
 278#########################################################################
 279
 280LIST_8260="$(boards_by_cpu mpc8260)"
 281
 282#########################################################################
 283## MPC83xx Systems (includes 8349, etc.)
 284#########################################################################
 285
 286LIST_83xx="$(boards_by_cpu mpc83xx)"
 287
 288#########################################################################
 289## MPC85xx Systems (includes 8540, 8560 etc.)
 290#########################################################################
 291
 292LIST_85xx="$(boards_by_cpu mpc85xx)"
 293
 294#########################################################################
 295## MPC86xx Systems
 296#########################################################################
 297
 298LIST_86xx="$(boards_by_cpu mpc86xx)"
 299
 300#########################################################################
 301## 74xx/7xx Systems
 302#########################################################################
 303
 304LIST_74xx_7xx="$(boards_by_cpu 74xx_7xx)"
 305
 306#########################################################################
 307## PowerPC groups
 308#########################################################################
 309
 310LIST_TSEC="             \
 311        ${LIST_83xx}    \
 312        ${LIST_85xx}    \
 313        ${LIST_86xx}    \
 314"
 315
 316LIST_powerpc="          \
 317        ${LIST_5xx}     \
 318        ${LIST_512x}    \
 319        ${LIST_5xxx}    \
 320        ${LIST_8xx}     \
 321        ${LIST_824x}    \
 322        ${LIST_8260}    \
 323        ${LIST_83xx}    \
 324        ${LIST_85xx}    \
 325        ${LIST_86xx}    \
 326        ${LIST_4xx}     \
 327        ${LIST_74xx_7xx}\
 328"
 329
 330# Alias "ppc" -> "powerpc" to not break compatibility with older scripts
 331# still using "ppc" instead of "powerpc"
 332LIST_ppc="              \
 333        ${LIST_powerpc} \
 334"
 335
 336#########################################################################
 337## StrongARM Systems
 338#########################################################################
 339
 340LIST_SA="$(boards_by_cpu sa1100)"
 341
 342#########################################################################
 343## ARM7 Systems
 344#########################################################################
 345
 346LIST_ARM7="$(boards_by_cpu arm720t)"
 347
 348#########################################################################
 349## ARM9 Systems
 350#########################################################################
 351
 352LIST_ARM9="$(boards_by_cpu arm920t)     \
 353        $(boards_by_cpu arm926ejs)      \
 354        $(boards_by_cpu arm925t)        \
 355        $(boards_by_cpu arm946es)       \
 356"
 357
 358#########################################################################
 359## ARM11 Systems
 360#########################################################################
 361LIST_ARM11="$(boards_by_cpu arm1136)    \
 362        $(boards_by_cpu arm1176)        \
 363"
 364
 365#########################################################################
 366## ARMV7 Systems
 367#########################################################################
 368
 369LIST_ARMV7="$(boards_by_cpu armv7)"
 370
 371#########################################################################
 372## AT91 Systems
 373#########################################################################
 374
 375LIST_at91="$(boards_by_soc at91)"
 376
 377#########################################################################
 378## Xscale Systems
 379#########################################################################
 380
 381LIST_pxa="$(boards_by_cpu pxa)"
 382
 383LIST_ixp="$(boards_by_cpu ixp)"
 384
 385#########################################################################
 386## SPEAr Systems
 387#########################################################################
 388
 389LIST_spear="$(boards_by_soc spear)"
 390
 391#########################################################################
 392## ARM groups
 393#########################################################################
 394
 395LIST_arm="$(boards_by_arch arm)"
 396
 397#########################################################################
 398## MIPS Systems         (default = big endian)
 399#########################################################################
 400
 401LIST_mips4kc="          \
 402        incaip          \
 403        incaip_100MHz   \
 404        incaip_133MHz   \
 405        incaip_150MHz   \
 406        qemu_mips       \
 407        vct_platinum    \
 408        vct_platinum_small      \
 409        vct_platinum_onenand    \
 410        vct_platinum_onenand_small      \
 411        vct_platinumavc \
 412        vct_platinumavc_small   \
 413        vct_platinumavc_onenand \
 414        vct_platinumavc_onenand_small   \
 415        vct_premium     \
 416        vct_premium_small       \
 417        vct_premium_onenand     \
 418        vct_premium_onenand_small       \
 419"
 420
 421LIST_au1xx0="           \
 422        dbau1000        \
 423        dbau1100        \
 424        dbau1500        \
 425        dbau1550        \
 426"
 427
 428LIST_mips="             \
 429        ${LIST_mips4kc} \
 430        ${LIST_mips5kc} \
 431        ${LIST_au1xx0}  \
 432"
 433
 434#########################################################################
 435## MIPS Systems         (little endian)
 436#########################################################################
 437
 438LIST_au1xx0_el="        \
 439        dbau1550_el     \
 440        pb1000          \
 441"
 442LIST_mips_el="                  \
 443        ${LIST_au1xx0_el}       \
 444"
 445#########################################################################
 446## OpenRISC Systems
 447#########################################################################
 448
 449LIST_openrisc="$(boards_by_arch openrisc)"
 450
 451#########################################################################
 452## x86 Systems
 453#########################################################################
 454
 455LIST_x86="$(boards_by_arch x86)"
 456
 457#########################################################################
 458## Nios-II Systems
 459#########################################################################
 460
 461LIST_nios2="$(boards_by_arch nios2)"
 462
 463#########################################################################
 464## MicroBlaze Systems
 465#########################################################################
 466
 467LIST_microblaze="$(boards_by_arch microblaze)"
 468
 469#########################################################################
 470## ColdFire Systems
 471#########################################################################
 472
 473LIST_m68k="$(boards_by_arch m68k)"
 474LIST_coldfire=${LIST_m68k}
 475
 476#########################################################################
 477## AVR32 Systems
 478#########################################################################
 479
 480LIST_avr32="$(boards_by_arch avr32)"
 481
 482#########################################################################
 483## Blackfin Systems
 484#########################################################################
 485
 486LIST_blackfin="$(boards_by_arch blackfin)"
 487
 488#########################################################################
 489## SH Systems
 490#########################################################################
 491
 492LIST_sh2="$(boards_by_cpu sh2)"
 493LIST_sh3="$(boards_by_cpu sh3)"
 494LIST_sh4="$(boards_by_cpu sh4)"
 495
 496LIST_sh="$(boards_by_arch sh)"
 497
 498#########################################################################
 499## SPARC Systems
 500#########################################################################
 501
 502LIST_sparc="$(boards_by_arch sparc)"
 503
 504#########################################################################
 505## NDS32 Systems
 506#########################################################################
 507
 508LIST_nds32="$(boards_by_arch nds32)"
 509
 510#-----------------------------------------------------------------------
 511
 512get_target_location() {
 513        local target=$1
 514        local BOARD_NAME=""
 515        local CONFIG_NAME=""
 516        local board=""
 517        local vendor=""
 518
 519        # Automatic mode
 520        local line=`egrep -i "^[[:space:]]*${target}[[:space:]]" boards.cfg`
 521
 522        if [ -z "${line}" ] ; then echo "" ; return ; fi
 523
 524        set ${line}
 525
 526        # add default board name if needed
 527        [ $# = 3 ] && set ${line} ${1}
 528
 529        CONFIG_NAME="${1%_config}"
 530
 531        [ "${BOARD_NAME}" ] || BOARD_NAME="${1%_config}"
 532
 533        if [ "$4" = "-" ] ; then
 534                board=${BOARD_NAME}
 535        else
 536                board="$4"
 537        fi
 538
 539        [ $# -gt 4 ] && [ "$5" != "-" ] && vendor="$5"
 540        [ $# -gt 6 ] && [ "$7" != "-" ] && {
 541                tmp="${7%:*}"
 542                if [ "$tmp" ] ; then
 543                        CONFIG_NAME="$tmp"
 544                fi
 545        }
 546
 547        # Assign board directory to BOARDIR variable
 548        if [ -z "${vendor}" ] ; then
 549            BOARDDIR=${board}
 550        else
 551            BOARDDIR=${vendor}/${board}
 552        fi
 553
 554        echo "${CONFIG_NAME}:${BOARDDIR}"
 555}
 556
 557get_target_maintainers() {
 558        local name=`echo $1 | cut -d : -f 1`
 559
 560        if ! grep -qsi "[[:blank:]]${name}[[:blank:]]" MAINTAINERS ; then
 561                echo ""
 562                return ;
 563        fi
 564
 565        local line=`tac MAINTAINERS | grep -ni "[[:blank:]]${name}[[:blank:]]" | cut -d : -f 1`
 566        local mail=`tac MAINTAINERS | tail -n +${line} | \
 567                sed -n ":start /.*@.*/ { b mail } ; n ; b start ; :mail /.*@.*/ { p ; n ; b mail } ; q" | \
 568                sed "s/^.*<//;s/>.*$//"`
 569        echo "$mail"
 570}
 571
 572get_target_arch() {
 573        local target=$1
 574
 575        # Automatic mode
 576        local line=`egrep -i "^[[:space:]]*${target}[[:space:]]" boards.cfg`
 577
 578        if [ -z "${line}" ] ; then echo "" ; return ; fi
 579
 580        set ${line}
 581        echo "$2"
 582}
 583
 584list_target() {
 585        if [ "$PRINT_MAINTS" != 'y' ] ; then
 586                echo "$1"
 587                return
 588        fi
 589
 590        echo -n "$1:"
 591
 592        local loc=`get_target_location $1`
 593
 594        if [ -z "${loc}" ] ; then echo "ERROR" ; return ; fi
 595
 596        local maintainers_result=`get_target_maintainers ${loc} | tr " " "\n"`
 597
 598        if [ "$MAINTAINERS_ONLY" != 'y' ] ; then
 599
 600                local dir=`echo ${loc} | cut -d ":" -f 2`
 601                local cfg=`echo ${loc} | cut -d ":" -f 1`
 602                local git_result=`git log --format=%aE board/${dir} \
 603                                include/configs/${cfg}.h | grep "@"`
 604                local git_result_recent=`echo ${git_result} | tr " " "\n" | \
 605                                                head -n 3`
 606                local git_result_top=`echo ${git_result} | tr " " "\n" | \
 607                        sort | uniq -c | sort -nr | head -n 3 | \
 608                        sed "s/^ \+[0-9]\+ \+//"`
 609
 610                echo -e "$git_result_recent\n$git_result_top\n$maintainers_result" | \
 611                        sort -u | tr "\n" " " | sed "s/ $//" ;
 612        else
 613                echo -e "$maintainers_result" | sort -u | tr "\n" " " | \
 614                                                sed "s/ $//" ;
 615        fi
 616
 617        echo ""
 618}
 619
 620# Each finished build will have a file called ${donep}${n},
 621# where n is the index of the build. Each build
 622# we've already noted as finished will have ${skipp}${n}.
 623# The code managing the build process will use this information
 624# to ensure that only BUILD_NBUILDS builds are in flight at once
 625donep="${LOG_DIR}/._done_"
 626skipp="${LOG_DIR}/._skip_"
 627
 628build_target_killed() {
 629        echo "Aborted $target build."
 630        # Remove the logs for this board since it was aborted
 631        rm -f ${LOG_DIR}/$target.MAKELOG ${LOG_DIR}/$target.ERR
 632        exit
 633}
 634
 635build_target() {
 636        target=$1
 637        build_idx=$2
 638
 639        if [ "$ONLY_LIST" == 'y' ] ; then
 640                list_target ${target}
 641                return
 642        fi
 643
 644        if [ $BUILD_MANY == 1 ] ; then
 645                output_dir="${OUTPUT_PREFIX}/${target}"
 646                mkdir -p "${output_dir}"
 647                trap build_target_killed TERM
 648        else
 649                output_dir="${OUTPUT_PREFIX}"
 650        fi
 651
 652        export BUILD_DIR="${output_dir}"
 653
 654        target_arch=$(get_target_arch ${target})
 655        eval cross_toolchain=\$CROSS_COMPILE_`echo $target_arch | tr '[:lower:]' '[:upper:]'`
 656        if [ "${cross_toolchain}" ] ; then
 657            MAKE="make CROSS_COMPILE=${cross_toolchain}"
 658        elif [ "${CROSS_COMPILE}" ] ; then
 659            MAKE="make CROSS_COMPILE=${CROSS_COMPILE}"
 660        else
 661            MAKE=make
 662        fi
 663
 664        ${MAKE} distclean >/dev/null
 665        ${MAKE} -s ${target}_config
 666
 667        ${MAKE} ${JOBS} ${CHECK} all \
 668                >${LOG_DIR}/$target.MAKELOG 2> ${LOG_DIR}/$target.ERR
 669
 670        # Check for 'make' errors
 671        if [ ${PIPESTATUS[0]} -ne 0 ] ; then
 672                RC=1
 673        fi
 674
 675        if [ $BUILD_MANY == 1 ] ; then
 676                trap - TERM
 677
 678                ${MAKE} -s tidy
 679
 680                if [ -s ${LOG_DIR}/${target}.ERR ] ; then
 681                        cp ${LOG_DIR}/${target}.ERR ${OUTPUT_PREFIX}/ERR/${target}
 682                else
 683                        rm ${LOG_DIR}/${target}.ERR
 684                fi
 685        else
 686                if [ -s ${LOG_DIR}/${target}.ERR ] ; then
 687                        if grep -iw error ${LOG_DIR}/${target}.ERR ; then
 688                                : $(( ERR_CNT += 1 ))
 689                                ERR_LIST="${ERR_LIST} $target"
 690                        else
 691                                : $(( WRN_CNT += 1 ))
 692                                WRN_LIST="${WRN_LIST} $target"
 693                        fi
 694                else
 695                        rm ${LOG_DIR}/${target}.ERR
 696                fi
 697        fi
 698
 699        OBJS=${output_dir}/u-boot
 700        if [ -e ${output_dir}/spl/u-boot-spl ]; then
 701                OBJS="${OBJS} ${output_dir}/spl/u-boot-spl"
 702        fi
 703
 704        ${CROSS_COMPILE}size ${OBJS} | tee -a ${LOG_DIR}/$target.MAKELOG
 705
 706        [ -e "${LOG_DIR}/${target}.ERR" ] && cat "${LOG_DIR}/${target}.ERR"
 707
 708        touch "${donep}${build_idx}"
 709}
 710
 711manage_builds() {
 712        search_idx=${OLDEST_IDX}
 713        if [ "$ONLY_LIST" == 'y' ] ; then return ; fi
 714
 715        while true; do
 716                if [ -e "${donep}${search_idx}" ] ; then
 717                        : $(( CURRENT_CNT-- ))
 718                        [ ${OLDEST_IDX} -eq ${search_idx} ] &&
 719                                : $(( OLDEST_IDX++ ))
 720
 721                        # Only want to count it once
 722                        rm -f "${donep}${search_idx}"
 723                        touch "${skipp}${search_idx}"
 724                elif [ -e "${skipp}${search_idx}" ] ; then
 725                        [ ${OLDEST_IDX} -eq ${search_idx} ] &&
 726                                : $(( OLDEST_IDX++ ))
 727                fi
 728                : $(( search_idx++ ))
 729                if [ ${search_idx} -gt ${TOTAL_CNT} ] ; then
 730                        if [ ${CURRENT_CNT} -ge ${BUILD_NBUILDS} ] ; then
 731                                search_idx=${OLDEST_IDX}
 732                                sleep 1
 733                        else
 734                                break
 735                        fi
 736                fi
 737        done
 738}
 739
 740build_targets() {
 741        for t in "$@" ; do
 742                # If a LIST_xxx var exists, use it.  But avoid variable
 743                # expansion in the eval when a board name contains certain
 744                # characters that the shell interprets.
 745                case ${t} in
 746                        *[-+=]*) list= ;;
 747                        *)       list=$(eval echo '${LIST_'$t'}') ;;
 748                esac
 749                if [ -n "${list}" ] ; then
 750                        build_targets ${list}
 751                else
 752                        : $((TOTAL_CNT += 1))
 753                        : $((CURRENT_CNT += 1))
 754                        rm -f "${donep}${TOTAL_CNT}"
 755                        rm -f "${skipp}${TOTAL_CNT}"
 756                        if [ "$CONTINUE" = 'y' -a -e ${LOG_DIR}/$t.MAKELOG ] ; then
 757                                : $((SKIP_CNT += 1))
 758                                touch "${donep}${TOTAL_CNT}"
 759                        elif [ "$REBUILD_ERRORS" = 'y' -a ! -e ${LOG_DIR}/$t.ERR ] ; then
 760                                : $((SKIP_CNT += 1))
 761                                touch "${donep}${TOTAL_CNT}"
 762                        else
 763                                if [ $BUILD_MANY == 1 ] ; then
 764                                        build_target ${t} ${TOTAL_CNT} &
 765                                else
 766                                        CUR_TGT="${t}"
 767                                        build_target ${t} ${TOTAL_CNT}
 768                                        CUR_TGT=''
 769                                fi
 770                        fi
 771                fi
 772
 773                # We maintain a running count of all the builds we have done.
 774                # Each finished build will have a file called ${donep}${n},
 775                # where n is the index of the build. Each build
 776                # we've already noted as finished will have ${skipp}${n}.
 777                # We track the current index via TOTAL_CNT, and the oldest
 778                # index. When we exceed the maximum number of parallel builds,
 779                # We look from oldest to current for builds that have completed,
 780                # and update the current count and oldest index as appropriate.
 781                # If we've gone through the entire list, wait a second, and
 782                # reprocess the entire list until we find a build that has
 783                # completed
 784                if [ ${CURRENT_CNT} -ge ${BUILD_NBUILDS} ] ; then
 785                        manage_builds
 786                fi
 787        done
 788}
 789
 790#-----------------------------------------------------------------------
 791
 792kill_children() {
 793        local OS=$(uname -s)
 794        local children=""
 795        case "${OS}" in
 796                "Darwin")
 797                        # Mac OS X is known to have BSD style ps
 798                        local pgid=$(ps -p $$ -o pgid | sed -e "/PGID/d")
 799                        children=$(ps -g $pgid -o pid | sed -e "/PID\|$$\|$pgid/d")
 800                        ;;
 801                *)
 802                        # everything else tries the GNU style
 803                        local pgid=$(ps -p $$ --no-headers -o "%r" | tr -d ' ')
 804                        children=$(pgrep -g $pgid | sed -e "/$$\|$pgid/d")
 805                        ;;
 806        esac
 807
 808        kill $children 2> /dev/null
 809        wait $children 2> /dev/null
 810
 811        exit
 812}
 813
 814print_stats() {
 815        if [ "$ONLY_LIST" == 'y' ] ; then return ; fi
 816
 817        # Only count boards that completed
 818        : $((TOTAL_CNT = `find ${skipp}* 2> /dev/null | wc -l`))
 819
 820        rm -f ${donep}* ${skipp}*
 821
 822        if [ $BUILD_MANY == 1 ] && [ -e "${OUTPUT_PREFIX}/ERR" ] ; then
 823                ERR_LIST=`grep -riwl error ${OUTPUT_PREFIX}/ERR/`
 824                ERR_LIST=`for f in $ERR_LIST ; do echo -n " $(basename $f)" ; done`
 825                ERR_CNT=`echo $ERR_LIST | wc -w | awk '{print $1}'`
 826                WRN_LIST=`grep -riwL error ${OUTPUT_PREFIX}/ERR/`
 827                WRN_LIST=`for f in $WRN_LIST ; do echo -n " $(basename $f)" ; done`
 828                WRN_CNT=`echo $WRN_LIST | wc -w | awk '{print $1}'`
 829        else
 830                # Remove the logs for any board that was interrupted
 831                rm -f ${LOG_DIR}/${CUR_TGT}.MAKELOG ${LOG_DIR}/${CUR_TGT}.ERR
 832        fi
 833
 834        : $((TOTAL_CNT -= ${SKIP_CNT}))
 835        echo ""
 836        echo "--------------------- SUMMARY ----------------------------"
 837        if [ "$CONTINUE" = 'y' -o "$REBUILD_ERRORS" = 'y' ] ; then
 838                echo "Boards skipped: ${SKIP_CNT}"
 839        fi
 840        echo "Boards compiled: ${TOTAL_CNT}"
 841        if [ ${ERR_CNT} -gt 0 ] ; then
 842                echo "Boards with errors: ${ERR_CNT} (${ERR_LIST} )"
 843        fi
 844        if [ ${WRN_CNT} -gt 0 ] ; then
 845                echo "Boards with warnings but no errors: ${WRN_CNT} (${WRN_LIST} )"
 846        fi
 847        echo "----------------------------------------------------------"
 848
 849        if [ $BUILD_MANY == 1 ] ; then
 850                kill_children
 851        fi
 852
 853        exit $RC
 854}
 855
 856#-----------------------------------------------------------------------
 857
 858# Build target groups selected by options, plus any command line args
 859set -- ${SELECTED} "$@"
 860# run PowerPC by default
 861[ $# = 0 ] && set -- powerpc
 862build_targets "$@"
 863wait
 864