From 1e89264ce326997f95391e00f1fa71319f1bb226 Mon Sep 17 00:00:00 2001 From: Leah Rowe Date: Sat, 7 Oct 2023 06:55:10 +0100 Subject: update/project/*: merge to update/project/trees Just one script. Just one! Well, two, but the 2nd one already existed: logic in update/project/trees and update/project/repo was merged into include/git.sh and update/project/build was renamed to update/project/trees; an -f option was added, which calls the functions under git.sh so git clones are now handled by the main build script (for handling makefiles and defconfigs) but the logic there is a stub, where git.sh does all the actual heavy lifting this cuts the file count down by two, and reduces sloccount a reasonable amount because much of the logic already exists in the build script, when it comes to handling targets. git.sh was adjusted to integrate with this, rather than act standalone Signed-off-by: Leah Rowe --- script/update/project/trees | 298 +++++++++++++++++++++++++++++++++++--------- 1 file changed, 241 insertions(+), 57 deletions(-) (limited to 'script/update/project/trees') diff --git a/script/update/project/trees b/script/update/project/trees index bb67734a..1055d500 100755 --- a/script/update/project/trees +++ b/script/update/project/trees @@ -1,108 +1,292 @@ #!/usr/bin/env sh # SPDX-License-Identifier: GPL-3.0-or-later -# SPDX-FileCopyrightText: 2014-2016,2020,2021,2023 Leah Rowe # SPDX-FileCopyrightText: 2022 Alper Nebi Yasak # SPDX-FileCopyrightText: 2022 Ferass El Hafidi +# SPDX-FileCopyrightText: 2023 Leah Rowe [ "x${DEBUG+set}" = 'xset' ] && set -v set -u -e . "include/err.sh" -. "include/git.sh" . "include/option.sh" +. "include/git.sh" + +export LOCALVERSION="-${projectname}-${version}" -eval "$(setvars "" _target tree rev project cfgsdir _xm)" +eval "$(setvars "" arch cfgsdir codedir config config_name crossgcc_ada mode \ + elfdir listfile project romtype target target_dir targets tree cbfstool _f \ + target1)" + +tmpclean="$(mktemp -d -t makeclean.XXXXXXXXXX)" main() { - [ -z "${1}" ] && err "project name not specified" - project="${1#src/}" && shift 1 + while getopts f:b:m:u:c:x: option + do + _f="${1}" + case "${1}" in + -b) : ;; + -u) mode="oldconfig" ;; + -m) mode="menuconfig" ;; + -c) mode="distclean" ;; + -x) mode="crossgcc-clean" ;; + -f) mode="fetch" ;; + *) err "Invalid option" ;; + esac + shift; project="${OPTARG#src/}"; shift + done + [ -z "${_f}" ] && err "flag not specified (-m, -u, -b, -c or -x)" + [ -z "${project}" ] && err "project name not specified" + + if [ ! -f "config/${project}/build.list" ]; then + build_projects $@ + else + build_targets $@ + fi +} + +build_projects() +{ + [ $# -gt 0 ] && x_ ./update project trees ${_f} ${@} - configure_targets $@ + if [ "${mode}" = "fetch" ]; then + fetch_project_repo + return 0 + fi - printf "Downloading %s and applying patches\n" ${project} + codedir="src/${project}" + [ -d "${codedir}" ] || x_ ./update project trees -f "${project}" - for x in ${targets}; do - download_for_target "${x}" - done + if [ "${project}" = "uefitool" ]; then + ( + x_ cd src/uefitool + cmake UEFIExtract/ || [ -f Makefile ] || \ + err "build_projects: !cmake UEFIExtract/" + ) + fi + + [ "${mode}" = "distclean" ] && mode="clean" + run_make_command || return 0 } -configure_targets() +build_targets() { + elfdir="elf/${project}" + cfgsdir="config/${project}" - [ -d "${cfgsdir}" ] || err "unsupported project name" + [ -d "${cfgsdir}" ] || err "directory, ${cfgsdir}, does not exist" - targets=$(listitems "${cfgsdir}") + listfile="${cfgsdir}/build.list" + [ -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=$(listitems "${cfgsdir}") || \ + err "Cannot get options for ${cfgsdir}" [ $# -gt 0 ] && targets=$@ - [ -z "${targets}" ] || return 0 - err "No targets for project: ${project}" + [ -z "${mode}" ] && x_ mkdir -p "${elfdir}/" + + handle_targets +} + +handle_targets() +{ + for x in ${targets}; do + target="${x}" + printf "Running 'make %s' for project '%s, target '%s''\n" \ + "${mode}" "${project}" "${target}" + [ "${project}" != "coreboot" ] || [ ! -z ${mode} ] || \ + x_ ./update vendor download ${target} + x_ handle_defconfig + done + + [ "${target1}" = "utils" ] && [ "${project}" = "coreboot" ] && return 0 + [ -z "${mode}" ] || return 0 + printf "Done! The files are stored under %s/\n\n" "${elfdir}" } -download_for_target() +handle_defconfig() { - _target="${1}" + handle_src_tree "${target}" || return 0 - fetch_config - [ -d "src/${project}/${tree}" ] && \ - printf "download/%s %s (%s): exists\n" \ - "${project}" "${tree}" "${_target}" 1>&2 && return 0 + if [ "${target1}" = "utils" ] && [ "${project}" = "coreboot" ]; then + handle_coreboot_utils "${tree}" + return 0 + fi - fetch_from_upstream - prepare_new_tree + 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}" + + [ ! -z ${mode} ] || check_config || continue + handle_makefile + [ ! -z ${mode} ] || copy_elf + done +} + +handle_src_tree() +{ + romtype="normal" + target_dir="${cfgsdir}/${target}" + + if [ "${mode}" = "fetch" ]; then + fetch_project_trees + return 1 + fi + + x_ mkdir -p "${elfdir}/${target}" + eval "$(setvars "" arch tree)" + + . "${target_dir}/target.cfg" || \ + err "handle_src_tree ${target_dir}: cannot load target.cfg" + + [ -z "${tree}" ] && \ + err "handle_src_tree: ${target_dir}: tree undefined" + [ -z "${arch}" ] && \ + err "handle_src_tree: ${target_dir}: undefined cpu type" + + codedir="src/${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 + x_ ./update project trees -f "${project}" "${target}" + elif [ "${mode}" = "distclean" ] || \ + [ "${mode}" = "crossgcc-clean" ]; then + [ -f "${tmpclean}/${tree}" ] && return 1 + touch "${tmpclean}/${tree}" + fi + + [ "${target1}" = "utils" ] && [ "${project}" = "coreboot" ] && return 0 + + # u-boot and coreboot are both compiled with coreboot's crossgcc + if [ "${project}" = "coreboot" ] || [ "${project}" = "u-boot" ]; then + [ ! -z ${mode} ] || check_cross_compiler || \ + err "handle_src_tree ${project}/${target}: crossgcc" + cbfstool="cbutils/${tree}/cbfstool" + [ -f "${cbfstool}" ] || \ + x_ ./update project trees -b coreboot utils "${tree}" + fi } -fetch_config() +# set up cross-compiler (coreboot crossgcc) for u-boot and coreboot +# (seabios and grub currently use hostcc, not crossgcc) +check_cross_compiler() { - x_ rm -f "${cfgsdir}/"*/seen - while true; do - eval "$(setvars "" rev tree)" - _xm="fetch_config ${project}/${_target}" + [ "${crossgcc_ada}" = "y" ] || [ "${crossgcc_ada}" = "n" ] || \ + crossgcc_ada="y" + [ "${crossgcc_ada}" != "y" ] && \ + export BUILD_LANGUAGES=c - check_config_for_target "${_target}" + cbdir="src/coreboot/${tree}" + [ "${project}" != "coreboot" ] && \ + cbdir="src/coreboot/default" # not u-boot (e.g. linux) + [ "${project}" = "u-boot" ] && \ + cbdir="src/coreboot/cros" # u-boot only used on coreboot/cros - # This is to override $rev and $tree - . "${cfgsdir}/${_target}/target.cfg" || \ - err "fetch_config: no \"${cfgsdir}/${_target}/target.cfg\"" + # only true if not building coreboot: + ctarget="${cbdir#src/coreboot/}" + [ -d "${cbdir}" ] || \ + x_ ./update project trees -f 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" +} - [ "${_target}" != "${tree}" ] && _target="${tree}" && continue - [ -z "${tree}" ] && err "${_xm}: tree undefined" - [ -z "${rev}" ] && err "${_xm}: revision undefined" - break +check_config() +{ + [ ! -f "${config}" ] && \ + err "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 + x_ mkdir -p "${dest_dir}" } -check_config_for_target() +handle_makefile() { - [ -f "${cfgsdir}/${1}/target.cfg" ] || \ - err "${_xm} check: target.cfg does not exist" - [ -f "${cfgsdir}/${1}/seen" ] && \ - err "${_xm} check: infinite loop in tree definitions" + x_ make clean -C "${codedir}" + x_ cp "${config}" "${codedir}/.config" + [ ! -z ${mode} ] || make -C "${codedir}" silentoldconfig || \ + make -C "${codedir}" oldconfig || : + + run_make_command || err "handle_makefile ${codedir}: no makefile!" - x_ touch "${cfgsdir}/${1}/seen" + if [ -e "${codedir}/.git" ] && [ "${project}" = "u-boot" ] && \ + [ "${mode}" = "distclean" ]; then + x_ git -C "${codedir}" clean -fdx + elif [ "${mode}" = "oldconfig" ] || [ "${mode}" = "menuconfig" ]; then + x_ cp "${codedir}/.config" "${config}" + fi } -fetch_from_upstream() +run_make_command() { - [ -d "src/${project}/${project}" ] && return 0 + [ -f "${codedir}/Makefile" ] || [ -f "${codedir}/makefile" ] || \ + [ -f "${codedir}/GNUmakefile" ] || return 1 + [ "${project}" = "coreboot" ] && [ -z "${mode}" ] && \ + x_ printf "%s\n" "${version}" >"${codedir}/.coreboot-version" - x_ mkdir -p "src/${project}" - x_ ./update project repo "${project}" + x_ make -C "${codedir}" -j$(nproc) ${mode} + [ "${mode}" != "clean" ] && return 0 + make -C "${codedir}" distclean 2>/dev/null || : } -prepare_new_tree() +copy_elf() { - printf "Creating %s tree %s (%s)\n" "${project}" "${tree}" "${_target}" + [ "${project}" != "coreboot" ] || x_ modify_coreboot_rom + while read f; do + [ ! -f "${codedir}/$f" ] || \ + x_ cp "${codedir}/${f}" "${dest_dir}/" + done < ${listfile} - x_ cp -R "src/${project}/${project}" "src/${project}/${tree}" - x_ git_reset_rev "src/${project}/${tree}" "${rev}" "err" - ( - x_ cd "src/${project}/${tree}" - git submodule update --init --checkout || \ - err "prepare_new_tree ${project}/${tree}: can't update git modules" - ) - git_am_patches "${PWD}/src/${project}/${tree}" \ - "${PWD}/${cfgsdir}/${tree}/patches" "err" + x_ make clean -C "${codedir}" } main $@ -- cgit v1.2.1