mirror of
https://codeberg.org/libreboot/lbmk.git
synced 2026-07-11 14:02:52 +02:00
8c03b886c4
Instead of having detailed error messages, run most commands through a function that calls err() under fault conditions. Where detail is still required, err() is still called manually. Where it isn't, the error message is simply whatever command was executed to cause the error. This results in a massive sloccount reduction for lbmk; specifically, 178 sloc reduction, or a 8.1% reduction. The total sloccount is now 2022, for shell scripts. Signed-off-by: Leah Rowe <leah@libreboot.org>
274 lines
7.8 KiB
Bash
Executable File
274 lines
7.8 KiB
Bash
Executable File
#!/usr/bin/env sh
|
|
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
# SPDX-FileCopyrightText: 2022 Alper Nebi Yasak <alpernebiyasak@gmail.com>
|
|
# SPDX-FileCopyrightText: 2022 Ferass El Hafidi <vitali64pmemail@protonmail.com>
|
|
# SPDX-FileCopyrightText: 2023 Leah Rowe <leah@libreboot.org>
|
|
|
|
[ "x${DEBUG+set}" = 'xset' ] && set -v
|
|
set -u -e
|
|
|
|
. "include/err.sh"
|
|
. "include/option.sh"
|
|
|
|
read projectname < projectname
|
|
read our_version < version
|
|
|
|
export LOCALVERSION="-${projectname}-${our_version}"
|
|
|
|
eval "$(setvars "" arch cfgsdir codedir config config_name crossgcc_ada mode \
|
|
elfdir listfile project romtype target target_dir targets tree cbfstool)"
|
|
|
|
tmpclean="$(mktemp -d -t makeclean.XXXXXXXXXX)" || fail "!mkdir tmpclean"
|
|
|
|
main()
|
|
{
|
|
while getopts b:m:u:c:x: option
|
|
do
|
|
case "${1}" in
|
|
-b) mode="all" ;;
|
|
-u) mode="oldconfig" ;;
|
|
-m) mode="menuconfig" ;;
|
|
-c) mode="distclean" ;;
|
|
-x) mode="crossgcc-clean" ;;
|
|
*) fail "Invalid option" ;;
|
|
esac
|
|
shift; project="${OPTARG}"; shift
|
|
done
|
|
[ -z "${mode}" ] && fail "mode not given (-m, -u, -b, -c or -x)"
|
|
[ -z "${project}" ] && fail "project name not specified"
|
|
|
|
handle_dependencies $@
|
|
handle_targets
|
|
}
|
|
|
|
handle_dependencies()
|
|
{
|
|
elfdir="elf/${project}"
|
|
|
|
cfgsdir="config/${project}"
|
|
[ -d "${cfgsdir}" ] || fail "directory, ${cfgsdir}, does not exist"
|
|
|
|
listfile="${cfgsdir}/build.list"
|
|
[ -f "${listfile}" ] || fail "list file, ${listfile}, does not exist"
|
|
|
|
# Build for all targets if no argument is given
|
|
targets=$(listitems "${cfgsdir}") || \
|
|
fail "Cannot get options for ${cfgsdir}"
|
|
[ $# -gt 0 ] && targets=$@
|
|
|
|
[ "${mode}" = "all" ] && xx_ mkdir -p "${elfdir}/"
|
|
}
|
|
|
|
handle_targets()
|
|
{
|
|
for x in ${targets}; do
|
|
target="${x}"
|
|
printf "Running 'make %s' for project '%s, target '%s''\n" \
|
|
"${mode}" "${project}" "${target}"
|
|
[ "${project}" != "coreboot" ] || [ "${mode}" != "all" ] || \
|
|
xx_ ./update blobs download ${target}
|
|
xx_ handle_defconfig
|
|
done
|
|
|
|
[ "${mode}" = "all" ] || return 0
|
|
printf "Done! The files are stored under %s/\n\n" "${elfdir}"
|
|
}
|
|
|
|
handle_defconfig()
|
|
{
|
|
handle_src_tree "${target}" || return 0
|
|
|
|
for y in "${target_dir}/config"/*; do
|
|
[ -f "${y}" ] || continue
|
|
config="${y}"
|
|
config_name="${config#$target_dir/config/}"
|
|
|
|
printf "handle/make/config %s %s: handling config %s\n" \
|
|
"${project}" "${target}" "${config_name}"
|
|
|
|
[ "${mode}" != "all" ] || check_config || continue
|
|
run_make_command
|
|
[ "${mode}" != "all" ] || copy_elf
|
|
done
|
|
}
|
|
|
|
handle_src_tree()
|
|
{
|
|
target_dir="${cfgsdir}/${target}"
|
|
xx_ mkdir -p "${elfdir}/${target}"
|
|
|
|
eval "$(setvars "undefined" arch tree)"
|
|
romtype="normal"
|
|
|
|
[ ! -f "${target_dir}/target.cfg" ] && \
|
|
fail "handle_src_tree: ${target_dir}: missing target.cfg"
|
|
|
|
# Override the above defaults using target.cfg
|
|
. "${target_dir}/target.cfg" # source
|
|
|
|
[ "${tree}" = "undefined" ] && \
|
|
fail "handle_src_tree: ${target_dir}: tree undefined"
|
|
[ "${arch}" = "undefined" ] && \
|
|
fail "handle_src_tree: ${target_dir}: undefined cpu type"
|
|
|
|
codedir="${project}/${tree}"
|
|
if [ ! -d "${codedir}" ]; then
|
|
if [ "${mode}" = "distclean" ] || \
|
|
[ "${mode}" = "crossgcc-clean" ]; then
|
|
printf "Directory %s doesn't exist; skipping clean\n" \
|
|
"${codedir}" 1>&2
|
|
return 1
|
|
fi
|
|
xx_ ./update project trees "${project}" "${target}"
|
|
elif [ "${mode}" = "distclean" ] || \
|
|
[ "${mode}" = "crossgcc-clean" ]; then
|
|
[ -f "${tmpclean}/${tree}" ] && return 1
|
|
touch "${tmpclean}/${tree}"
|
|
fi
|
|
|
|
# u-boot and coreboot are both compiled with coreboot's crossgcc
|
|
if [ "${project}" = "coreboot" ] || [ "${project}" = "u-boot" ]; then
|
|
[ "${mode}" != "all" ] || check_cross_compiler || \
|
|
fail "handle_src_tree ${project}/${target}: crossgcc"
|
|
cbfstool="cbutils/${tree}/cbfstool"
|
|
[ -f "${cbfstool}" ] || xx_ ./build coreboot utils "${tree}"
|
|
fi
|
|
}
|
|
|
|
# set up cross-compiler (coreboot crossgcc) for u-boot and coreboot
|
|
# (seabios and grub currently use hostcc, not crossgcc)
|
|
check_cross_compiler()
|
|
{
|
|
[ "${crossgcc_ada}" = "y" ] || [ "${crossgcc_ada}" = "n" ] || \
|
|
crossgcc_ada="y"
|
|
[ "${crossgcc_ada}" != "y" ] && \
|
|
export BUILD_LANGUAGES=c
|
|
|
|
cbdir="coreboot/${tree}"
|
|
[ "${project}" != "coreboot" ] && \
|
|
cbdir="coreboot/default" # not u-boot (e.g. linux will use it)
|
|
[ "${project}" = "u-boot" ] && \
|
|
cbdir="coreboot/cros" # u-boot only used on coreboot/cros
|
|
# only true if not building coreboot:
|
|
ctarget="${cbdir#coreboot/}"
|
|
[ -d "${cbdir}" ] || \
|
|
xx_ ./update project trees coreboot ${ctarget}
|
|
|
|
if [ "${arch}" = "x86_32" ] || [ "${arch}" = "x86_64" ]; then
|
|
[ -d "${cbdir}/util/crossgcc/xgcc/i386-elf/" ] || \
|
|
make -C "${cbdir}" crossgcc-i386 CPUS=$(nproc) || \
|
|
return 1
|
|
case "$(uname -m)" in
|
|
x86*|i*86|amd64) : ;;
|
|
*) export CROSS_COMPILE=i386-elf- ;;
|
|
esac
|
|
elif [ "${arch}" = "ARMv7" ]; then
|
|
[ -d "${cbdir}/util/crossgcc/xgcc/arm-eabi/" ] || \
|
|
make -C "${cbdir}" crossgcc-arm CPUS=$(nproc) || \
|
|
return 1
|
|
case "$(uname -m)" in
|
|
arm|arm32|armv6*|armv7*) : ;;
|
|
*) export CROSS_COMPILE=arm-eabi- ;;
|
|
esac
|
|
elif [ "${arch}" = "AArch64" ]; then
|
|
[ -d "${cbdir}/util/crossgcc/xgcc/aarch64-elf/" ] || \
|
|
make -C "${cbdir}" crossgcc-aarch64 CPUS=$(nproc) || \
|
|
return 1
|
|
# aarch64 also needs armv7 toolchain for arm-trusted-firmware
|
|
[ -d "${cbdir}/util/crossgcc/xgcc/arm-eabi/" ] || \
|
|
make -C "${cbdir}" crossgcc-arm CPUS=$(nproc) || \
|
|
return 1
|
|
case "$(uname -m)" in
|
|
arm64|aarch64) : ;;
|
|
*) export CROSS_COMPILE=aarch64-elf- ;;
|
|
esac
|
|
fi
|
|
|
|
# we *must* ensure that u-boot's build system uses crossgcc first
|
|
export PATH="$(pwd)/${cbdir}/util/crossgcc/xgcc/bin:$PATH"
|
|
}
|
|
|
|
check_config()
|
|
{
|
|
[ ! -f "${config}" ] && \
|
|
fail "check_config: ${project}/${target}: configs missing"
|
|
|
|
dest_dir="${elfdir}/${target}/${config_name}"
|
|
# TODO: very hacky check. do it properly (based on build.list)
|
|
for elftest in "${dest_dir}"/*; do
|
|
[ -f "${elftest}" ] || continue
|
|
printf "Build already exists, so skipping build\n" 1>&2
|
|
return 1
|
|
done
|
|
xx_ mkdir -p "${dest_dir}"
|
|
}
|
|
|
|
run_make_command()
|
|
{
|
|
xx_ ./handle make file -c "${codedir}"
|
|
xx_ cp "${config}" "${codedir}/.config"
|
|
[ "${mode}" != "all" ] || make -C "${codedir}" silentoldconfig || \
|
|
make -C "${codedir}" oldconfig || : # don't error on oldconfig
|
|
|
|
if [ "${project}" = "coreboot" ] && [ "${mode}" = "all" ]; then
|
|
printf "%s\n" "${our_version}" >"${codedir}/.coreboot-version" \
|
|
|| fail "run_make_command: ${codedir}: can't set version"
|
|
fi
|
|
xx_ make -C "${codedir}" -j$(nproc) ${mode}
|
|
|
|
if [ -e "${codedir}/.git" ] && [ "${project}" = "u-boot" ] && \
|
|
[ "${mode}" = "distclean" ]; then
|
|
xx_ git -C "${codedir}" clean -fdx
|
|
elif [ "${mode}" = "oldconfig" ] || [ "${mode}" = "menuconfig" ]; then
|
|
xx_ cp "${codedir}/.config" "${config}"
|
|
fi
|
|
}
|
|
|
|
copy_elf()
|
|
{
|
|
[ "${project}" != "coreboot" ] || xx_ modify_coreboot_rom
|
|
|
|
while read f; do
|
|
[ ! -f "${codedir}/$f" ] || \
|
|
xx_ cp "${codedir}/${f}" "${dest_dir}/"
|
|
done < ${listfile}
|
|
|
|
xx_ ./handle make file -c "${codedir}"
|
|
}
|
|
|
|
modify_coreboot_rom()
|
|
{
|
|
rompath="${codedir}/build/coreboot.rom"
|
|
[ -f "${rompath}" ] || \
|
|
fail "modify_coreboot_rom: does not exist: ${rompath}"
|
|
tmprom="$(mktemp -t rom.XXXXXXXXXX)"
|
|
xx_ rm -f "${tmprom}"
|
|
|
|
if [ "${romtype}" = "d8d16sas" ]; then
|
|
# pike2008 roms hang seabios. an empty rom will override
|
|
# the built-in one, thus disabling all execution of it
|
|
xx_ touch "${tmprom}"
|
|
for deviceID in "0072" "3050"; do
|
|
xx_ "${cbfstool}" "${rompath}" add -f "${tmprom}" \
|
|
-n "pci1000,${deviceID}.rom" -t raw
|
|
done
|
|
elif [ "${romtype}" = "i945 laptop" ]; then
|
|
# for bucts-based installation method from factory bios
|
|
xx_ dd if="${rompath}" of="${tmprom}" bs=1 \
|
|
skip=$(($(stat -c %s "${rompath}") - 0x10000)) \
|
|
count=64k
|
|
xx_ dd if="${tmprom}" of="${rompath}" bs=1 \
|
|
seek=$(($(stat -c %s "${rompath}") - 0x20000)) \
|
|
count=64k conv=notrunc
|
|
fi
|
|
xx_ rm -f "${tmprom}"
|
|
}
|
|
|
|
fail()
|
|
{
|
|
[ -z "${codedir}" ] || ./handle make file -c "${codedir}" || :
|
|
err "${1}"
|
|
}
|
|
|
|
main $@
|