5 # This script builds coreboot images for all available targets.
7 # This file is subject to the terms and conditions of the GNU General
8 # Public License. See the file COPYING in the main directory of this
9 # archive for more details.
12 #set -x # Turn echo on....
14 ABUILD_DATE
="Nov 18, 2023"
15 ABUILD_VERSION
="0.11.03"
19 # Where shall we place all the build trees?
20 TARGET_DEFAULT
=coreboot-builds
21 TARGET
=${COREBOOT_BUILD_DIR:-${TARGET_DEFAULT}}
22 XML_DEFAULT
="$TOP/abuild.xml"
23 XMLFILE
="${XML_DEFAULT}"
24 REAL_XMLFILE
="${XML_DEFAULT}"
26 # Name associated with a run of abuild
27 TESTRUN_DEFAULT
=default
28 TESTRUN
="${TESTRUN_DEFAULT}"
30 export KCONFIG_OVERWRITECONFIG
=1
32 # path to payload. Should be more generic
35 # get path to coreboot XGCC if it's not already set
36 if [ -z "$XGCCPATH" ]; then
37 XGCCPATH
="${TOP}/util/crossgcc/xgcc/bin/"
40 # Add XGCC to the path.
41 if [ -d "$XGCCPATH" ] && [[ ":$PATH:" != *":$XGCCPATH:"* ]]; then
42 PATH
="$XGCCPATH:$PATH"
45 # Lines of error context to be printed in FAILURE case
51 # Did any board fail to build?
54 # Exit with a non-zero errorlevel on failure
57 # default: don't save checksums
60 # default: single CPU build
63 # change with -d <directory>
64 configdir
="$TOP/configs"
69 # One might want to adjust these in case of cross compiling
70 for i
in make gmake gnumake nonexistent_make
; do
71 $i --version 2>/dev
/null |
grep "GNU Make" >/dev
/null
&& break
73 if [ "$i" = "nonexistent_make" ]; then
74 echo No GNU Make found.
79 # this can be changed to junit by -J
82 # quiet mode: only print pass, failure, and 'skipped' messages
85 # clang mode enabled by -sb option.
88 # Mark whether abuild was called recursively
91 # Skip builds with this Kconfig value set
94 # Skip builds with this Kconfig value notset
98 ts_exec_shell
=$
(printf "%(%s)T" -2)
99 ts_basetime_str
=$
(date -u --date=@
${ts_exec_shell})
105 printf "\n%s: execution interrupted manually.\n" "$0"
106 if [ "$mode" == "junit" ]; then
107 printf "%s: deleting incomplete xml output file.\n" "$0"
114 test "$verbose" == "true" && echo "$*"
119 test "$mode" == "junit" && echo "$*" >> "$XMLFILE"
125 test "$mode" == "junit" && {
132 # Return mainboard descriptors.
133 # By default all mainboards are listed, but when passing a two-level path
134 # below src/mainboard, such as emulation/qemu-i440fx, or emulation/*, it
135 # returns all board descriptors in that hierarchy.
136 function get_mainboards
138 local search_space
=${1-*/*}
139 # shellcheck disable=SC2086
140 grep -h "^[[:space:]]*config\>[[:space:]]*\<BOARD_" \
141 ${ROOT}/src
/mainboard
/${search_space}/Kconfig.name
2>/dev
/null | \
142 sed "s,^.*\<BOARD_\([A-Z0-9_]*\)\>.*$,\1,"
145 # Given a mainboard descriptor, return its directory below src/mainboard
146 function mainboard_directory
150 # shellcheck disable=SC2086
151 grep -l "^[[:space:]]*config\>[[:space:]]*\<BOARD_${MAINBOARD}\>" \
152 ${ROOT}/src
/mainboard
/*/*/Kconfig.name | \
153 sed "s:^$ROOT/src/mainboard/\(.*\)/Kconfig.name$:\1:"
156 # Given a mainboard descriptor, return its vendor (CONFIG_VENDOR_*)
157 function mainboard_vendor
162 # shellcheck disable=SC2086
164 grep -l "^[[:space:]]*config\>[[:space:]]*\<BOARD_${MAINBOARD}\>" \
165 ${ROOT}/src
/mainboard
/*/*/Kconfig.name | \
166 sed "s:^\(${ROOT}/src/mainboard/.*\)/.*/\(Kconfig.name\)$:\1/\2:" )
167 if [ ! -f "$kconfig_file" ]; then
170 grep "^[[:space:]]*config\>[[:space:]]*\<VENDOR_" "$kconfig_file" | \
171 sed "s,^.*\<VENDOR_\([A-Z0-9_]*\)\>.*$,\1,"
174 # Accepts directory names (eg. emulation/qemu-i440fx) and mainboard
175 # descriptors (eg. EMULATION_QEMU_X86_I440F} and returns the latter
177 # If a directory contains multiple boards, returns them all.
178 function normalize_target
180 # TODO: Change 'targets' variable to an array
184 VARIANT_UC
=$
(echo "${variant}" |
tr '[:lower:]' '[:upper:]' |
tr '-' '_')
186 targets
=$
(get_mainboards
"$1")
187 if [ -n "$targets" ]; then
188 # shellcheck disable=SC2086
189 targets
="$(grep "${VARIANT_UC}\$
" <<< ${targets})"
194 targets
=$
(echo "$1" |
tr ',' ' ')
195 for i
in $targets; do
196 if [ -n "$(mainboard_directory "$i")" ]; then
199 echo "$i is not a valid target" >&2
205 # shellcheck disable=SC2129
206 function create_config
212 local config_file
="${build_dir}/config.build"
213 board_srcdir
="$(mainboard_directory "${BUILD_NAME}")"
215 mkdir
-p "${build_dir}"
216 mkdir
-p "$TARGET/sharedutils"
218 if [ "$quiet" == "false" ]; then echo " Creating config file for $BUILD_NAME..."; fi
219 echo "CONFIG_VENDOR_$(mainboard_vendor "${BUILD_NAME}")=y" > "${config_file}"
220 echo "CONFIG_BOARD_${BUILD_NAME}=y" >> "${config_file}"
221 grep "select[\t ]*ARCH" "${ROOT}/src/mainboard/${board_srcdir}/Kconfig" | \
222 sed "s,^.*\(ARCH_.*\)[^A-Z0-9_]*,CONFIG_\1=y," >> "${config_file}"
223 echo "CONFIG_MAINBOARD_DIR=\"${board_srcdir}\"" >> "${config_file}"
225 update_config
"$BUILD_NAME" "$build_dir" "$config_file"
228 if [ $ret -eq 0 ]; then
229 if [ "$quiet" == "false" ]; then echo " $BUILD_NAME config created."; fi
232 # Does this ever happen?
233 if [ "$quiet" == "false" ]; then printf "%s config creation FAILED!\nLog excerpt:\n" "$BUILD_NAME"; fi
234 tail -n $CONTEXT "$build_dir/config.log" 2> /dev
/null ||
tail -$CONTEXT "$build_dir/config.log"
239 function update_config
247 defconfig_file
=${build_dir}/config.$
(echo "${BUILD_NAME}" |
tr '[:upper:]' '[:lower:]').default
249 # get a working payload for the board if we have one.
250 # the --payload option expects a directory containing
251 # a shell script payload.sh
252 # Usage: payload.sh [BOARD]
253 # the script returns an absolute path to the payload binary.
255 if [ -f "$payloads/payload.sh" ]; then
256 PAYLOAD
=$
(sh
"$payloads/payload.sh" "$BUILD_NAME")
258 if [ $PAYLOAD_OK -gt 0 ]; then
259 echo "problem with payload"
262 if [ "$quiet" == "false" ]; then printf "Using payload %s\n" "$PAYLOAD"; fi
263 elif [ "$payloads" = "none" ]; then
267 if [ "$PAYLOAD" = "none" ]; then
269 echo "CONFIG_PAYLOAD_NONE=y"
270 echo "# CONFIG_PAYLOAD_ELF is not set"
271 } >> "${config_file}"
272 elif [ "$PAYLOAD" != "/dev/null" ]; then
274 echo "# CONFIG_PAYLOAD_NONE is not set"
275 echo "CONFIG_PAYLOAD_ELF=y"
276 echo "CONFIG_PAYLOAD_FILE=\"$PAYLOAD\""
277 } >> "${config_file}"
279 # Disable all other payload config options
281 echo "# CONFIG_PAYLOAD_SEABIOS is not set"
282 echo "# CONFIG_PAYLOAD_FILO is not set"
283 echo "# CONFIG_PAYLOAD_GRUB2 is not set"
284 echo "# CONFIG_PAYLOAD_DEPTHCHARGE is not set"
285 echo "# CONFIG_PAYLOAD_LINUXBOOT is not set"
286 echo "# CONFIG_PAYLOAD_UBOOT is not set"
287 echo "# CONFIG_PAYLOAD_EDK2 is not set"
288 echo "# CONFIG_PXE is not set"
289 echo "# CONFIG_BUILD_IPXE is not set"
290 echo "# CONFIG_MEMTEST_SECONDARY_PAYLOAD is not set"
291 echo "# CONFIG_COREINFO_SECONDARY_PAYLOAD is not set"
292 echo "# CONFIG_NVRAMCUI_SECONDARY_PAYLOAD is not set"
293 echo "# CONFIG_TINT_SECONDARY_PAYLOAD is not set"
294 } >> "${config_file}"
296 if [ "$quiet" == "false" ]; then echo " $MAINBOARD ($customizing)"; fi
297 # shellcheck disable=SC2059
298 printf "$configoptions" >> "${config_file}"
300 $MAKE olddefconfig
"$verboseopt" "DOTCONFIG=${config_file}" "obj=${build_dir}" "objutil=$TARGET/sharedutils" &> "${build_dir}/config.log" ; \
302 if [ $CONFIG_OK -eq 0 ]; then
303 $MAKE savedefconfig
"$verboseopt" DEFCONFIG
="${defconfig_file}" DOTCONFIG="${config_file}" obj="${build_dir}" objutil="$TARGET/sharedutils" &>> "${build_dir}/config.log"
310 # shellcheck disable=SC2129
311 function create_buildenv
317 if [ -z "$config_file" ]; then
318 create_config
"$BUILD_NAME" "$build_dir"
320 local new_config_file
="${build_dir}/config.build"
321 cp "$config_file" "$new_config_file"
322 update_config
"$BUILD_NAME" "$build_dir" "$new_config_file"
326 # Allow simple "make" in the target directory
327 local MAKEFILE
=$TARGET/${BUILD_NAME}/Makefile
328 echo "# autogenerated" > "$MAKEFILE"
329 echo "TOP=$ROOT" >> "$MAKEFILE"
330 echo "BUILD=$TARGET" >> "$MAKEFILE"
331 echo "OBJ=\$(BUILD)/${MAINBOARD}" >> "$MAKEFILE"
332 echo "OBJUTIL=\$(BUILD)/sharedutils" >> "$MAKEFILE"
333 echo "all:" >> "$MAKEFILE"
334 echo " @cp -a config.h config.h.bak" >> "$MAKEFILE"
335 echo " @cd \$(TOP); \$(MAKE) olddefconfig DOTCONFIG=\$(OBJ)/config.build objutil=\$(OBJUTIL) obj=\$(OBJ)" >> "$MAKEFILE"
336 echo " @tail -n+6 config.h > config.new; tail -n+6 config.h.bak > config.old" >> "$MAKEFILE"
337 echo " @cmp -s config.new config.old && cp -a config.h.bak config.h || echo \"Config file changed\"" >> "$MAKEFILE"
338 echo " @rm config.h.bak config.new config.old" >> "$MAKEFILE"
339 echo " @cd \$(TOP); \$(MAKE) DOTCONFIG=\$(OBJ)/config.build objutil=\$(OBJUTIL) obj=\$(OBJ)" >> "$MAKEFILE"
344 function check_config
348 local TEST_STRING
="$3"
351 local CONFIG_FILE
="$BUILD_DIR/config.build"
352 local CONFIG_LOG
="$BUILD_DIR/config.log"
354 if [ -z "$NEGATE" ]; then
355 if ! grep -q "$TEST_STRING" "$CONFIG_FILE"; then
356 echo "config file: $CONFIG_FILE has incorrect $TEST_TYPE"
357 echo "Error: Expected '$TEST_STRING' in config file." >> "$CONFIG_LOG"
361 if grep -q "$TEST_STRING" "$CONFIG_FILE"; then
362 echo "config file: $CONFIG_FILE has incorrect $TEST_TYPE"
363 echo "Error: Expected not to see '$TEST_STRING' in config file." >> "$CONFIG_LOG"
371 # Counting microseconds since start of shell
372 function add_timestamp
374 local now
=${EPOCHREALTIME}
375 local seconds
=$
(echo $now | cut
-f 1 -d '.')
376 local usecs
=$
(echo $now | cut
-f 2 -d '.')
377 seconds
=$
(( seconds
- ts_exec_shell
))
378 usecs
=$
(( seconds
* 1000 * 1000 + 10#$usecs ))
382 function ts_delta_seconds
384 local delta
=$
(( ($2 - $1) / (1000 * 1000) ))
388 function ts_delta_string
394 delta
=$
(( ($2 - $1) / 1000 ))
395 ts_minutes
=$
(( delta
/ (60 * 1000) ))
396 delta
=$
(( delta
% (60 * 1000) ))
397 ts_seconds
=$
(( delta
/ 1000))
398 delta
=$
(( delta
% 1000 ))
400 if [ $ts_minutes -ne 0 ] ; then
401 printf "%d min %d sec" $ts_minutes $ts_seconds
403 printf "%d.%03d seconds" $ts_seconds $delta
407 function compile_target
411 if [ "$quiet" == "false" ]; then echo " Compiling $MAINBOARD image$cpuconfig..."; fi
415 ts_1
=$
(add_timestamp
)
416 eval "$BUILDPREFIX" "$MAKE" "$verboseopt" DOTCONFIG
="${build_dir}/config.build" obj
="${build_dir}" objutil
="$TARGET/sharedutils" BUILD_TIMELESS
=$TIMELESS \
417 &> "${build_dir}/make.log" ; \
419 ts_2
=$
(add_timestamp
)
421 cd "${build_dir}" ||
return $?
423 timestamps
="abuild.timestamps"
424 printf "Build started %s\n" "${ts_basetime_str}" > "${timestamps}"
425 printf "BASETIME_SECONDS %d\n" $ts_exec_shell >> "${timestamps}"
426 printf "TS_0 %d\n" $ts_0 >> "${timestamps}"
427 printf "TS_1 %d\n" $ts_1 >> "${timestamps}"
428 printf "TS_2 %d\n" $ts_2 >> "${timestamps}"
430 duration
=$
(ts_delta_seconds
$ts_0 $ts_2)
431 duration_str
=$
(ts_delta_string
$ts_0 $ts_2)
432 junit
" <testcase classname='${TESTRUN}${testclass/#/.}' name='$BUILD_NAME' time='$duration' >"
434 if [ $MAKE_FAILED -eq 0 ]; then
437 junit
"</system-out>"
438 printf "ok\n" > compile.status
439 printf "%s built successfully. (took %s)\n" "$BUILD_NAME" "${duration_str}"
440 echo "$BUILD_NAME" >> "$PASSED_BOARDS"
442 junit
"<failure type='BuildFailed'>"
445 printf "failed\n" > compile.status
446 printf "%s build FAILED after %s!\nLog excerpt:\n" "$BUILD_NAME" "${duration_str}"
447 tail -n $CONTEXT make.log
2> /dev
/null ||
tail -$CONTEXT make.log
448 if [ "$clean_work" = "true" ]; then
449 echo "$BUILD_NAME" >> "$FAILED_BOARDS"
451 echo "$BUILD_NAME - Log: ${build_dir}/make.log" >> "$FAILED_BOARDS"
455 cd "$CURR" ||
return $?
456 if [ -n "$checksum_file" ]; then
457 sha256sum
"${build_dir}/coreboot.rom" >> "${checksum_file}_platform"
458 sort "${build_dir}/config.h" |
grep CONFIG_
> "${build_dir}/config.h.sorted"
459 sha256sum
"${build_dir}/config.h.sorted" >> "${checksum_file}_config"
462 stats_files
="${build_dir}/${timestamps}"
463 if [ -f ${build_dir}/ccache.stats
]; then
464 stats_files
="${stats_files} ${build_dir}/ccache.stats"
466 flock
-F -w 0.1 $TARGET/.statslock
tar -rf ${stats_archive} ${stats_files} 2> /dev
/null
468 if [ "$clean_work" = "true" ]; then
469 rm -rf "${build_dir}"
471 if [ "$clean_objs" = "true" ]; then
472 find ${build_dir} \
! \
( -name coreboot.rom
-o -name config.h
-o -name config.build
-o -name make.log \
) -type f
-exec rm {} +
473 find ${build_dir} -type d
-exec rmdir -p {} + 2>/dev
/null
478 function build_config
487 board_srcdir
=$
(mainboard_directory
"${MAINBOARD}")
489 if [ "$(cat "${build_dir}/compile.status
" 2>/dev/null)" = "ok" ] && \
490 [ "$buildall" = "false" ]; then
491 echo "Skipping $BUILD_NAME; (already successful)"
497 if [ "$chromeos" = true
] && [ "$(grep -c "^
[[:space
:]]*select[[:space
:]]*MAINBOARD_HAS_CHROMEOS\
>" "${ROOT}/src
/mainboard
/${board_srcdir}/Kconfig
")" -eq 0 ]; then
498 echo "${BUILD_NAME} doesn't support ChromeOS, skipping."
502 if [ "$quiet" == "false" ]; then echo "Building $BUILD_NAME"; fi
503 mkdir
-p "$TARGET/${BUILD_NAME}" "$TARGET/abuild"
504 ABSPATH
="$(cd "$TARGET/abuild
" && pwd)"
505 XMLFILE
="$ABSPATH/${BUILD_NAME}.xml"
508 ts_0
=$
(add_timestamp
)
510 create_buildenv
"$BUILD_NAME" "$build_dir" "$config_file"
511 local BUILDENV_CREATED
=$?
513 check_config
"$build_dir" "mainboard" "CONFIG_BOARD_${MAINBOARD}=y"
514 local MAINBOARD_OK
=$?
516 check_config
"$build_dir" "vendor" "CONFIG_VENDOR_$(mainboard_vendor "${MAINBOARD}")=y"
519 if [ "$chromeos" = false
]; then
520 # Skip this rule for configs created from templates that already
521 # come with CHROMEOS enabled.
522 grep -q "^CONFIG_CHROMEOS=y" ${config_file:-/dev/null} || \
523 check_config
"$build_dir" "ChromeOS" "CONFIG_CHROMEOS=y" negate
524 local FORCE_ENABLED_CROS
=$?
526 local FORCE_ENABLED_CROS
=0
529 if [ "$clang" = true
]; then
530 check_config
"$build_dir" "clang" "CONFIG_COMPILER_LLVM_CLANG=y"
531 if [ $?
-ne 0 ]; then
532 echo "${MAINBOARD} doesn't support clang, skipping."
537 if [ -n "${skipconfig_set}" ]; then
538 check_config
"${build_dir}" "config value" "CONFIG_${skipconfig_set}=y" negate
539 if [ $?
-ne 0 ]; then
540 echo "${MAINBOARD} has ${skipconfig_set} set. Skipping at user's request."
545 if [ -n "${skipconfig_unset}" ]; then
546 check_config
"${build_dir}" "config value" "CONFIG_${skipconfig_unset}=y"
547 if [ $?
-ne 0 ]; then
548 echo "${MAINBOARD} does not have ${skipconfig_unset} set. Skipping at user's request."
553 if [ $BUILDENV_CREATED -ne 0 ] ||
[ $MAINBOARD_OK -ne 0 ] ||
[ $VENDOR_OK -ne 0 ] ||
[ $FORCE_ENABLED_CROS -eq 1 ]; then
554 junit
" <testcase classname='${TESTRUN}${testclass/#/.}' name='$BUILD_NAME' >"
556 junit
"<failure type='BuildFailed'>"
557 junitfile
"$build_dir/config.log"
559 printf "failed\n" > compile.status
560 printf "%s build configuration FAILED!\nLog excerpt:\n" "$BUILD_NAME"
561 tail -n $CONTEXT "$build_dir/config.log" 2> /dev
/null ||
tail -$CONTEXT "$build_dir/config.log"
564 echo "$BUILD_NAME - Log: $build_dir/config.log" >> "$FAILED_BOARDS"
568 local required_arches
570 required_arches
=$
(grep -E "^CONFIG_ARCH_(BOOTBLOCK|R.MSTAGE|VERSTAGE)" "$TARGET/${BUILD_NAME}/config.build" | \
571 sed "s,^CONFIG_ARCH_[^_]*_\([^=]*\)=.*$,\1," |
sort -u |
tr 'A-Z\n\r' 'a-z ')
573 missing_arches
="$($MAKE --no-print-directory -f - \
574 REQUIRED_ARCHES="$required_arches" <<'EOF'
576 .PHONY: missing_arches
578 $(if $(XCOMPILE_COMPLETE),,$(error $(xcompile) is invalid.))
579 @echo $(foreach arch,$(REQUIRED_ARCHES),$(if $(filter $(arch),$(SUBARCH_SUPPORTED)),,$(arch)))
582 # shellcheck disable=SC2181
583 if [[ $?
-ne 0 ]]; then
584 echo "Calculating missing_arches failed" >&2
588 if [ -n "$missing_arches" ]; then
589 printf "skipping %s because we're missing compilers for (%s)\n" "$BUILD_NAME" "$missing_arches"
593 if [ $BUILDENV_CREATED -eq 0 ] && [ $configureonly -eq 0 ]; then
595 if [ "$scanbuild" = "true" ]; then
596 scanbuild_out
=$TARGET/${BUILD_NAME}-scanbuild
597 rm -rf "${scanbuild_out}"
598 BUILDPREFIX
="scan-build ${SCANBUILD_ARGS} -o ${scanbuild_out}tmp"
600 compile_target
"${BUILD_NAME}"
601 if [ "$scanbuild" = "true" ]; then
602 mv "${scanbuild_out}"tmp
/* "${scanbuild_out}"
603 rmdir "${scanbuild_out}tmp"
610 function record_mainboard
614 if test "$mode" != "text" && test -f "$TARGET/abuild/${log}.xml"; then
615 cat "$TARGET/abuild/${log}.xml" >> "$REAL_XMLFILE"
616 echo "$TARGET/abuild/${log}.xml written to $REAL_XMLFILE" >&2
618 echo "Warning: $TARGET/abuild/${log}.xml not found." >&2
622 # One target may build several configs
623 function build_target
627 MAINBOARD_LC
=$
(echo "$MAINBOARD" |
tr '[:upper:]' '[:lower:]')
629 # look for config files in the config directory that match the boardname
630 if [ -n "$( find "$configdir" -maxdepth 1 -name "config.
${MAINBOARD_LC}*" -print -quit )" ]; then
631 for config
in "$configdir/config.${MAINBOARD_LC}"*; do
632 BUILD_NAME
="${config##*/}"
633 BUILD_NAME
="${BUILD_NAME##config.}"
634 BUILD_NAME
=$
(echo "${BUILD_NAME}" |
tr '[:lower:]' '[:upper:]')
635 echo $BUILD_NAME $MAINBOARD
636 # If the file in configs/ results in the same build_name as the default config
637 # append a '_' to differentiate. Otherwise the default configuration would
638 # override the results.
639 if [ "${MAINBOARD}" = "${BUILD_NAME}" ]; then
640 BUILD_NAME
=${BUILD_NAME}"_"
642 echo "Building config $BUILD_NAME"
643 build_dir
=$TARGET/${BUILD_NAME}
644 build_config
"$MAINBOARD" "$build_dir" "$BUILD_NAME" "$config"
645 record_mainboard
"$BUILD_NAME"
646 remove_target
"$BUILD_NAME"
650 echo "Building board $MAINBOARD (using default config)"
651 build_dir
=$TARGET/${MAINBOARD}
652 build_config
"$MAINBOARD" "$build_dir" "$MAINBOARD"
653 record_mainboard
"$MAINBOARD"
654 remove_target
"$MAINBOARD"
657 function remove_target
659 if [ "$remove" != "true" ]; then
665 # Save the generated coreboot.rom file of each board.
666 if [ -r "$TARGET/${BUILD_NAME}/coreboot.rom" ]; then
667 cp "$TARGET/${BUILD_NAME}/coreboot.rom" \
668 "${BUILD_NAME}_coreboot.rom"
671 echo "Removing build dir for $BUILD_NAME..."
672 rm -rf "${TARGET:?}/${BUILD_NAME}"
685 [-a|--all] Build previously succeeded ports as well
686 [-A|--any-toolchain] Use any toolchain
687 [-b|--board-variant <name>] Build specific board variant under the
689 [-B|--blobs] Allow using binary files
690 [--checksum <path/basefile>] Store checksums at path/basefile
691 [-c|--cpus <numcpus>] Build on <numcpus> at the same time
692 [-C|--config] Configure-only mode
693 [-d|--dir <dir>] Directory containing config files
694 [-e|--exitcode] Exit with a non-zero errorlevel on failure
695 [-J|--junit] Write JUnit formatted xml log file
696 [-K|--kconfig <name>] Prepend file to generated Kconfig
697 [-l|--loglevel <num>] Set loglevel
698 [-L|--clang] Use clang on supported arch
699 [-n|--name] Set build name - also sets xmlfile if not
701 [-o|--outdir <path>] Store build results in path
702 (defaults to $TARGET)
703 [-p|--payloads <dir>] Use payloads in <dir> to build images
704 [-P|--prefix <name>] File name prefix in CBFS
705 [-q|--quiet] Print fewer messages
706 [-r|--remove] Remove output dir after build
707 [-R|--root <path>] Absolute path to coreboot sources
709 [--scan-build] Use clang's static analyzer
710 [--skip_set <value>] Skip building boards with this Kconfig set
711 [--skip_unset <value>] Skip building boards with this Kconfig not set
712 [--timeless] Generate timeless builds
713 [-t|--target <vendor/board>] Attempt to build target vendor/board only
714 [-T|--test] Submit image(s) to automated test system
715 [-u|--update] Update existing image
716 [-v|--verbose] Print more messages
717 [-x|--chromeos] Build with CHROMEOS enabled
718 Skip boards without ChromeOS support
719 [-X|--xmlfile <name>] Set JUnit XML log file filename
720 (defaults to $XMLFILE)
721 [-y|--ccache] Use ccache
722 [-z|--clean] Remove build results when finished
723 [-Z|--clean-somewhat] Remove build but keep coreboot.rom + config
725 [-V|--version] Print version number and exit
726 [-h|--help] Print this help and exit
728 [-s|--silent] obsolete
736 coreboot autobuild v$ABUILD_VERSION ($ABUILD_DATE)
738 Copyright (C) 2004 by Stefan Reinauer <stepan@openbios.org>
739 Copyright (C) 2006-2010 by coresystems GmbH <info@coresystems.de>
741 This program is free software; you may redistribute it under the terms
742 of the GNU General Public License. This program has absolutely no
753 test -f util
/sconfig
/sconfig.l
&& ROOT
=$
( pwd )
754 test -f ..
/util
/sconfig
/sconfig.l
&& ROOT
=$
( cd ..
&& pwd )
755 test "$ROOT" = "" && ROOT
=$
( cd ..
/..
&& pwd )
757 # Look if we have getopt. If not, build it.
758 export PATH
=$PATH:util
/abuild
759 getopt
- > /dev
/null
2>/dev
/null || gcc
-o util
/abuild
/getopt util
/abuild
/getopt.c
761 # Save command line for xargs parallelization.
764 # parse parameters.. try to find out whether we're running GNU getopt
765 getoptbrand
="$(getopt -V)"
767 # shellcheck disable=SC2086
768 if [ "${getoptbrand:0:6}" == "getopt" ]; then
769 # Detected GNU getopt that supports long options.
770 args
=$
(getopt
-l version
,verbose
,quiet
,help,all
,target
:,board-variant
:,payloads
:,cpus
:,silent
,junit
,config
,loglevel
:,remove
,prefix
:,update
,scan-build
,ccache
,blobs
,clang
,any-toolchain
,clean
,clean-somewhat
,outdir
:,chromeos
,xmlfile
:,kconfig
:,dir
:,root
:,recursive
,checksum
:,timeless
,exitcode
,asserts
,name
:,skip_set
:,skip_unset
: -o Vvqhat
:b
:p
:c
:sJCl
:rP
:uyBLAzZo
:xX
:K
:d
:R
:Ien
: -- "$@") ||
exit 1
774 # Detected non-GNU getopt
775 args
=$
(getopt Vvqhat
:b
:p
:c
:sJCl
:rP
:uyBLAZzo
:xX
:K
:d
:R
:Ien
: "$@")
780 if [ $retval != 0 ]; then
792 # testclass needs to be undefined if not used for variable expansion to work
796 -J|
--junit) shift; mode
=junit
; rm -f "$XMLFILE" ;;
797 -t|
--target) shift; target
="$1"; shift;;
798 -b|
--board-variant) shift; variant
="$1"; shift;;
799 -a|
--all) shift; buildall
=true
;;
800 -d|
--dir) shift; configdir
="$1"; shift;;
801 -e|
--exitcode) shift; exitcode
=1;;
802 -r|
--remove) shift; remove
=true
;;
803 -v|
--verbose) shift; verbose
=true
; verboseopt
='V=1';;
804 -q|
--quiet) shift; quiet
=true
;;
805 -V|
--version) shift; myversion
; exit 0;;
806 -h|
--help) shift; myversion
; myhelp
; exit 0;;
807 -p|
--payloads) shift; payloads
="$1"; shift;;
808 -R|
--root) shift; ROOT
="$1"; MAKE
="$MAKE -C $1"; shift;;
810 export MAKEFLAGS
="-j $1"
812 test "$MAKEFLAGS" == "-j max" && export MAKEFLAGS
="-j" && cpuconfig
=" in parallel"
813 test "$1" == "1" && cpuconfig
=" on 1 cpu"
814 expr "$1" : '-\?[0-9]\+$' > /dev
/null
&& test "0$1" -gt 1 && cpuconfig
=" on $1 cpus in parallel"
820 customizing
="${customizing}, scan-build"
821 SCANBUILD_ARGS
=${SCANBUILD_ARGS:-'-k'}
822 configoptions
="${configoptions}CONFIG_FATAL_ASSERTS=y\n"
826 customizing
="${customizing}, Skipping builds with CONFIG_${skipconfig_set}=Y"
830 skipconfig_unset
="$1"
831 customizing
="${customizing}, Skipping builds with CONFIG_${skipconfig_unset} not set"
835 configoptions
="${configoptions}CONFIG_FATAL_ASSERTS=y\n"
838 customizing
="${customizing}, ccache"
839 configoptions
="${configoptions}CONFIG_CCACHE=y\n"
841 -C|
--config) shift; configureonly
=1;;
843 customizing
="${customizing}, loglevel $1"
844 configoptions
="${configoptions}CONFIG_DEFAULT_CONSOLE_LOGLEVEL_$1=y\n"
845 configoptions
="${configoptions}CONFIG_DEFAULT_CONSOLE_LOGLEVEL=$1\n"
848 customizing
="${customizing}, update"
849 configoptions
="${configoptions}CONFIG_UPDATE_IMAGE=y\n"
852 customizing
="${customizing}, cbfs prefix $1"
853 configoptions
="${configoptions}CONFIG_CBFS_PREFIX=\"$1\""
856 customizing
="${customizing}, blobs"
857 configoptions
="${configoptions}CONFIG_USE_AMD_BLOBS=y\nCONFIG_USE_QC_BLOBS=y\nCONFIG_FSP_USE_REPO=y\n"
859 -A|
--any-toolchain) shift
860 customizing
="${customizing}, any-toolchain"
861 configoptions
="${configoptions}CONFIG_ANY_TOOLCHAIN=y\n"
865 customizing
="${customizing}, clang"
866 configoptions
="${configoptions}CONFIG_COMPILER_LLVM_CLANG=y\n# CONFIG_COMPILER_GCC is not set\n"
869 customizing
="${customizing}, clean"
872 -Z|
--clean-somewhat) shift
873 customizing
="${customizing}, clean-somewhat"
885 customizing
="${customizing}, chromeos"
886 configoptions
="${configoptions}CONFIG_CHROMEOS=y\n"
892 -I|
--recursive) shift; recursive
=true
;;
894 testclass
="$(basename "$1" | tr '.' '_' )"
895 customizing
="${customizing}, $1 config"
896 configoptions
="$(cat "$1")${configoptions}\n"
898 --checksum) shift; checksum_file
="$1"; shift;;
899 --timeless) shift; TIMELESS
=1;;
901 -*) printf "Invalid option '%s'\n\n" "$1"; myhelp
; exit 1;;
906 if [[ "${TESTRUN}" != "${TESTRUN_DEFAULT}" ]]; then
908 if [[ "${XML_UPDATED}" != "${XML_DEFAULT}" ]]; then
909 XMLFILE
="abuild-${TESTRUN}.xml"
910 REAL_XMLFILE
="${XMLFILE}"
912 if [[ "${TARGET}" == "${TARGET_DEFAULT}" ]]; then
918 printf "Invalid option '%s'\n\n" "$1"; myhelp
; exit 1;
921 if [ -z "$TARGET" ] ||
[ "$TARGET" = "/" ]; then
922 echo "Please specify a valid, non-root build directory."
926 if ! mkdir
-p "$TARGET"; then
927 echo "Unable to create build directory"
931 if echo "${skipconfig_set}${skipconfig_unset}" |
grep -q "CONFIG_" >/dev
/null
2>&1; then
932 echo "Error: Do not include CONFIG_ in the Kconfig value to skip"
936 customizing
=$
(echo "$customizing" | cut
-c3-)
937 if [ -z "$customizing" ]; then
938 customizing
="Default configuration"
940 customizing
="Config: ${customizing}"
941 FAILED_BOARDS
="$(realpath ${TARGET}/failed_boards)"
942 PASSED_BOARDS
="$(realpath ${TARGET}/passing_boards)"
944 stats_archive
="$TARGET/statistics.tar"
946 # Generate a single xcompile for all boards
947 export xcompile
="${TARGET}/xcompile"
949 if [ "$recursive" = "false" ]; then
951 $MAKE -C"${ROOT}" obj
="$TARGET/temp" objutil
="$TARGET/sharedutils" UPDATED_SUBMODULES
=1 "${xcompile}" ||
exit 1
952 rm -f "$FAILED_BOARDS" "$PASSED_BOARDS"
954 # Initialize empty statistics archive
955 tar -cf "${stats_archive}" "${xcompile}" 2> /dev
/null
959 if [ "$cpus" != "1" ]; then
960 # Limit to 32 parallel builds for now.
961 # Thrashing all caches because we run
962 # 160 abuilds in parallel is no fun.
963 if [ "$cpus" = "max" ]; then
966 # Test if xargs supports the non-standard -P flag
967 # FIXME: disabled until we managed to eliminate all the make(1) quirks
968 echo |
xargs -P ${cpus:-0} -n 1 echo 2>/dev
/null
>/dev
/null
&& USE_XARGS
=1
971 if [ "$USE_XARGS" = "0" ]; then
972 test "$MAKEFLAGS" == "" && test "$cpus" != "" && export MAKEFLAGS
="-j $cpus"
973 export MAKEFLAGS
="$MAKEFLAGS UPDATED_SUBMODULES=1" # no need to re-download
976 local targets
=${*-$(get_mainboards)}
977 for MAINBOARD
in $targets; do
978 build_target
"${MAINBOARD}"
988 local cpus_per_target
990 local targets
=${*-$(get_mainboards)}
993 printf "%s" "$configoptions" > "$TMPCFG"
994 $MAKE -j "$cpus" DOTCONFIG
="$TMPCFG" obj
="$TARGET/temp" objutil
="$TARGET/sharedutils" olddefconfig
2>/dev
/null
996 if [ "$scanbuild" = "true" ]; then
997 scanbuild_out
=$TARGET/sharedutils-scanbuild
998 rm -rf "${scanbuild_out}"
999 BUILDPREFIX
="scan-build -o ${scanbuild_out}tmp"
1001 mkdir
-p "$TARGET/abuild"
1002 ABSPATH
="$(cd "$TARGET/abuild
" && pwd)"
1003 local XMLFILE
="$ABSPATH/__util.xml"
1005 stime
=$
(add_timestamp
)
1006 $BUILDPREFIX "$MAKE" -j "$cpus" DOTCONFIG
="$TMPCFG" obj
="$TARGET/temp" objutil
="$TARGET/sharedutils" tools
> "$TARGET/sharedutils/make.log" 2>&1
1008 etime
=$
(add_timestamp
)
1009 local duration
=$
(ts_delta_seconds
$stime $etime)
1011 junit
" <testcase classname='util' name='all' time='$duration' >"
1012 if [ $ret -eq 0 ]; then
1013 junit
"<system-out>"
1014 junitfile
"$TARGET/sharedutils/make.log"
1015 junit
"</system-out>"
1018 junit
"<failure type='BuildFailed'>"
1019 junitfile
"$TARGET/sharedutils/make.log"
1022 echo "Shared Utilities - Log: $TARGET/sharedutils/make.log" >> "$FAILED_BOARDS"
1027 if [ "$scanbuild" = "true" ]; then
1028 mv "${scanbuild_out}tmp/"* "${scanbuild_out}"
1029 rmdir "${scanbuild_out}tmp"
1031 rm -rf "$TARGET/temp" "$TMPCFG"
1032 num_targets
=$
(wc -w <<<"$targets")
1033 cpus_per_target
=$
(((${cpus:-1} + num_targets
- 1) / num_targets
))
1034 echo "$targets" |
xargs -P ${cpus:-0} -n 1 "$0" "${cmdline[@]}" -I -c "$cpus_per_target" -t
1038 junit
'<?xml version="1.0" encoding="utf-8"?>'
1041 if [ "$target" != "" ]; then
1042 # build a single board
1043 MAINBOARD
=$
(normalize_target
"${target}")
1044 if [ -z "${MAINBOARD}" ]; then
1045 printf "No such target: %s" "${target}"
1046 if [ -n "${variant}" ]; then
1047 printf ", variant: %s" "${variant}"
1052 build_srcdir
="$(mainboard_directory "${MAINBOARD}")"
1053 if [ "$(echo "${MAINBOARD}" | wc -w)" -gt 1 ]; then
1054 build_targets
"${MAINBOARD}"
1055 elif [ ! -r "$ROOT/src/mainboard/${build_srcdir}" ]; then
1056 echo "No such target: ${MAINBOARD}"
1059 build_target
"${MAINBOARD}"
1060 XMLFILE
=$REAL_XMLFILE
1064 rm -f "$REAL_XMLFILE"
1065 XMLFILE
="$REAL_XMLFILE"
1066 junit
'<?xml version="1.0" encoding="utf-8"?>'
1068 if [ "$mode" != "text" ]; then
1069 for xmlfile
in $TARGET/abuild
/*_
*.xml
; do
1070 cat "$xmlfile" >> "$REAL_XMLFILE"
1073 XMLFILE
=$REAL_XMLFILE
1075 junit
'</testsuite>'
1077 if [ "$recursive" = "false" ]; then
1079 # Print the list of failed configurations
1080 if [ -f "$FAILED_BOARDS" ]; then
1081 printf "%s configuration(s) failed:\n" "$( wc -l < "$FAILED_BOARDS" )"
1082 cat "$FAILED_BOARDS"
1084 if [ "$exitcode" != "0" ]; then
1087 elif [ -f "$PASSED_BOARDS" ]; then
1088 printf "All %s tested configurations passed.\n" "$( wc -l < "$PASSED_BOARDS" )"
1090 printf "No boards tested.\n"