Files
lbmk/script/trees
Leah Rowe 87df6ae369 trees: support build dependencies, not just fetch
We already have this to an extent, e.g. the xtree variable.

The xtree variable could probably be removed, in favour of
this, and used for the same purpose.

It works like this, for example:

build_depend="coreboot/default grub/xhci seabios u-boot/gru_bob flashprog"

the "/" denotes a tree, if it's a multi-tree project. However, specifying
the entire multi-tree project without slash is possible, for example:

build_depend="coreboot"

this would specify that all coreboot trees must be built.

This functionality will be used in follow-up commits, centralising
script/trees into mk on the main directory, repacing "build".

Signed-off-by: Leah Rowe <leah@libreboot.org>
2024-07-06 11:34:19 +01:00

308 lines
8.7 KiB
Bash
Executable File

#!/usr/bin/env sh
# SPDX-License-Identifier: GPL-3.0-or-later
# Copyright (c) 2022-2023 Alper Nebi Yasak <alpernebiyasak@gmail.com>
# Copyright (c) 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com>
# Copyright (c) 2023-2024 Leah Rowe <leah@libreboot.org>
set -u -e
. "include/lib.sh"
. "include/git.sh"
eval `setvars "" xarch cdir defconfig cmakedir xlang mode makeargs elfdir cmd \
project target target_dir targets xtree _f target1 bootstrapargs mkhelper \
autoconfargs listfile autogenargs btype tree rev tree_depend build_depend`
main()
{
while getopts f:b:m:u:c:x:s:l:n: option; do
[ -n "$_f" ] && $err "only one flag is permitted"
_f="$1"
case "$1" in
-b) mode="" ;;
-u) mode="oldconfig" ;;
-m) mode="menuconfig" ;;
-c) mode="distclean" ;;
-x) mode="crossgcc-clean" ;;
-f) mode="fetch" ;;
-s) mode="savedefconfig" ;;
-l) mode="olddefconfig" ;;
-n) mode="nconfig" ;;
*) $err "invalid option '-$option'" ;;
esac
[ -z "${OPTARG+x}" ] && shift 1 && break
project="${OPTARG#src/}"; shift 2
done
[ -z "$_f" ] && $err "missing flag (-m/-u/-b/-c/-x/-f/-s/-l/-n)"
[ -z "$project" ] && for p in $(ls -1 config/git); do
./update trees $_f "$p" || $err "!./update trees $_f $p"
[ "$XBMK_RELEASE" != "y" ] || singletree "$p" || \
x_ rm -Rf "src/$p/$p"; continue
done && return 0
[ -f "config/git/$project/pkg.cfg" ] || $err "'$project' not defined"
elfdir="elf/$project"
datadir="config/data/$project"
cfgsdir="config/$project"
listfile="$datadir/build.list" # needed on multi, optional on single
remkdir "${tmpgit%/*}"
cmd="build_targets" && singletree "$project" && cmd="build_project"
$cmd $@
[ "$target1" = "utils" ] && [ "$project" = "coreboot" ] && return 0
[ -f "$listfile" ] || return 0
[ -z "$mode" ] && printf "\n\nOK! Check %s/\n\n" "$elfdir"; return 0
}
build_project()
{
load_target_config "$cfgsdir" || return 0
[ -f "$listfile" ] || listfile="" # optional on single-tree
dest_dir="$elfdir"
[ ! -f "$listfile" ] || elfcheck || return 0
cdir="src/${project}"
x_ ./update trees -f "$project"
[ "$mode" = "distclean" ] && mode="clean"
run_make_command || return 0
[ -n "$mode" ] || copy_elf; return 0
}
build_targets()
{
[ "$elfdir" = "elf/coreboot" ] && elfdir="$cbelfdir"
[ -d "$cfgsdir" ] || $err "directory, $cfgsdir, does not exist"
[ -f "$listfile" ] || $err "list file, $listfile, does not exist"
# Build for all targets if no argument is given
[ $# -gt 0 ] && target1="$1"
[ "$target1" = "utils" ] && [ "$project" = "coreboot" ] && shift 1
targets="$(ls -1 "$cfgsdir")" || $err "Can't get options for $cfgsdir"
[ $# -gt 0 ] && targets=$@
handle_targets
}
handle_targets()
{
for x in $targets; do
target="$x"
printf "'make %s', '%s', '%s'\n" "$mode" "$project" "$target"
[ "$project" != "coreboot" ] || [ -n "$mode" ] || \
[ "$target1" = "utils" ] || x_ ./vendor download $target
x_ handle_defconfig
done
}
handle_defconfig()
{
handle_src_tree "$target" || return 0
[ "$target1" = "utils" ] && [ "$project" = "coreboot" ] && \
eval "check_coreboot_utils \"$tree\"; return 0"
for y in "$target_dir/config"/*; do
[ -f "$y" ] || continue
defconfig="$y"
[ -n "$mode" ] || check_defconfig || continue
handle_makefile
[ -n "$mode" ] || copy_elf
done; return 0
}
handle_src_tree()
{
target_dir="$cfgsdir/$target"
[ -f "CHANGELOG" ] || fetch_project "$project"
load_target_config "$target_dir" || return 1
x_ mkdir -p "$elfdir/$target"
chkvars tree
cdir="src/$project/$tree"
if [ "$mode" = "distclean" ] || [ "$mode" = "crossgcc-clean" ]; then
[ -d "$cdir" ] || return 1
fi
x_ ./update trees -f "$project" "$target"
[ "$target1" = "utils" ] && [ "$project" = "coreboot" ] && return 0
[ -z "$mode" ] && check_cross_compiler; return 0
}
load_target_config()
{
eval `setvars "" xarch xlang bootstrapargs autoconfargs xtree \
tree_depend makeargs btype mkhelper build_depend`
[ -f "$1/target.cfg" ] || btype="auto"
[ -f "$datadir/mkhelper.cfg" ] && eval `setcfg "$datadir/mkhelper.cfg"`
_tcfg="$1/target.cfg"
while [ -f "$_tcfg" ] || [ "$cmd" = "build_targets" ]; do
eval `setvars "" rev tree`
printf "Loading %s config: %s\n" "$project" "$_tcfg"
eval `setcfg "$_tcfg"`
[ "$cmd" = "build_project" ] && break
[ "$mode" = "fetch" ] || break
[ "${_tcfg%/*/target.cfg}" = "${_tcfg%"/$tree/target.cfg"}" ] \
&& break; _tcfg="${_tcfg%/*/target.cfg}/$tree/target.cfg"
done
[ -z "$btype" ] || [ "${mode%config}" = "$mode" ] || return 1
[ -z "$mode" ] && for bd in $build_depend; do
bd_project="${bd%%/*}"; bd_tree="${bd##*/}"
[ -z "$bd_project" ] && $err "$project/$tree: bad bd: '$bd'"
[ "${bd##*/}" = "$bd" ] && bd_tree=""
[ -z "$bd_project" ] || ./update trees -b $bd_project \
$bd_tree || $err "$project/$tree: !bd $bd"; continue
done
[ "$mode" = "fetch" ] || return 0
[ -f "CHANGELOG" ] && return 1; fetch_${cmd#build_}; return 1
}
check_cross_compiler()
{
for _xarch in $xarch; do
cbdir="src/coreboot/$tree"
[ "$project" != "coreboot" ] && cbdir="src/coreboot/default"
[ -n "$xtree" ] && cbdir="src/coreboot/$xtree"
x_ ./update trees -f coreboot ${cbdir#src/coreboot/}
export PATH="$PWD/$cbdir/util/crossgcc/xgcc/bin:$PATH"
export CROSS_COMPILE="${xarch% *}-"
[ -n "$xlang" ] && export BUILD_LANGUAGES="$xlang"
# sometimes buildgcc fails for like no reason. try twice.
make -C "$cbdir" crossgcc-${_xarch%-*} $makeargs || \
make -C "$cbdir" crossgcc-${_xarch%-*} $makeargs || \
$err "!mkxgcc $project/$xtree '${_xarch%-*}' '$makeargs'"
done; return 0
}
check_coreboot_utils()
{
for util in cbfstool ifdtool; do
utilelfdir="elf/$util/$1"
utilsrcdir="src/coreboot/$1/util/$util"
utilmode="" && [ -n "$mode" ] && utilmode="clean"
x_ make -C "$utilsrcdir" $utilmode -j$XBMK_THREADS $makeargs
[ -z "$mode" ] && [ ! -f "$utilelfdir/$util" ] && \
x_ mkdir -p "$utilelfdir" && \
x_ cp "$utilsrcdir/$util" "elf/$util/$1"
[ -z "$mode" ] || x_ rm -Rf "$utilelfdir"
done; return 0
}
check_defconfig()
{
[ -f "$defconfig" ] || $err "$project/$target: missing defconfig"
dest_dir="$elfdir/$target/${defconfig#"$target_dir/config/"}"
elfcheck || return 1 # skip build if a previous one exists
x_ mkdir -p "$dest_dir"
}
elfcheck()
{
# TODO: very hacky check. do it properly (based on build.list)
for elftest in "$dest_dir"/*; do
[ -e "$elftest" ] && e "$elftest" f && return 1
done; return 0
}
handle_makefile()
{
check_makefile "$cdir" && x_ make clean -C "$cdir"
x_ cp "$defconfig" "$cdir/.config"
[ -n "$mode" ] || [ -n "$btype" ] || make -C "$cdir" \
silentoldconfig || make -C "$cdir" oldconfig || :
run_make_command || $err "handle_makefile $cdir: no makefile!"
_copy=".config" && [ "$mode" = "savedefconfig" ] && _copy="defconfig"
[ "${mode%config}" = "$mode" ] || x_ cp "$cdir/$_copy" "$defconfig"
[ -e "$cdir/.git" ] && [ "$project" = "u-boot" ] && \
[ "$mode" = "distclean" ] && x_ git -C "$cdir" clean -fdx; return 0
}
run_make_command()
{
check_cmake "$cdir" && [ -z "$mode" ] && check_autoconf "$cdir"
check_makefile "$cdir" || return 1
[ "$project" = "coreboot" ] && [ -z "$mode" ] && x_ \
printf "%s\n" "${version%%-*}" > "$cdir/.coreboot-version"
make -C "$cdir" $mode -j$XBMK_THREADS $makeargs || $err "$cdir mk$mode"
[ -z "$mkhelper" ] || [ -n "$mode" ] || $mkhelper || $err "!$mkhelper"
[ "$mode" = "clean" ] && make -C "$cdir" distclean || :; return 0
}
check_cmake()
{
[ -z "$cmakedir" ] || check_makefile "$1" || cmake -B "$1" \
"$1/$cmakedir" || check_makefile "$1" || $err "$1: !cmk $cmakedir"
[ -z "$cmakedir" ] || check_makefile "$1" || \
$err "check_cmake $1: can't generate Makefile"; return 0
}
check_autoconf()
{
(
cd "$1" || $err "!cd $1"
[ -f "bootstrap" ] && x_ ./bootstrap $bootstrapargs
[ -f "autogen.sh" ] && x_ ./autogen.sh $autogenargs
[ -f "configure" ] && x_ ./configure $autoconfargs; return 0
) || $err "can't bootstrap project: $1"
}
check_makefile()
{
[ -f "$1/Makefile" ] || [ -f "$1/makefile" ] || \
[ -f "$1/GNUmakefile" ] || return 1; return 0
}
mkpayload_grub()
{
eval `setvars "" grub_modules grub_install_modules`
eval `setcfg "$grubdata/module/$tree"`
x_ rm -f "$cdir/grub.elf"
"${cdir}/grub-mkstandalone" --grub-mkimage="${cdir}/grub-mkimage" \
-O i386-coreboot -o "${cdir}/grub.elf" -d "${cdir}/grub-core/" \
--fonts= --themes= --locales= --modules="$grub_modules" \
--install-modules="$grub_install_modules" \
"/boot/grub/grub_default.cfg=${cdir}/.config" \
"/boot/grub/grub.cfg=$grubdata/memdisk.cfg" \
"/background.png=$grubdata/background/background1280x800.png" || \
$err "$tree: cannot build grub.elf"; return 0
}
copy_elf()
{
[ -f "$listfile" ] && x_ mkdir -p "$dest_dir" && while read -r f; do
[ -f "$cdir/$f" ] && x_ cp "$cdir/$f" "$dest_dir"
done < "$listfile"; x_ make clean -C "$cdir"
}
main $@