mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-03-26 13:59:02 +02:00
On coreboot for example, as Mate has told me, if you're making Kconfig changes and re-compiling, sometimes the actual image that you build might still have the old one in it, due to how coreboot's build system works. To mitigate this, you can just always run distclean before doing the build, but lbmk was doing just clean. In practise, we did not find any issues, but this change should be harmless, and might prevent such issues in the future. It's even possible that we might have already encountered this before and not realised, and we were just lucky that no noticeable issues were caused. It's *also* possible that the reverse is true: an issue that was previously covered up, then that issue will now be exposed. However, if that turns out to be true, then that is good because we are exposing said bugs and then we will know to fix them! Anyway, the variable in target.cfg is: cleancmd="whatever_you_want" e.g. cleancmd="distclean" You may also specify this in global mkhelper.cfg files, per project; I've already done this for SeaBIOS, coreboot and U-Boot, since all of these use Kconfig files. Signed-off-by: Leah Rowe <leah@libreboot.org>
301 lines
9.1 KiB
Bash
Executable File
301 lines
9.1 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"
|
|
|
|
XBMKPATH="$PATH"
|
|
|
|
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 cleancmd`
|
|
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
|
|
unset CROSS_COMPILE
|
|
export PATH="$XBMKPATH"
|
|
[ "$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 cleancmd`
|
|
_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()
|
|
{
|
|
_cleancmd="clean"
|
|
[ -n "$cleancmd" ] && _cleancmd="$cleancmd"
|
|
$dry check_makefile "$srcdir" && \
|
|
x_ make -C "$srcdir" $cleanargs $_cleancmd
|
|
[ -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
|