coreboot-kgpe-d16/util/abuild/abuild
Martin Roth 6d2cbb9e58 abuild: Update file locations
The full path to the passed/failed build lists needs to be specified.
On the builders, the absolute path is passed in, which conflicted with
the ${TOP} value, causing this to fail on the builders. When TOP was
removed from the path, the builders worked correctly, but it failed when
run locally.  This fixes the path in either case.

Change-Id: Ia4370f4a2b84991edccfc723a3136b88ca27db7d
Signed-off-by: Martin Roth <martinroth@google.com>
Reviewed-on: https://review.coreboot.org/20660
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Stefan Reinauer <stefan.reinauer@coreboot.org>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
2017-07-25 15:11:24 +00:00

856 lines
25 KiB
Bash
Executable file

#!/bin/bash
#
# coreboot autobuild
#
# This script builds coreboot images for all available targets.
#
# (C) 2004 by Stefan Reinauer <stepan@openbios.org>
# (C) 2006-2010 by coresystems GmbH <info@coresystems.de>
# (C) 2013-2014 Sage Electronic Engineering, LLC
# (C) 2014 Patrick Georgi <patrick@georgi-clan.de>
#
# This file is subject to the terms and conditions of the GNU General
# Public License. See the file COPYING in the main directory of this
# archive for more details.
#
#set -x # Turn echo on....
ABUILD_DATE="Mar 28, 2017"
ABUILD_VERSION="0.10.03"
TOP=$PWD
# Where shall we place all the build trees?
TARGET=${COREBOOT_BUILD_DIR:-coreboot-builds}
XMLFILE=$TOP/abuild.xml
REAL_XMLFILE=$XMLFILE
export KCONFIG_OVERWRITECONFIG=1
# path to payload. Should be more generic
PAYLOAD=/dev/null
# get path to coreboot XGCC if it's not already set
if [ -z "$XGCCPATH" ]; then
XGCCPATH="${TOP}/util/crossgcc/xgcc/bin/"
fi
# Add XGCC to the path.
if [ -d "$XGCCPATH" ] && [[ ":$PATH:" != *":$XGCCPATH:"* ]]; then
PATH="$XGCCPATH:$PATH"
fi
# Lines of error context to be printed in FAILURE case
CONTEXT=12
# Configure-only mode
configureonly=0
# Did any board fail to build?
failed=0
# default: don't save checksums
checksum_file=""
# default: single CPU build
cpus=1
# change with -d <directory>
configdir="$TOP/configs"
# Timeless builds
TIMELESS=0
# One might want to adjust these in case of cross compiling
for i in make gmake gnumake nonexistant_make; do
$i --version 2>/dev/null |grep "GNU Make" >/dev/null && break
done
if [ "$i" = "nonexistant_make" ]; then
echo No GNU Make found.
exit 1
fi
MAKE=$i
# this can be changed to junit by -J
mode=text
# quiet mode: only print pass, failure, and 'skipped' messages
quiet=false
# clang mode enabled by -sb option.
scanbuild=false
# Mark whether abuild was called recursively
recursive=false
trap interrupt INT
function interrupt
{
printf "\n%s: execution interrupted manually.\n" "$0"
if [ "$mode" == "junit" ]; then
printf "%s: deleting incomplete xml output file.\n" "$0"
fi
exit 1
}
function debug
{
test "$verbose" == "true" && echo "$*"
}
function junit
{
test "$mode" == "junit" && echo "$*" >> "$XMLFILE"
return 0
}
function junitfile
{
test "$mode" == "junit" && {
printf '<![CDATA[\n'
cat "$1"
printf ']]>\n'
} >> "$XMLFILE"
}
# Return mainboard descriptors.
# By default all mainboards are listed, but when passing a two-level path
# below src/mainboard, such as emulation/qemu-i440fx, or emulation/*, it
# returns all board descriptors in that hierarchy.
function get_mainboards
{
local search_space=${1-*/*}
# shellcheck disable=SC2086
grep -h "^[[:space:]]*config\>[[:space:]]*\<BOARD_" \
${ROOT}/src/mainboard/${search_space}/Kconfig.name 2>/dev/null | \
sed "s,^.*\<BOARD_\([A-Z0-9_]*\)\>.*$,\1,"
}
# Given a mainboard descriptor, return its directory below src/mainboard
function mainboard_directory
{
local MAINBOARD=$1
# shellcheck disable=SC2086
grep -l "^[[:space:]]*config\>[[:space:]]*\<BOARD_${MAINBOARD}\>" \
${ROOT}/src/mainboard/*/*/Kconfig.name | \
sed "s:^$ROOT/src/mainboard/\(.*\)/Kconfig.name$:\1:"
}
# Given a mainboard descriptor, return its vendor (CONFIG_VENDOR_*)
function mainboard_vendor
{
local MAINBOARD=$1
local kconfig_file
# shellcheck disable=SC2086
kconfig_file=$( \
grep -l "^[[:space:]]*config\>[[:space:]]*\<BOARD_${MAINBOARD}\>" \
${ROOT}/src/mainboard/*/*/Kconfig.name | \
sed "s:^\(${ROOT}/src/mainboard/.*\)/.*/\(Kconfig.name\)$:\1/\2:" )
if [ ! -f "$kconfig_file" ]; then
exit 1
fi
grep "^[[:space:]]*config\>[[:space:]]*\<VENDOR_" "$kconfig_file" | \
sed "s,^.*\<VENDOR_\([A-Z0-9_]*\)\>.*$,\1,"
}
# Accepts directory names (eg. emulation/qemu-i440fx) and mainboard
# descriptors (eg. EMULATION_QEMU_X86_I440F} and returns the latter
# format.
# If a directory contains multiple boards, returns them all.
function normalize_target
{
local targets
targets=$(get_mainboards "$1")
if [ -n "$targets" ]; then
echo "$targets"
return
fi
targets=$(echo "$1" | tr ',' ' ')
for i in $targets; do
if [ -n "$(mainboard_directory "$i")" ]; then
echo "$i"
else
echo "$i is not a valid target" >&2
exit 1
fi
done
}
# shellcheck disable=SC2129
function create_config
{
local BUILD_NAME=$1
local build_dir=$2
local board_srcdir
local config_file="${build_dir}/config.build"
board_srcdir="$(mainboard_directory "${BUILD_NAME}")"
mkdir -p "${build_dir}"
mkdir -p "$TARGET/sharedutils"
if [ "$quiet" == "false" ]; then echo " Creating config file for $BUILD_NAME..."; fi
echo "CONFIG_VENDOR_$(mainboard_vendor "${BUILD_NAME}")=y" > "${config_file}"
echo "CONFIG_BOARD_${BUILD_NAME}=y" >> "${config_file}"
grep "select[\t ]*ARCH" "${ROOT}/src/mainboard/${board_srcdir}/Kconfig" | \
sed "s,^.*\(ARCH_.*\)[^A-Z0-9_]*,CONFIG_\1=y," >> "${config_file}"
echo "CONFIG_MAINBOARD_DIR=\"${board_srcdir}\"" >> "${config_file}"
update_config "$BUILD_NAME" "$build_dir" "$config_file"
ret=$?
if [ $ret -eq 0 ]; then
if [ "$quiet" == "false" ]; then echo " $BUILD_NAME config created."; fi
return 0
else
# Does this ever happen?
if [ "$quiet" == "false" ]; then printf "%s config creation FAILED!\nLog excerpt:\n" "$BUILD_NAME"; fi
tail -n $CONTEXT "$build_dir/config.log" 2> /dev/null || tail -$CONTEXT "$build_dir/config.log"
return 1
fi
}
function update_config
{
local BUILD_NAME=$1
local build_dir=$2
local config_file=$3
local PAYLOAD
local defconfig_file
defconfig_file=${build_dir}/config.$(echo "${BUILD_NAME}" | tr '[:upper:]' '[:lower:]').default
# get a working payload for the board if we have one.
# the --payload option expects a directory containing
# a shell script payload.sh
# Usage: payload.sh [BOARD]
# the script returns an absolute path to the payload binary.
if [ -f "$payloads/payload.sh" ]; then
PAYLOAD=$(sh "$payloads/payload.sh" "$BUILD_NAME")
local PAYLOAD_OK=$?
if [ $PAYLOAD_OK -gt 0 ]; then
echo "problem with payload"
exit 1
fi
if [ "$quiet" == "false" ]; then printf "Using payload %s\n" "$PAYLOAD"; fi
elif [ "$payloads" = "none" ]; then
PAYLOAD=none
fi
if [ "$PAYLOAD" = "none" ]; then
{
echo "CONFIG_PAYLOAD_NONE=y"
echo "# CONFIG_PAYLOAD_SEABIOS is not set"
echo "# CONFIG_PAYLOAD_ELF is not set"
echo "# CONFIG_PAYLOAD_BAYOU is not set"
echo "# CONFIG_PAYLOAD_FILO is not set"
echo "# CONFIG_PAYLOAD_GRUB2 is not set"
echo "# CONFIG_PAYLOAD_OPENBIOS is not set"
echo "# CONFIG_PAYLOAD_DEPTHCHARGE is not set"
echo "# CONFIG_PAYLOAD_UBOOT is not set"
echo "# CONFIG_PAYLOAD_TIANOCORE is not set"
} >> "${config_file}"
elif [ "$PAYLOAD" != "/dev/null" ]; then
{
echo "# CONFIG_PAYLOAD_NONE is not set"
echo "# CONFIG_PAYLOAD_SEABIOS is not set"
echo "CONFIG_PAYLOAD_ELF=y"
echo "CONFIG_PAYLOAD_FILE=\"$PAYLOAD\""
} >> "${config_file}"
fi
if [ "$quiet" == "false" ]; then echo " $MAINBOARD ($customizing)"; fi
# shellcheck disable=SC2059
printf "$configoptions" >> "${config_file}"
yes "" 2>/dev/null | $MAKE oldconfig "$verboseopt" "DOTCONFIG=${config_file}" "obj=${build_dir}" "objutil=$TARGET/sharedutils" &> "${build_dir}/config.log" ; \
CONFIG_OK=$?
if [ $CONFIG_OK -eq 0 ]; then
$MAKE savedefconfig "$verboseopt" DEFCONFIG="${defconfig_file}" DOTCONFIG="${config_file}" obj="${build_dir}" objutil="$TARGET/sharedutils" &>> "${build_dir}/config.log"
return $?
else
return 1
fi
}
# shellcheck disable=SC2129
function create_buildenv
{
local BUILD_NAME=$1
local build_dir=$2
local config_file=$3
if [ -z "$config_file" ]; then
create_config "$BUILD_NAME" "$build_dir"
else
local new_config_file="${build_dir}/config.build"
cp "$config_file" "$new_config_file"
update_config "$BUILD_NAME" "$build_dir" "$new_config_file"
fi
local ret=$?
# Allow simple "make" in the target directory
local MAKEFILE=$TARGET/${BUILD_NAME}/Makefile
echo "# autogenerated" > "$MAKEFILE"
echo "TOP=$ROOT" >> "$MAKEFILE"
echo "BUILD=$TARGET" >> "$MAKEFILE"
echo "OBJ=\$(BUILD)/${MAINBOARD}" >> "$MAKEFILE"
echo "OBJUTIL=\$(BUILD)/sharedutils" >> "$MAKEFILE"
echo "all:" >> "$MAKEFILE"
echo " @cp -a config.h config.h.bak" >> "$MAKEFILE"
echo " @cd \$(TOP); \$(MAKE) oldconfig DOTCONFIG=\$(OBJ)/config.build objutil=\$(OBJUTIL) obj=\$(OBJ)" >> "$MAKEFILE"
echo " @tail -n+6 config.h > config.new; tail -n+6 config.h.bak > config.old" >> "$MAKEFILE"
echo " @cmp -s config.new config.old && cp -a config.h.bak config.h || echo \"Config file changed\"" >> "$MAKEFILE"
echo " @rm config.h.bak config.new config.old" >> "$MAKEFILE"
echo " @cd \$(TOP); \$(MAKE) DOTCONFIG=\$(OBJ)/config.build objutil=\$(OBJUTIL) obj=\$(OBJ)" >> "$MAKEFILE"
return $ret
}
function check_config
{
local BUILD_DIR="$1"
local TEST_TYPE="$2"
local TEST_STRING="$3"
local CONFIG_FILE="$BUILD_DIR/config.build"
local CONFIG_LOG="$BUILD_DIR/config.log"
if ! grep -q "$TEST_STRING" "$CONFIG_FILE"; then
echo "config file: $CONFIG_FILE has incorrect $TEST_TYPE"
echo "Error: Expected '$TEST_STRING' in config file." >> "$CONFIG_LOG"
return 1
fi
return 0
}
function compile_target
{
local BUILD_NAME=$1
if [ "$quiet" == "false" ]; then echo " Compiling $MAINBOARD image$cpuconfig..."; fi
CURR=$( pwd )
#stime=`perl -e 'print time();' 2>/dev/null || date +%s`
eval $BUILDPREFIX $MAKE "$verboseopt" DOTCONFIG="${build_dir}/config.build" obj="${build_dir}" objutil="$TARGET/sharedutils" BUILD_TIMELESS=$TIMELESS \
&> "${build_dir}/make.log" ; \
MAKE_FAILED=$?
cp .xcompile "${build_dir}/xcompile.build"
cd "${build_dir}" || return $?
etime=$(perl -e 'print time();' 2>/dev/null || date +%s)
duration=$(( etime - stime ))
junit " <testcase classname='board${testclass/#/.}' name='$BUILD_NAME' time='$duration' >"
if [ $MAKE_FAILED -eq 0 ]; then
junit "<system-out>"
junitfile make.log
junit "</system-out>"
printf "ok\n" > compile.status
printf "%s built successfully. (took %ss)\n" "$BUILD_NAME" "${duration}"
echo "$BUILD_NAME" >> "$PASSED_BOARDS"
else
junit "<failure type='BuildFailed'>"
junitfile make.log
junit "</failure>"
printf "failed\n" > compile.status
printf "%s build FAILED after %ss!\nLog excerpt:\n" "$BUILD_NAME" "${duration}"
tail -n $CONTEXT make.log 2> /dev/null || tail -$CONTEXT make.log
echo "$BUILD_NAME - Log: ${TOP}/${build_dir}/make.log" >> "$FAILED_BOARDS"
failed=1
fi
cd "$CURR" || return $?
if [ -n "$checksum_file" ]; then
sha256sum "${build_dir}/coreboot.rom" >> "${checksum_file}_platform"
sort "${build_dir}/config.h" | grep CONFIG_ > "${build_dir}/config.h.sorted"
sha256sum "${build_dir}/config.h.sorted" >> "${checksum_file}_config"
fi
if [ "$clean_work" = "true" ]; then
rm -rf "${build_dir}"
fi
return $MAKE_FAILED
}
function build_config
{
local MAINBOARD=$1
local build_dir=$2
local BUILD_NAME=$3
local config_file=$4
local board_srcdir
local ret
board_srcdir=$(mainboard_directory "${MAINBOARD}")
if [ "$(cat "${build_dir}/compile.status" 2>/dev/null)" = "ok" ] && \
[ "$buildall" = "false" ]; then
echo "Skipping $BUILD_NAME; (already successful)"
return
fi
export HOSTCC='gcc'
if [ "$chromeos" = true ] && [ "$(grep -c "^[[:space:]]*select[[:space:]]*MAINBOARD_HAS_CHROMEOS\>" "${ROOT}/src/mainboard/${board_srcdir}/Kconfig")" -eq 0 ]; then
echo "${BUILD_NAME} doesn't support Chrome OS, skipping."
return
fi
if [ -f "src/mainboard/${board_srcdir}/abuild.disabled" ]; then
echo "${BUILD_NAME} disabled:"
cat "src/mainboard/${board_srcdir}/abuild.disabled"
return
fi
if [ "$quiet" == "false" ]; then echo "Building $BUILD_NAME"; fi
mkdir -p "$TARGET/${BUILD_NAME}" "$TARGET/abuild"
ABSPATH="$(cd "$TARGET/abuild" && pwd)"
XMLFILE="$ABSPATH/${BUILD_NAME}.xml"
rm -f "${XMLFILE}"
stime=$(perl -e 'print time();' 2>/dev/null || date +%s)
create_buildenv "$BUILD_NAME" "$build_dir" "$config_file"
local BUILDENV_CREATED=$?
check_config "$build_dir" "mainboard" "CONFIG_BOARD_${MAINBOARD}=y"
local MAINBOARD_OK=$?
check_config "$build_dir" "vendor" "CONFIG_VENDOR_$(mainboard_vendor "${MAINBOARD}")=y"
local VENDOR_OK=$?
if [ $BUILDENV_CREATED -ne 0 ] || [ $MAINBOARD_OK -ne 0 ] || [ $VENDOR_OK -ne 0 ]; then
junit " <testcase classname='board${testclass/#/.}' name='$BUILD_NAME' >"
junit "<failure type='BuildFailed'>"
junitfile "$build_dir/config.log"
junit "</failure>"
printf "failed\n" > compile.status
printf "%s build configuration FAILED!\nLog excerpt:\n" "$BUILD_NAME"
tail -n $CONTEXT "$build_dir/config.log" 2> /dev/null || tail -$CONTEXT "$build_dir/config.log"
junit "</testcase>"
echo "$BUILD_NAME - Log: ${TOP}/$build_dir/config.log" >> "$FAILED_BOARDS"
return
fi
required_arches=$(egrep "^CONFIG_ARCH_(BOOTBLOCK|R.MSTAGE|VERSTAGE)" "$TARGET/${BUILD_NAME}/config.build" | \
sed "s,^CONFIG_ARCH_[^_]*_\([^=]*\)=.*$,\1," |sort -u |tr 'A-Z\n\r' 'a-z ')
# shellcheck disable=SC2016,SC2059
missing_arches=$(printf 'include .xcompile\nall: ; @echo $(foreach arch,'"$required_arches"',$(if $(filter $(arch),$(SUBARCH_SUPPORTED)),,$(arch)))' | make --no-print-directory -f -)
if [ -n "$missing_arches" ]; then
printf "skipping %s because we're missing compilers for (%s)\n" "$BUILD_NAME" "$missing_arches"
return
fi
if [ $BUILDENV_CREATED -eq 0 ] && [ $configureonly -eq 0 ]; then
BUILDPREFIX=
if [ "$scanbuild" = "true" ]; then
scanbuild_out=$TARGET/${BUILD_NAME}-scanbuild
rm -rf "${scanbuild_out}"
BUILDPREFIX="scan-build -o ${scanbuild_out}tmp"
fi
compile_target "${BUILD_NAME}"
if [ "$scanbuild" = "true" ]; then
mv "${scanbuild_out}"tmp/* "${scanbuild_out}"
rmdir "${scanbuild_out}tmp"
fi
fi
junit "</testcase>"
}
# One target may build several configs
function build_target
{
local MAINBOARD=$1
local MAINBOARD_LC
MAINBOARD_LC=$(echo "$MAINBOARD" | tr '[:upper:]' '[:lower:]')
# look for config files in the config directory that match the boardname
if [ -n "$( find "$configdir" -maxdepth 1 -name "config.${MAINBOARD_LC}*" -print -quit )" ]; then
for config in "$configdir/config.${MAINBOARD_LC}"*; do
BUILD_NAME="${config##*/}"
BUILD_NAME="${BUILD_NAME##config.}"
BUILD_NAME=$(echo "${BUILD_NAME}" | tr '[:lower:]' '[:upper:]')
echo "Building config $BUILD_NAME"
build_dir=$TARGET/${BUILD_NAME}
build_config "$MAINBOARD" "$build_dir" "$BUILD_NAME" "$config"
remove_target "$BUILD_NAME"
done
else
echo "Building board $MAINBOARD (using default config)"
build_dir=$TARGET/${MAINBOARD}
build_config "$MAINBOARD" "$build_dir" "$MAINBOARD"
remove_target "$MAINBOARD"
fi
}
function remove_target
{
if [ "$remove" != "true" ]; then
return
fi
local BUILD_NAME=$1
# Save the generated coreboot.rom file of each board.
if [ -r "$TARGET/${BUILD_NAME}/coreboot.rom" ]; then
cp "$TARGET/${BUILD_NAME}/coreboot.rom" \
"${BUILD_NAME}_coreboot.rom"
fi
echo "Removing build dir for $BUILD_NAME..."
rm -rf "${TARGET:?}/${BUILD_NAME}"
return
}
function myhelp
{
cat << __END_OF_HELP
Usage: $0 [options]
$0 [-V|--version]
$0 [-h|--help]
Options:\n"
[-a|--all] Build previously succeeded ports as well
[-B|--blobs] Allow using binary files
[--checksum <path/basefile>] Store checksums at path/basefile
[-c|--cpus <numcpus>] Build on <numcpus> at the same time
[-C|--config] Configure-only mode
[-d|--dir <dir>] Directory containing config files
[-J|--junit] Write JUnit formatted xml log file
[-K|--kconfig <name>] Prepend file to generated Kconfig
[-l|--loglevel <num>] Set loglevel
[-L|--clang] Use clang
[-o|--outdir <path>] Store build results in path
(defaults to $TARGET)
[-p|--payloads <dir>] Use payloads in <dir> to build images
[-P|--prefix <name>] File name prefix in CBFS
[-q|--quiet] Print fewer messages
[-r|--remove] Remove output dir after build
[-R|--root <path>] Absolute path to coreboot sources
(defaults to $ROOT)
[--scan-build] Use clang's static analyzer
[--timeless] Generate timeless builds
[-t|--target <vendor/board>] Attempt to build target vendor/board only
[-T|--test] Submit image(s) to automated test system
[-u|--update] Update existing image
[-v|--verbose] Print more messages
[-x|--chromeos] Build with CHROMEOS enabled
Skip boards without Chrome OS support
[-X|--xmlfile <name>] Set JUnit XML log file filename
(defaults to $XMLFILE)
[-y|--ccache] Use ccache
[-z|--clean] Remove build results when finished
[-V|--version] Print version number and exit
[-h|--help] Print this help and exit
[-s|--silent] obsolete
__END_OF_HELP
}
function myversion
{
cat << EOF
coreboot autobuild v$ABUILD_VERSION ($ABUILD_DATE)
Copyright (C) 2004 by Stefan Reinauer <stepan@openbios.org>
Copyright (C) 2006-2010 by coresystems GmbH <info@coresystems.de>
This program is free software; you may redistribute it under the terms
of the GNU General Public License. This program has absolutely no
warranty.
EOF
}
# default options
target=""
buildall=false
verbose=false
test -f util/sconfig/sconfig.l && ROOT=$( pwd )
test -f ../util/sconfig/sconfig.l && ROOT=$( cd .. && pwd )
test "$ROOT" = "" && ROOT=$( cd ../.. && pwd )
# Look if we have getopt. If not, build it.
export PATH=$PATH:util/abuild
getopt - > /dev/null 2>/dev/null || gcc -o util/abuild/getopt util/abuild/getopt.c
# Save command line for xargs parallelization.
cmdline=("$@")
# parse parameters.. try to find out whether we're running GNU getopt
getoptbrand="$(getopt -V)"
# shellcheck disable=SC2086
if [ "${getoptbrand:0:6}" == "getopt" ]; then
# Detected GNU getopt that supports long options.
args=$(getopt -l version,verbose,quiet,help,all,target:,payloads:,cpus:,silent,junit,config,loglevel:,remove,prefix:,update,scan-build,ccache,blobs,clang,clean,outdir:,chromeos,xmlfile:,kconfig:,dir:,root:,recursive,checksum:,timeless -o Vvqhat:p:c:sJCl:rP:uyBLzo:xX:K:d:R:I -- "$@") || exit 1
eval set -- $args
retval=$?
else
# Detected non-GNU getopt
args=$(getopt Vvqhat:p:c:sJCl:rP:uyBLzo:xX:K:d:R:I "$@")
set -- $args
retval=$?
fi
if [ $retval != 0 ]; then
myhelp
exit 1
fi
chromeos=false
clean_work=false
verboseopt='V=0'
customizing=""
configoptions=""
# testclass needs to be undefined if not used for variable expansion to work
unset testclass
while true ; do
case "$1" in
-J|--junit) shift; mode=junit; rm -f "$XMLFILE" ;;
-t|--target) shift; target="$1"; shift;;
-a|--all) shift; buildall=true;;
-d|--dir) shift; configdir="$1"; shift;;
-r|--remove) shift; remove=true;;
-v|--verbose) shift; verbose=true; verboseopt='V=1';;
-q|--quiet) shift; quiet=true;;
-V|--version) shift; myversion; exit 0;;
-h|--help) shift; myversion; myhelp; exit 0;;
-p|--payloads) shift; payloads="$1"; shift;;
-R|--root) shift; ROOT="$1"; shift;;
-c|--cpus) shift
export MAKEFLAGS="-j $1"
cpus=$1
test "$MAKEFLAGS" == "-j max" && export MAKEFLAGS="-j" && cpuconfig=" in parallel"
test "$1" == "1" && cpuconfig=" on 1 cpu"
expr "$1" : '-\?[0-9]\+$' > /dev/null && test "0$1" -gt 1 && cpuconfig=" on $1 cpus in parallel"
shift;;
# obsolete option
-s|--silent) shift;;
--scan-build) shift
scanbuild=true
customizing="${customizing}, scan-build"
;;
-y|--ccache) shift
customizing="${customizing}, ccache"
configoptions="${configoptions}CONFIG_CCACHE=y\n"
;;
-C|--config) shift; configureonly=1;;
-l|--loglevel) shift
customizing="${customizing}, loglevel $1"
configoptions="${configoptions}CONFIG_DEFAULT_CONSOLE_LOGLEVEL_$1=y\n"
configoptions="${configoptions}CONFIG_DEFAULT_CONSOLE_LOGLEVEL=$1\n"
shift;;
-u|--update) shift
customizing="${customizing}, update"
configoptions="${configoptions}CONFIG_UPDATE_IMAGE=y\n"
;;
-P|--prefix) shift
customizing="${customizing}, cbfs prefix $1"
configoptions="${configoptions}CONFIG_CBFS_PREFIX=\"$1\""
shift;;
-B|--blobs) shift
customizing="${customizing}, blobs"
configoptions="${configoptions}CONFIG_USE_BLOBS=y\n"
;;
-L|--clang) shift
customizing="${customizing}, clang"
configoptions="${configoptions}CONFIG_COMPILER_LLVM_CLANG=y\n# CONFIG_COMPILER_GCC is not set\n"
;;
-z|--clean) shift
customizing="${customizing}, clean"
clean_work=true
;;
-o|--outdir) shift
TARGET=$1; shift
;;
-x|--chromeos) shift
chromeos=true
testclass=chromeos
customizing="${customizing}, chrome os"
configoptions="${configoptions}CONFIG_CHROMEOS=y\n"
;;
-X|--xmlfile) shift; XMLFILE=$1; REAL_XMLFILE=$1; shift;;
-I|--recursive) shift; recursive=true;;
-K|--kconfig) shift
testclass="$(basename "$1" | tr '.' '_' )"
customizing="${customizing}, $1 config"
configoptions="$(cat "$1")${configoptions}\n"
shift;;
--checksum) shift; checksum_file="$1"; shift;;
--timeless) shift; TIMELESS=1;;
--) shift; break;;
-*) printf "Invalid option '%s'\n\n" "$1"; myhelp; exit 1;;
*) break;;
esac
done
if [ -n "$1" ]; then
printf "Invalid option '%s'\n\n" "$1"; myhelp; exit 1;
fi
if [ -z "$TARGET" ] || [ "$TARGET" = "/" ]; then
echo "Please specify a valid, non-root build directory."
exit 1
fi
customizing=$(echo "$customizing" | cut -c3-)
if [ "$customizing" = "" ]; then
customizing="default configuration"
fi
FAILED_BOARDS="${COREBOOT_BUILD_DIR:-${TOP}/coreboot-builds}/failed_boards"
PASSED_BOARDS="${COREBOOT_BUILD_DIR:-${TOP}/coreboot-builds}/passing_boards"
if [ "$recursive" = "false" ]; then
rm -f "$FAILED_BOARDS" "$PASSED_BOARDS"
fi
USE_XARGS=0
if [ "$cpus" != "1" ]; then
# Limit to 32 parallel builds for now.
# Thrashing all caches because we run
# 160 abuilds in parallel is no fun.
if [ "$cpus" = "max" ]; then
cpus=32
fi
# Test if xargs supports the non-standard -P flag
# FIXME: disabled until we managed to eliminate all the make(1) quirks
echo | xargs -P ${cpus:-0} -n 1 echo 2>/dev/null >/dev/null && USE_XARGS=1
fi
if [ "$USE_XARGS" = "0" ]; then
test "$MAKEFLAGS" == "" && test "$cpus" != "" && export MAKEFLAGS="-j $cpus"
build_targets()
{
local targets=${*-$(get_mainboards)}
for MAINBOARD in $targets; do
build_target "${MAINBOARD}"
done
}
else
build_targets()
{
local ABSPATH
local stime
local etime
local num_targets
local cpus_per_target
local targets=${*-$(get_mainboards)}
# seed shared utils
TMPCFG=$(mktemp)
printf "%s" "$configoptions" > "$TMPCFG"
$MAKE -j "$cpus" DOTCONFIG="$TMPCFG" obj="$TARGET/temp" objutil="$TARGET/sharedutils" allnoconfig
printf "%s" "$configoptions" >> "$TMPCFG"
yes "" 2>/dev/null | $MAKE -j "$cpus" DOTCONFIG="$TMPCFG" obj="$TARGET/temp" objutil="$TARGET/sharedutils" oldconfig 2>/dev/null |head > /dev/null
BUILDPREFIX=
if [ "$scanbuild" = "true" ]; then
scanbuild_out=$TARGET/sharedutils-scanbuild
rm -rf "${scanbuild_out}"
BUILDPREFIX="scan-build -o ${scanbuild_out}tmp"
fi
mkdir -p "$TARGET/abuild"
ABSPATH="$(cd "$TARGET/abuild" && pwd)"
local XMLFILE="$ABSPATH/__util.xml"
rm -f "${XMLFILE}"
stime=$(perl -e 'print time();' 2>/dev/null || date +%s)
$BUILDPREFIX $MAKE -j "$cpus" DOTCONFIG="$TMPCFG" obj="$TARGET/temp" objutil="$TARGET/sharedutils" tools > "$TARGET/sharedutils/make.log" 2>&1
local ret=$?
etime=$(perl -e 'print time();' 2>/dev/null || date +%s)
local duration=$(( etime - stime ))
junit " <testcase classname='util' name='all' time='$duration' >"
if [ $ret -eq 0 ]; then
junit "<system-out>"
junitfile "$TARGET/sharedutils/make.log"
junit "</system-out>"
junit "</testcase>"
else
junit "<failure type='BuildFailed'>"
junitfile "$TARGET/sharedutils/make.log"
junit "</failure>"
junit "</testcase>"
echo "Shared Utilities - Log: $TARGET/sharedutils/make.log" >> "$FAILED_BOARDS"
return
fi
if [ "$scanbuild" = "true" ]; then
mv "${scanbuild_out}tmp/"* "${scanbuild_out}"
rmdir "${scanbuild_out}tmp"
fi
rm -rf "$TARGET/temp" "$TMPCFG"
num_targets=$(wc -w <<<"$targets")
cpus_per_target=$(((${cpus:-1} + num_targets - 1) / num_targets))
echo "$targets" | xargs -P ${cpus:-0} -n 1 "$0" "${cmdline[@]}" -I -c "$cpus_per_target" -t
}
fi
debug "ROOT=$ROOT"
junit '<?xml version="1.0" encoding="utf-8"?>'
junit '<testsuite>'
if [ "$target" != "" ]; then
# build a single board
MAINBOARD=$(normalize_target "${target}")
if [ -z "${MAINBOARD}" ]; then
printf "No such target: %s\n" "$target"
exit 1
fi
build_srcdir="$(mainboard_directory "${MAINBOARD}")"
if [ "$(echo "${MAINBOARD}" | wc -w)" -gt 1 ]; then
build_targets "${MAINBOARD}"
elif [ ! -r "$ROOT/src/mainboard/${build_srcdir}" ]; then
echo "No such target: ${MAINBOARD}"
exit 1
else
build_target "${MAINBOARD}"
test "$mode" != "text" && \
test -f "$TARGET/abuild/${MAINBOARD}.xml" && \
cat "$TARGET/abuild/${MAINBOARD}.xml" >> "$REAL_XMLFILE"
XMLFILE=$REAL_XMLFILE
fi
else
build_targets
rm -f "$REAL_XMLFILE"
XMLFILE="$REAL_XMLFILE"
junit '<?xml version="1.0" encoding="utf-8"?>'
junit '<testsuite>'
if [ "$mode" != "text" ]; then
for xmlfile in $TARGET/abuild/*_*.xml; do
cat "$xmlfile" >> "$REAL_XMLFILE"
done
fi
XMLFILE=$REAL_XMLFILE
fi
junit '</testsuite>'
if [ "$recursive" = "false" ]; then
# Print the list of failed configurations
if [ -f "$FAILED_BOARDS" ]; then
printf "%s configuration(s) failed:\n" "$( wc -l < "$FAILED_BOARDS" )"
cat "$FAILED_BOARDS"
echo
else
printf "All %s tested configurations passed.\n" "$( wc -l < "$PASSED_BOARDS" )"
fi
fi
exit $failed