cbmk/script/trees
Leah Rowe ef3ff3dfe4 trees, multi: download bare project *before* trees
when downloading multi-tree projects, the rev can be reset
to HEAD instead of the actual rev for a given target. this
occurs when the bare repo (e.g. src/coreboot/coreboot) does
not exist and has to be downloaded first.

bare repository downloading does not rely on target.cfg, in
this context, only pkg.cfg, but it uses the same variable
names (e.g. "rev").

instead of using a separate variable name, thus increasing
code complexity (which is the exact opposite of what i want
to do), do the bare repository download first.

this means that the git.sh script is much cleaner now, for
multi-tree projects, in that it *only* copies the bare repo
then runs git_prep; in that context, the bare repo is cloned
directly by calling the relevant function from script/trees,
which is the same behaviour as when cloning single-tree
project sources.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2024-06-30 00:45:21 +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"
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()
{
[ "$cmd" = "build_targets" ] && [ ! -d "src/$project/$project" ] && \
x_ mkdir -p "src/$project" && fetch_project "$project"
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 $@