Files
lbmk/script/trees
Leah Rowe c0017c7357 Experimental U-Boot payload (32-bit dtb, U-Boot)
NOTE: Support added for xarch target x86_64-elf,
but U-Boot failed to build with this error:

OBJCOPY lib/efi_loader/helloworld.efi
x86_64-elf-objcopy: lib/efi_loader/helloworld_efi.so: invalid bfd target
make[2]: *** [scripts/Makefile.lib:476: lib/efi_loader/helloworld.efi] Error 1

Since I'm building U-Boot for x86_64 *on* an x86-64
host, and since that is currently the recommended type
of machine to use for lbmk development, and since the
other x86 payloads currently don't cross compile anyway,
this is an acceptable compromise for now. This is because
at present, I'm not making U-Boot the primary payload on x86,
instead preferring to chain it from GRUB and SeaBIOS.

The target.cfg file for x86 u-boot shows xarch/xtree commented.
Uncomment these to compile on crossgcc instead of hostcc.

I mention 64-bit because I initially did this first, but decided
to do 32-bit first. I'll work on the 64-bit one next (SPL).

It's only enabled in QEMU for now.

Signed-off-by: Leah Rowe <leah@libreboot.org>
2024-11-03 09:22:52 +00:00

293 lines
8.9 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 srcdir premake cmakedir xlang mode makeargs elfdir cmd \
project target target_dir targets xtree _f release bootstrapargs mkhelper \
autoconfargs listfile autogenargs btype tree rev tree_depend build_depend \
defconfig postmake mkhelpercfg dry dest_dir mdir cleanargs`; badhash="n"
main()
{
while getopts f:b:m:u:c:x:s:l:n:d: option; do
[ -n "$_f" ] && $err "only one flag is permitted"
_f="$1" && [ "$_f" = "-d" ] && dry=":"
case "$1" in
-d) mode="" ;;
-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" ] && mk $_f $(ls -1 config/git) && return 1
[ -f "config/git/$project/pkg.cfg" ] || $err "'$project' not defined"
for d in "elf" "config/data" "config" "src"; do
eval "${d#*/}dir=\"$d/$project\""
done; dest_dir="$elfdir"
listfile="$datadir/build.list"
[ -f "$listfile" ] || listfile="" # optional on all projects
mkhelpercfg="$datadir/mkhelper.cfg"
e "$mkhelpercfg" f missing && mkhelpercfg="$TMPDIR/mkhelper.cfg" && \
x_ touch "$mkhelpercfg"
targets="$@"; cmd="build_targets $targets"
singletree "$project" && cmd="build_project"
remkdir "${tmpgit%/*}"
}
build_project()
{
configure_project "$configdir" || return 0
[ ! -f "$listfile" ] || $dry elfcheck || return 0
[ "$mode" = "distclean" ] && mode="clean"
run_make_command || return 0
[ -n "$mode" ] || $dry copy_elf; return 0
}
build_targets()
{
[ -d "$configdir" ] || $err "directory, $configdir, does not exist"
[ $# -gt 0 ] || targets="$(ls -1 "$configdir")" || $err "!o $configdir"
for x in $targets; do
[ "$x" = "list" ] && x_ ls -1 "config/$project" && \
listfile="" && break
target="$x"
printf "'make %s', '%s', '%s'\n" "$mode" "$project" "$target"
x_ handle_defconfig
[ -n "$mode" ] || [ -z "$postmake" ] || $postmake || \
$err "$project/$target: !postmake: $postmake"; continue
done; return 0
}
handle_defconfig()
{
target_dir="$configdir/$target"
[ -f "CHANGELOG" ] || fetch_project "$project"
configure_project "$target_dir" || return 0
x_ mkdir -p "$elfdir/$target"
chkvars tree; srcdir="src/$project/$tree"
if [ "$mode" = "distclean" ] || [ "$mode" = "crossgcc-clean" ]; then
[ -d "$srcdir" ] || return 0
fi
[ -z "$mode" ] && $dry check_cross_compiler
for y in "$target_dir/config"/*; do
[ "$_f" = "-d" ] || [ -f "$y" ] || continue
[ "$_f" = "-d" ] || defconfig="$y"
[ -n "$mode" ] || check_defconfig || continue
handle_makefile
[ -n "$mode" ] || $dry copy_elf
done; return 0
}
configure_project()
{
eval `setvars "" xarch xlang build_depend autoconfargs xtree postmake \
tree_depend makeargs btype mkhelper bootstrapargs premake release \
cleanargs`
_tcfg="$1/target.cfg"; badhash="n"; [ -f "$_tcfg" ] || btype="auto"
[ -f "$datadir/mkhelper.cfg" ] && eval `setcfg "$datadir/mkhelper.cfg"`
while [ -f "$_tcfg" ] || [ "$cmd" != "build_project" ]; do
eval `setvars "" rev tree`; eval `setcfg "$_tcfg"`
printf "Loading %s config: %s\n" "$project" "$_tcfg"
[ "$_f" = "-d" ] && build_depend="" # dry run
[ "$cmd" = "build_project" ] && break
[ "$mode" = "fetch" ] || break
[ "${_tcfg%/*/target.cfg}" = "${_tcfg%"/$tree/target.cfg"}" ] \
&& break; _tcfg="${_tcfg%/*/target.cfg}/$tree/target.cfg"
done
[ "$XBMK_RELEASE" = "y" ] && [ "$release" = "n" ] && return 1
[ -z "$btype" ] || [ "${mode%config}" = "$mode" ] || return 1
[ -z "$mode" ] && build_dependencies
mdir="$PWD/config/submodule/$project"
[ -n "$tree" ] && mdir="$mdir/$tree"
[ -f "CHANGELOG" ] || check_project_hashes
[ "$mode" = "fetch" ] || x_ ./mk -f "$project" $target
[ "$mode" = "fetch" ] || return 0
[ -f "CHANGELOG" ] && return 1; fetch_${cmd#build_}; return 1
}
build_dependencies()
{
for bd in $build_depend; do
bd_p="${bd%%/*}"; bd_t="${bd##*/}"
[ -z "$bd_p" ] && $dry $err "$project/$tree: !bd '$bd'"
[ "${bd##*/}" = "$bd" ] && bd_t=""
[ -z "$bd_p" ] || $dry ./mk -b $bd_p $bd_t \
|| $err "!mk $project/$tree $bd_p/$bd_t"; continue
done; return 0
}
check_project_hashes()
{
mkdir -p "$XBMK_CACHE/hash" || $err "!mkdir '$XBMK_CACHE/hash'"
old_pjhash=""; [ ! -f "$XBMK_CACHE/hash/$project$tree" ] || \
read -r old_pjhash < "$XBMK_CACHE/hash/$project$tree"
x_ rm -f "$TMPDIR/project.list" "$TMPDIR/project.hash" \
"$TMPDIR/project.tmp"; x_ touch "$TMPDIR/project.tmp"
x_ touch "$TMPDIR/project.hash"
for rmchk in "$datadir" "$configdir/$tree" "$mdir"; do
[ -d "$rmchk" ] || continue
find "$rmchk" -type f -not -path "*/.git*/*" >> \
"$TMPDIR/project.tmp" || $err "!find $rmchk > project.tmp"
done; sort "$TMPDIR/project.tmp" > "$TMPDIR/project.list" || \
$err "!sort project tmp/list"
while read -r rmchk; do
[ ! -f "$rmchk" ] || sha512sum "$rmchk" | awk \
'{print $1}' >> "$TMPDIR/project.hash" || $err "!h $rmchk"
done < "$TMPDIR/project.list"
pjhash="$(sha512sum "$TMPDIR/project.hash" | awk '{print $1}')" || :
badhash="y" && [ "$pjhash" = "$old_pjhash" ] && badhash="n"
[ -f "$XBMK_CACHE/hash/$project$tree" ] || badhash="y"
printf "%s\n" "$pjhash" > "$XBMK_CACHE/hash/$project$tree" || \
$err "!mk $XBMK_CACHE/hash/$project$tree"
[ "$badhash" = "n" ] || rm -Rf "src/$project/$tree" \
"elf/$project/$tree" "elf/$project/$target" || \
$err "!rm $project $tree"; :
}
check_cross_compiler()
{
xgccargs="UPDATED_SUBMODULES=1 CPUS=$XBMK_THREADS"
for _xarch in $xarch; do
cbdir="src/coreboot/$tree"
[ "$project" != "coreboot" ] && cbdir="src/coreboot/default"
[ -n "$xtree" ] && cbdir="src/coreboot/$xtree"
x_ ./mk -f coreboot ${cbdir#src/coreboot/}
export PATH="$PWD/$cbdir/util/crossgcc/xgcc/bin:$PATH"
export CROSS_COMPILE="${xarch% *}-"
[ -n "$xlang" ] && export BUILD_LANGUAGES="$xlang"
xfix="${_xarch%-*}" && [ "$xfix" = "x86_64" ] && xfix="x64"
# sometimes buildgcc fails for like no reason. try twice.
make -C "$cbdir" crossgcc-$xfix $xgccargs || \
make -C "$cbdir" crossgcc-$xfix $xgccargs || \
$err "!mkxgcc $project/$xtree '$xfix' '$xgccargs'"
done; return 0
}
check_defconfig()
{
[ -f "$defconfig" ] || $dry $err "$project/$target: missing defconfig"
dest_dir="$elfdir/$target/${defconfig#"$target_dir/config/"}"
$dry elfcheck || return 1 # skip build if a previous one exists
$dry 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()
{
$dry check_makefile "$srcdir" && x_ make -C "$srcdir" $cleanargs clean
[ -f "$defconfig" ] && x_ cp "$defconfig" "$srcdir/.config"
[ -n "$mode" ] || [ -n "$btype" ] || $dry make -C \
"$srcdir" silentoldconfig || make -C "$srcdir" oldconfig || :
run_make_command || $err "handle_makefile $srcdir: no makefile!"
_copy=".config" && [ "$mode" = "savedefconfig" ] && _copy="defconfig"
[ "${mode%config}" = "$mode" ] || \
$dry x_ cp "$srcdir/$_copy" "$defconfig"
[ -e "$srcdir/.git" ] && [ "$project" = "u-boot" ] && \
[ "$mode" = "distclean" ] && $dry x_ git -C "$srcdir" $cleanargs clean -fdx; :
}
run_make_command()
{
[ -z "$premake" ] || [ -n "$mode" ] || $premake || $err "!$premake"
$dry check_cmake "$srcdir" && [ -z "$mode" ] && $dry check_autoconf \
"$srcdir"; $dry check_makefile "$srcdir" || return 1
$dry make -C "$srcdir" $mode -j$XBMK_THREADS $makeargs || $err "!$mode"
[ -z "$mkhelper" ] || [ -n "$mode" ] || $mkhelper || $err "!$mkhelper"
[ "$mode" = "clean" ] && \
$dry make -C "$srcdir" $cleanargs distclean || :; :
}
check_cmake()
{
[ -z "$cmakedir" ] || $dry check_makefile "$1" || cmake -B "$1" \
"$1/$cmakedir" || $dry check_makefile "$1" || $err \
"$1: !cmk $cmakedir"
[ -z "$cmakedir" ] || $dry 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
}
copy_elf()
{
[ -f "$listfile" ] && x_ mkdir -p "$dest_dir" && while read -r f; do
[ -f "$srcdir/$f" ] && x_ cp "$srcdir/$f" "$dest_dir"
done < "$listfile"; x_ make clean -C "$srcdir" $cleanargs
}
main $@ || exit 0
. "$mkhelpercfg"
$cmd