Files
lbmk/script/trees
T
Leah Rowe a5e724e51e trees: unified multi-tree configuration handling
the same function that loads configurations for single-tree
projects has been merged with the function for multi-tree
configs in git.sh, and that functionality has been removed
from git.sh; now it is all unified in the trees script.

as the saying goes: write one program to do one thing well.

the purpose of git.sh is to download source code, but not
to handle configuration files; the latter is meant to be
handled by the trees script, which then calls into git.sh
before running the build logic for that given project.

additionally: the "seen" files are no longer handled, at all.
the logic there was added ages ago, because at the time, i was
considering whether to separate configuration into a new
repository, so that users could more easily make their own
configuration, so it was a guard against misconfiguration.
however, that decision was canceled and we're always very
careful not to introduce a loop; if a loop does occur, the
worst that can possibly happen is you waste some CPU cycles.

Instead, print (on standard output) what config file is being
used, so the operator can see when an infinite loop occurs.

ALSO:

remove _setcfgarg in load_project_config()

it was used to skip when a target.cfg file didn't exist,
specifically on single-tree projects, but this is now
handled using -f instead, on the while loop inside that
function, so _setcfgarg is now a redundant variable.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2024-06-30 00:02:03 +01:00

308 lines
8.5 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"
cbmakeargs="UPDATED_SUBMODULES=1 CPUS=$XBMK_THREADS"
eval `setvars "" xarch cdir config cmakedir xlang mode makeargs elfdir xtree \
project target target_dir targets tree _f target1 bootstrapargs mkhelper \
autoconfargs config_name listfile autogenargs btype cmd`
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
[ -n "${OPTARG+x}" ] || $err "OPTARG not set"
project="${OPTARG#src/}"; shift 2
done
[ -z "$_f" ] && $err "missing flag (-m/-u/-b/-c/-x/-f/-s/-l/-n)"
[ -z "$project" ] && $err "project name not specified"
[ -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_project_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
config="$y"
config_name="${config#"$target_dir/config/"}"
[ -n "$mode" ] || check_config || continue
handle_makefile
[ -n "$mode" ] || copy_elf
done
}
handle_src_tree()
{
target_dir="$cfgsdir/$target"
load_project_config "$target_dir" || return 1
x_ mkdir -p "$elfdir/$target"
chkvars tree
cdir="src/$project/$tree"
if [ ! -d "$cdir" ]; then
if [ "$mode" = "distclean" ] || \
[ "$mode" = "crossgcc-clean" ]; then
printf "Dir '%s' missing; skip clean\n" "$cdir" 1>&2
return 1
fi
x_ ./update trees -f "$project" "$target"
fi
[ "$target1" = "utils" ] && [ "$project" = "coreboot" ] && return 0
[ -z "$mode" ] && check_cross_compiler; return 0
}
load_project_config()
{
eval `setvars "" xarch xlang bootstrapargs autoconfargs xtree \
tree_depend makeargs btype mkhelper`
[ -f "$1/target.cfg" ] || btype="auto"
_tcfg="$1/target.cfg"
while [ -f "$_tcfg" ] || [ "$cmd" = "build_targets" ]; do
# target.cfg optional on single-tree so return if missing.
# target.cfg mandatory on multi-tree so err if missing.
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
[ "$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%-*} $cbmakeargs || \
make -C "$cbdir" crossgcc-${_xarch%-*} $cbmakeargs || \
$err "!mkxgcc $project/$xtree '${_xarch%-*}' '$cbmakeargs'"
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 $cbmakeargs
[ -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_config()
{
[ -f "$config" ] || $err "check_config $project/$target: no config"
dest_dir="$elfdir/$target/$config_name"
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 "$config" "$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" "$config"
[ -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" \
&& makeargs="$makeargs $cbmakeargs"
make -C "$cdir" $mode -j$XBMK_THREADS $makeargs || $err "$cdir mk$mode"
[ -z "$mkhelper" ] || [ -n "$mode" ] || $mkhelper || \
$err "$cdir: helper command failed: $mkhelper" # eg mkpayload_grub
[ "$mode" != "clean" ] && return 0
make -C "$cdir" distclean 2>/dev/null || :
}
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 $@