abuild: Build saved config files

Update abuild to allow for building saved miniconfig files.

If one or more config files exist for a platform under
coreboot/configs, they will be built instead of the automatically
generated default config.

The config filename needs to start with "config.$VENDOR_$BOARD" to be
picked up by the abuild script.

- Update to version 0.10.0
- Add -d parameter to specify the saved config file directory
- Break 2nd half of create_config function into update_config
to set the payload for saved config files.
- Unset new payload Kconfig options that could be set in a saved
config file.
- Update a bunch of MAINBOARD variable names to BUILD_NAME since
the build name isn't necessarily the same as the mainboard name.
- Split build_target into two functions - build_target and
build_config because one mainboard can now build multiple
configurations.
- Update remove target and call it directly from build_target()
instead of from build_targets()

Change-Id: I1a276d3e507b178f7dcd9dc125fa9c59f1ab47bd
Signed-off-by: Martin Roth <martinroth@google.com>
Reviewed-on: https://review.coreboot.org/17590
Tested-by: build bot (Jenkins)
Reviewed-by: Paul Menzel <paulepanter@users.sourceforge.net>
Reviewed-by: Patrick Georgi <pgeorgi@google.com>
This commit is contained in:
Martin Roth 2016-11-23 18:47:53 -07:00
parent c01ff74a6a
commit 26174c97fe
1 changed files with 196 additions and 85 deletions

View File

@ -16,8 +16,8 @@
#set -x # Turn echo on....
ABUILD_DATE="Oct 13, 2015"
ABUILD_VERSION="0.9.4"
ABUILD_DATE="Nov 23, 2016"
ABUILD_VERSION="0.10.0"
TOP=$PWD
@ -51,6 +51,9 @@ failed=0
# default: single CPU build
cpus=1
# change with -d <directory>
configdir="$TOP/configs"
# 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
@ -173,72 +176,114 @@ function normalize_target
function create_config
{
local MAINBOARD=$1
local BUILD_NAME=$1
local build_dir=$2
local build_dir=$TARGET/${MAINBOARD}
local config_file=${build_dir}/config.build
local board_srcdir=$(mainboard_directory ${MAINBOARD})
# 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
local PAYLOAD=`sh $payloads/payload.sh $MAINBOARD`
if [ $? -gt 0 ]; then
echo "problem with payload"
exit 1
fi
if [ "$quiet" == "false" ]; then printf "Using payload $PAYLOAD\n"; fi
elif [ "$payloads" = "none" ]; then
local PAYLOAD=none
fi
local board_srcdir=$(mainboard_directory ${BUILD_NAME})
mkdir -p ${build_dir}
mkdir -p $TARGET/sharedutils
if [ "$quiet" == "false" ]; then printf " Creating config file for $MAINBOARD... \n"; fi
printf "CONFIG_VENDOR_$(mainboard_vendor ${MAINBOARD})=y\n" > ${config_file}
printf "CONFIG_BOARD_${MAINBOARD}=y\n" >> ${config_file}
if [ "$quiet" == "false" ]; then printf " Creating config file for $BUILD_NAME... \n"; fi
printf "CONFIG_VENDOR_$(mainboard_vendor ${BUILD_NAME})=y\n" > ${config_file}
printf "CONFIG_BOARD_${BUILD_NAME}=y\n" >> ${config_file}
grep "select[\t ]*ARCH" ${ROOT}/src/mainboard/${board_srcdir}/Kconfig | \
sed "s,^.*\(ARCH_.*\)[^A-Z0-9_]*,CONFIG_\1=y," >> ${config_file}
printf "CONFIG_MAINBOARD_DIR=\"${board_srcdir}\"\n" >> ${config_file}
if [ "$PAYLOAD" = "none" ]; then
printf "CONFIG_PAYLOAD_NONE=y\n" >> ${config_file}
elif [ "$PAYLOAD" != "/dev/null" ]; then
printf "# CONFIG_PAYLOAD_NONE is not set\n" >> ${config_file}
printf "# CONFIG_PAYLOAD_SEABIOS is not set\n" >> ${config_file}
printf "CONFIG_PAYLOAD_ELF=y\n" >> ${config_file}
printf "CONFIG_PAYLOAD_FILE=\"$PAYLOAD\"\n" >> ${config_file}
fi
if [ "$quiet" == "false" ]; then printf " $MAINBOARD ($customizing)\n"; fi
printf "$configoptions" >> ${config_file}
update_config "$BUILD_NAME" "$build_dir" "$config_file"
yes "" 2>/dev/null | $MAKE oldconfig $silent DOTCONFIG=${config_file} obj=${build_dir} objutil=$TARGET/sharedutils &> ${build_dir}/config.log
ret=$?
if [ $ret -eq 0 ]; then
if [ "$quiet" == "false" ]; then printf " $MAINBOARD config created.\n"; fi
if [ "$quiet" == "false" ]; then printf " $BUILD_NAME config created.\n"; fi
return 0
else
# Does this ever happen?
if [ "$quiet" == "false" ]; then printf "$MAINBOARD config creation FAILED!\nLog excerpt:\n"; fi
if [ "$quiet" == "false" ]; then printf "$BUILD_NAME config creation FAILED!\nLog excerpt:\n"; 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 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
local PAYLOAD=$(sh "$payloads/payload.sh" "$BUILD_NAME")
if [ $? -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
local 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
echo "$configoptions" >> "${config_file}"
# shellcheck disable=SC2086
$MAKE olddefconfig $silent "DOTCONFIG=${config_file}" "obj=${build_dir}" "objutil=$TARGET/sharedutils" &> "${build_dir}/config.log"
if [ $? -eq 0 ]; then
$MAKE savedefconfig $silent DEFCONFIG="${defconfig_file}" DOTCONFIG="${config_file}" obj="${build_dir}" objutil="$TARGET/sharedutils" &> "${build_dir}/config.log"
return $?
else
return 1
fi
}
function create_buildenv
{
local MAINBOARD=$1
local BUILD_NAME=$1
local build_dir=$2
local config_file=$3
create_config $MAINBOARD
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
ret=$?
# Allow simple "make" in the target directory
local MAKEFILE=$TARGET/${MAINBOARD}/Makefile
local MAKEFILE=$TARGET/${BUILD_NAME}/Makefile
echo "# autogenerated" > $MAKEFILE
echo "TOP=$ROOT" >> $MAKEFILE
echo "BUILD=$TARGET" >> $MAKEFILE
@ -255,128 +300,194 @@ function create_buildenv
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 MAINBOARD=$1
local BUILD_NAME=$1
if [ "$quiet" == "false" ]; then printf " Compiling $MAINBOARD image$cpuconfig...\n"; fi
CURR=$( pwd )
#stime=`perl -e 'print time();' 2>/dev/null || date +%s`
build_dir=$TARGET/${MAINBOARD}
eval $BUILDPREFIX $MAKE $silent DOTCONFIG=${build_dir}/config.build obj=${build_dir} objutil=$TARGET/sharedutils \
&> ${build_dir}/make.log
ret=$?
cp .xcompile ${build_dir}/xcompile.build
cd $TARGET/${MAINBOARD}
cd ${build_dir}
etime=`perl -e 'print time();' 2>/dev/null || date +%s`
duration=$(( $etime - $stime ))
junit " <testcase classname='board${testclass/#/.}' name='$MAINBOARD' time='$duration' >"
junit " <testcase classname='board${testclass/#/.}' name='$BUILD_NAME' time='$duration' >"
if [ $ret -eq 0 ]; then
junit "<system-out>"
junitfile make.log
junit "</system-out>"
printf "ok\n" > compile.status
printf "$MAINBOARD built successfully. (took ${duration}s)\n"
printf "$BUILD_NAME built successfully. (took ${duration}s)\n"
else
ret=1
junit "<failure type='BuildFailed'>"
junitfile make.log
junit "</failure>"
printf "failed\n" > compile.status
printf "$MAINBOARD build FAILED after ${duration}s!\nLog excerpt:\n"
printf "$BUILD_NAME build FAILED after ${duration}s!\nLog excerpt:\n"
tail -n $CONTEXT make.log 2> /dev/null || tail -$CONTEXT make.log
failed=1
fi
cd $CURR
if [ $clean_work = "true" ]; then
rm -rf $TARGET/${MAINBOARD}
rm -rf ${build_dir}
fi
return $ret
}
function build_target
function build_config
{
local MAINBOARD=$1
local board_srcdir=$(mainboard_directory ${MAINBOARD})
local build_dir=$2
local BUILD_NAME=$3
local config_file=$4
if [ "`cat $TARGET/${MAINBOARD}/compile.status 2>/dev/null`" = "ok" -a \
local board_srcdir=$(mainboard_directory "${MAINBOARD}")
if [ "$(cat "${build_dir}/compile.status" 2>/dev/null)" = "ok" -a \
"$buildall" = "false" ]; then
printf "Skipping $MAINBOARD; (already successful)\n"
echo "Skipping $BUILD_NAME; (already successful)"
return
fi
HOSTCC='gcc'
export HOSTCC='gcc'
if [ $chromeos = true -a `grep -c "^[[:space:]]*select[[:space:]]*MAINBOARD_HAS_CHROMEOS\>" ${ROOT}/src/mainboard/${board_srcdir}/Kconfig` -eq 0 ]; then
echo "${MAINBOARD} doesn't support Chrome OS, skipping."
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 "${MAINBOARD} disabled:"
cat src/mainboard/${board_srcdir}/abuild.disabled
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 printf "Building $MAINBOARD\n"; fi
mkdir -p $TARGET/${MAINBOARD} $TARGET/abuild
ABSPATH=`cd $TARGET/abuild; pwd`
XMLFILE=$ABSPATH/${MAINBOARD}.xml
rm -f ${XMLFILE}
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 "<failure type='BuildFailed'>"
junitfile "$build_dir/config.log"
junit "</failure>"
printf "failed\n" > compile.status
printf "$BUILD_NAME build configuration FAILED!\nLog excerpt:\n"
tail -n $CONTEXT "$build_dir/config.log" 2> /dev/null || tail -$CONTEXT "$build_dir/config.log"
junit "</testcase>"
return
fi
stime=`perl -e 'print time();' 2>/dev/null || date +%s`
create_buildenv $MAINBOARD
required_arches=`egrep "^CONFIG_ARCH_(BOOTBLOCK|R.MSTAGE|VERSTAGE)" $TARGET/${MAINBOARD}/config.build | \
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 '`
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 $MAINBOARD because we're missing compilers for ($missing_arches)\n"
printf "skipping $BUILD_NAME because we're missing compilers for ($missing_arches)\n"
return
fi
if [ $? -eq 0 -a $configureonly -eq 0 ]; then
BUILDPREFIX=
if [ "$scanbuild" = "true" ]; then
scanbuild_out=$TARGET/${MAINBOARD}-scanbuild
scanbuild_out=$TARGET/${BUILD_NAME}-scanbuild
rm -rf ${scanbuild_out}
BUILDPREFIX="scan-build -o ${scanbuild_out}tmp"
fi
compile_target ${MAINBOARD}
compile_target ${BUILD_NAME}
if [ "$scanbuild" = "true" ]; then
mv ${scanbuild_out}tmp/* ${scanbuild_out}
rmdir ${scanbuild_out}tmp
fi
fi
# Not calculated here because we still print it in compile_target
#etime=`perl -e 'print time();' 2>/dev/null || date +%s`
#duration=$(( $etime - $stime ))
junit "</testcase>"
}
# One target may build several configs
function build_target
{
local MAINBOARD=$1
local 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 0
return
fi
local MAINBOARD=$1
local BUILD_NAME=$1
# Save the generated coreboot.rom file of each board.
if [ -r "$TARGET/${MAINBOARD}/coreboot.rom" ]; then
cp $TARGET/${MAINBOARD}/coreboot.rom \
${MAINBOARD}_coreboot.rom
if [ -r "$TARGET/${BUILD_NAME}/coreboot.rom" ]; then
cp "$TARGET/${BUILD_NAME}/coreboot.rom" \
"${BUILD_NAME}_coreboot.rom"
fi
printf "Removing build dir for board $MAINBOARD...\n"
rm -rf $TARGET/${MAINBOARD}
echo "Removing build dir for $BUILD_NAME..."
rm -rf "$TARGET/${BUILD_NAME}"
return 0
return
}
function myhelp
@ -391,6 +502,7 @@ Options:\n"
[-q|--quiet] print fewer messages
[-a|--all] build previously succeeded ports as well
[-r|--remove] remove output dir after build
[-d|--dir <dir>] directory containing config files
[-t|--target <vendor/board>] attempt to build target vendor/board only
[-p|--payloads <dir>] use payloads in <dir> to build images
[-V|--version] print version number and exit
@ -457,11 +569,11 @@ cmdline="$* -c 1"
getoptbrand="`getopt -V`"
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: -o Vvqhat:p:c:sJCl:rP:uyBLzo:xX:K: -- "$@"` || exit 1
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: -o Vvqhat:p:c:sJCl:rP:uyBLzo:xX:K:d: -- "$@"` || exit 1
eval set -- $args
else
# Detected non-GNU getopt
args=`getopt Vvqhat:p:c:sJCl:rP:uyBLzo:xX:K: $*`
args=`getopt Vvqhat:p:c:sJCl:rP:uyBLzo:xX:K:d: $*`
set -- $args
fi
@ -481,6 +593,7 @@ while true ; do
-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; silent='V=1';;
-q|--quiet) shift; quiet=true;;
@ -580,7 +693,6 @@ build_targets()
local targets=${*-$(get_mainboards)}
for MAINBOARD in $targets; do
build_target ${MAINBOARD}
remove_target ${MAINBOARD}
done
}
else
@ -657,7 +769,6 @@ if [ "$target" != "" ]; then
exit 1
else
build_target ${MAINBOARD}
remove_target ${MAINBOARD}
test "$mode" != "text" && \
test -f $TARGET/abuild/${MAINBOARD}.xml && \
cat $TARGET/abuild/${MAINBOARD}.xml >> $REAL_XMLFILE