#!/usr/bin/env sh # SPDX-License-Identifier: GPL-3.0-or-later # SPDX-FileCopyrightText: 2022-2023 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/option.sh" . "include/git.sh" export LOCALVERSION="-${projectname}-${version%%-*}" eval "$(setvars "" arch cfgsdir codedir config config_name crossgcc_ada mode \ elfdir listfile project romtype target target_dir targets tree _f target1)" main() { while getopts f:b:m:u:c:x:s:l:n: option; do _f="${1}" case "${1}" in -b) : ;; -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" ;; esac shift; project="${OPTARG#src/}"; shift done [ -z "${_f}" ] && err "missing flag (-m/-u/-b/-c/-x/-f/-s/-l/-n)" [ -z "${project}" ] && err "project name not specified" [ -f "config/${project}/build.list" ] && build_targets $@ && return 0 build_projects $@ } build_projects() { [ $# -gt 0 ] && x_ ./update trees ${_f} ${@} if [ "${mode}" = "fetch" ]; then fetch_project_repo return 0 fi codedir="src/${project}" [ -d "${codedir}" ] || x_ ./update trees -f "${project}" 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 } build_targets() { elfdir="elf/${project}" [ "${elfdir}" = "elf/coreboot" ] && \ elfdir="elf/coreboot_nopayload_DO_NOT_FLASH" cfgsdir="config/${project}" [ -d "${cfgsdir}" ] || err "directory, ${cfgsdir}, does not exist" 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=$(items "${cfgsdir}") || \ err "Cannot get options for ${cfgsdir}" [ $# -gt 0 ] && targets=$@ [ -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_ ./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}" } handle_defconfig() { handle_src_tree "${target}" || return 0 if [ "${target1}" = "utils" ] && [ "${project}" = "coreboot" ]; then handle_coreboot_utils "${tree}" return 0 fi 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 "${arch}" ] && err "handle_src_tree $project/$tree: arch unset" [ -z "${tree}" ] && err "handle_src_tree $project/$tree: tree unset" 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 trees -f "${project}" "${target}" fi [ "${target1}" = "utils" ] && [ "${project}" = "coreboot" ] && return 0 [ "$project" != "coreboot" ] && [ "$project" != "u-boot" ] && return 0 # u-boot and coreboot are both compiled with coreboot's crossgcc [ -z "${mode}" ] || return 0 check_cross_compiler } # 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="src/coreboot/${tree}" [ "${project}" != "coreboot" ] && cbdir="src/coreboot/default" # only true if not building coreboot: ctarget="${cbdir#src/coreboot/}" [ -d "${cbdir}" ] || x_ ./update trees -f coreboot ${ctarget} if [ "${arch}" = "x86_32" ] || [ "${arch}" = "x86_64" ]; then [ -d "${cbdir}/util/crossgcc/xgcc/i386-elf/" ] || \ x_ make -C "${cbdir}" crossgcc-i386 CPUS=$(nproc) 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/" ] || \ x_ make -C "${cbdir}" crossgcc-arm CPUS=$(nproc) 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/" ] || \ x_ make -C "${cbdir}" crossgcc-aarch64 CPUS=$(nproc) # aarch64 also needs armv7 toolchain for arm-trusted-firmware [ -d "${cbdir}/util/crossgcc/xgcc/arm-eabi/" ] || \ x_ make -C "${cbdir}" crossgcc-arm CPUS=$(nproc) 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}" ] && \ 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}" } handle_makefile() { 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!" if [ -e "${codedir}/.git" ] && [ "${project}" = "u-boot" ] && \ [ "${mode}" = "distclean" ]; then x_ git -C "${codedir}" clean -fdx elif [ "${mode}" = "oldconfig" ] || [ "${mode}" = "olddefconfig" ] || \ [ "${mode}" = "menuconfig" ] || [ "${mode}" = "nconfig" ]; then x_ cp "${codedir}/.config" "${config}" elif [ "${mode}" = "savedefconfig" ]; then x_ cp "${codedir}/defconfig" "${config}" fi } run_make_command() { [ -f "${codedir}/Makefile" ] || [ -f "${codedir}/makefile" ] || \ [ -f "${codedir}/GNUmakefile" ] || return 1 [ "${project}" = "coreboot" ] && [ -z "${mode}" ] && \ x_ printf "%s\n" "${version%%-*}" >"${codedir}/.coreboot-version" x_ make ${mode} -j$(nproc) -C "${codedir}" [ "${mode}" != "clean" ] && return 0 make -C "${codedir}" distclean 2>/dev/null || : } copy_elf() { [ "${project}" != "coreboot" ] || x_ modify_coreboot_rom while read f; do [ ! -f "${codedir}/$f" ] || \ x_ cp "${codedir}/${f}" "${dest_dir}/" done < ${listfile} x_ make clean -C "${codedir}" } main $@