Rockchip RK3566 - orangepi-build指令碼分析

大奥特曼打小怪兽發表於2024-07-10

在《Rockchip RK3566 - orangepi-build編譯》我們介紹了SDK的編譯流程,本節將會對編譯指令碼進行深入的分析。

----------------------------------------------------------------------------------------------------------------------------

開發板 :Orange Pi 3B開發板
eMMC32GB
LPDDR48GB
螢幕 :15.6英寸HDMI介面螢幕
u-boot2017.09
linux5.10
----------------------------------------------------------------------------------------------------------------------------

一、build.sh分析

orangepi-build編譯命令是由build.sh指令碼實現的,其指令碼相對來說比較長,這裡我們去掉一些非重點程式碼(比如docker),內容如下:

點選檢視程式碼
# 獲取當前指令碼所在的目錄路徑
SRC="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"

# check for whitespace in ${SRC} and exit for safety reasons 空字串檢驗
grep -q "[[:space:]]" <<<"${SRC}" && { echo "\"${SRC}\" contains whitespace. Not supported. Aborting." >&2 ; exit 1 ; }

cd "${SRC}" || exit

# 啟用呼叫跟蹤
if [[ "${ORANGEPI_ENABLE_CALL_TRACING}" == "yes" ]]; then
        set -T # inherit return/debug traps
        mkdir -p "${SRC}"/output/debug
        echo -n "" > "${SRC}"/output/debug/calls.txt
        trap 'echo "${BASH_LINENO[@]}|${BASH_SOURCE[@]}|${FUNCNAME[@]}" >> ${SRC}/output/debug/calls.txt ;' RETURN
fi

# 執行./script/general.sh指令碼
if [[ -f "${SRC}"/scripts/general.sh ]]; then

        # shellcheck source=scripts/general.sh
        source "${SRC}"/scripts/general.sh

else

        echo "Error: missing build directory structure"
        echo "Please clone the full repository by https://github.com/orangepi-xunlong/orangepi-build"
        exit 255

fi

# 校驗第一個引數
if [[ "${EUID}" == "0" ]] || [[ "${1}" == "vagrant" ]]; then
        :
elif [[ "${1}" == docker || "${1}" == dockerpurge || "${1}" == docker-shell ]] && grep -q "$(whoami)" <(getent group docker); then
        :
else
        # 以root身份執行指令碼
        display_alert "This script requires root privileges, trying to use sudo" "" "wrn"
        sudo "${SRC}/build.sh" "$@"
        exit $?
fi

# 走else分支,為宿主機ubuntu 22.04系統安裝基礎包,比如dialog、uuid、uuid-runtime等
if [ "$OFFLINE_WORK" == "yes" ]; then
        echo -e "\n"
        display_alert "* " "You are working offline."
        display_alert "* " "Sources, time and host will not be checked"
        echo -e "\n"
        sleep 3s
else
        # check and install the basic utilities here 
        prepare_host_basic
fi

EXTER="${SRC}/external"

# Create userpatches directory if not exists
mkdir -p "${SRC}"/userpatches

# Create example configs if none found in userpatches
if ! ls "${SRC}"/userpatches/{config-example.conf,config-docker.conf,config-vagrant.conf} 1> /dev/null 2>&1; then

        # Migrate old configs
        if ls "${SRC}"/*.conf 1> /dev/null 2>&1; then
                display_alert "Migrate config files to userpatches directory" "all *.conf" "info"
                cp "${SRC}"/*.conf "${SRC}"/userpatches  || exit 1
                rm "${SRC}"/*.conf
                [[ ! -L "${SRC}"/userpatches/config-example.conf ]] && ln -fs config-example.conf "${SRC}"/userpatches/config-default.conf || exit 1
        fi

        display_alert "Create example config file using template" "config-default.conf" "info"

        # Create example config
        if [[ ! -f "${SRC}"/userpatches/config-example.conf ]]; then
                cp "${EXTER}"/config/templates/config-example.conf "${SRC}"/userpatches/config-example.conf || exit 1
                ln -fs config-example.conf "${SRC}"/userpatches/config-default.conf || exit 1
        fi

        # Create Docker config
        if [[ ! -f "${SRC}"/userpatches/config-docker.conf ]]; then
                cp "${EXTER}"/config/templates/config-docker.conf "${SRC}"/userpatches/config-docker.conf || exit 1
        fi

        # Create Docker file
        if [[ ! -f "${SRC}"/userpatches/Dockerfile ]]; then
                cp "${EXTER}"/config/templates/Dockerfile "${SRC}"/userpatches/Dockerfile || exit 1
        fi

        # Create Vagrant config
        if [[ ! -f "${SRC}"/userpatches/config-vagrant.conf ]]; then
                cp "${EXTER}"/config/templates/config-vagrant.conf "${SRC}"/userpatches/config-vagrant.conf || exit 1
        fi

        # Create Vagrant file
        if [[ ! -f "${SRC}"/userpatches/Vagrantfile ]]; then
                cp "${EXTER}"/config/templates/Vagrantfile "${SRC}"/userpatches/Vagrantfile || exit 1
        fi

fi

# 不會進入
if [[ -z "${CONFIG}" && -n "$1" && -f "${SRC}/userpatches/config-$1.conf" ]]; then
        CONFIG="userpatches/config-$1.conf"
        shift
fi

# usind default if custom not found
if [[ -z "${CONFIG}" && -f "${SRC}/userpatches/config-default.conf" ]]; then
        CONFIG="userpatches/config-default.conf"
fi
# source build configuration file
CONFIG_FILE="$(realpath "${CONFIG}")"

if [[ ! -f "${CONFIG_FILE}" ]]; then
        display_alert "Config file does not exist" "${CONFIG}" "error"
        exit 254
fi

CONFIG_PATH=$(dirname "${CONFIG_FILE}")

# Source the extensions manager library at this point, before sourcing the config.
# This allows early calls to enable_extension(), but initialization proper is done later.
# shellcheck source=scripts/extensions.sh
source "${SRC}"/scripts/extensions.sh

display_alert "Using config file" "${CONFIG_FILE}" "info"
pushd "${CONFIG_PATH}" > /dev/null || exit
# shellcheck source=/dev/null
source "${CONFIG_FILE}"
popd > /dev/null || exit

[[ -z "${USERPATCHES_PATH}" ]] && USERPATCHES_PATH="${CONFIG_PATH}"

# Script parameters handling
while [[ "${1}" == *=* ]]; do

        parameter=${1%%=*}
        value=${1##*=}
        shift
        display_alert "Command line: setting $parameter to" "${value:-(empty)}" "info"
        eval "$parameter=\"$value\""

done


if [[ "${BUILD_ALL}" == "yes" || "${BUILD_ALL}" == "demo" ]]; then

        # shellcheck source=scripts/build-all-ng.sh
        source "${SRC}"/scripts/build-all-ng.sh

else

        # shellcheck source=scripts/main.sh
        source "${SRC}"/scripts/main.sh

fi

接下來我們針對該指令碼內容從上往下依次分析。

1.1 開啟呼叫追蹤

如果我們需要啟動呼叫跟蹤,在執行命令時設定ORANGEPI_ENABLE_CALL_TRACING即可,比如:

ORANGEPI_ENABLE_CALL_TRACING=yes && ./build.sh

如果環境變數 ORANGEPI_ENABLE_CALL_TRACING 設定為 "yes",將啟用函式呼叫跟蹤;

if [[ "${ORANGEPI_ENABLE_CALL_TRACING}" == "yes" ]]; then
        set -T # inherit return/debug traps
        # 建立除錯目錄
        mkdir -p "${SRC}"/output/debug
        # 初始化一個空的calls.txt檔案,用於儲存除錯資訊
        echo -n "" > "${SRC}"/output/debug/calls.txt
        # 設定一個陷阱,在指令碼退出時記錄函式呼叫詳情 
        trap 'echo "${BASH_LINENO[@]}|${BASH_SOURCE[@]}|${FUNCNAME[@]}" >> ${SRC}/output/debug/calls.txt ;' RETURN
fi

1.2 執行general.sh指令碼

接著是使用source命令執行general.sh指令碼,該指令碼位於<SDK>/scripts目錄下;

if [[ -f "${SRC}"/scripts/general.sh ]]; then
    source "${SRC}"/scripts/general.sh
else
    echo "錯誤:缺少構建目錄結構"
    echo "請透過 https://github.com/orangepi-xunlong/orangepi-build 克隆完整的儲存庫"
    exit 255
fi

使用source命令執行指令碼的一些注意事項:

  • 環境變數和函式的影響:被執行的指令碼可以修改當前shell的環境變數和定義的函式,這些修改將持續影響到當前shell的會話,直到會話結束或者重新定義了這些變數和函式。
  • 退出狀態:被執行的指令碼的退出狀態(即最後一個命令的退出狀態)會影響到當前shell。可以透過$?變數來獲取最近一次執行命令的退出狀態;
  • 互動性:與直接執行指令碼不同,使用source執行指令碼時,不會建立新的shell環境,因此不會有新的子shell程序。這使得它適合於需要指令碼和當前shell環境之間相互影響的場景,例如定義函式或設定環境變數。

1.3 執行prepare_host_basic指令碼

prepare_host_basic指令碼是在general.sh中定義的,為宿主機ubuntu 22.04系統安裝基礎包,比如dialoguuiduuid-runtime等。

1.4 建立userpatches目錄

如果userpatches目錄不存在則建立userpatches目錄;

EXTER="${SRC}/external"

# Create userpatches directory if not exists
mkdir -p "${SRC}"/userpatches
1.4.1 建立example config

接著這段指令碼程式碼主要用於檢查和建立示例配置檔案和相關檔案,如果在 ${SRC}/userpatches 目錄下找不到特定的配置檔案,則建立相應的示例配置檔案和相關檔案;

# Create example configs if none found in userpatches  檢查是否存在示例配置檔案,如果都不存在則進入
if ! ls "${SRC}"/userpatches/{config-example.conf,config-docker.conf,config-vagrant.conf} 1> /dev/null 2>&1; then
        # Migrate old configs  遷移舊配置檔案,不會進入
        if ls "${SRC}"/*.conf 1> /dev/null 2>&1; then
                display_alert "Migrate config files to userpatches directory" "all *.conf" "info"
                cp "${SRC}"/*.conf "${SRC}"/userpatches  || exit 1
                rm "${SRC}"/*.conf
                [[ ! -L "${SRC}"/userpatches/config-example.conf ]] && ln -fs config-example.conf "${SRC}"/userpatches/config-default.conf || exit 1
        fi

        display_alert "Create example config file using template" "config-default.conf" "info"

        # Create example config
        if [[ ! -f "${SRC}"/userpatches/config-example.conf ]]; then
                cp "${EXTER}"/config/templates/config-example.conf "${SRC}"/userpatches/config-example.conf || exit 1
                ln -fs config-example.conf "${SRC}"/userpatches/config-default.conf || exit 1
        fi

        # Create Docker config
        if [[ ! -f "${SRC}"/userpatches/config-docker.conf ]]; then
                cp "${EXTER}"/config/templates/config-docker.conf "${SRC}"/userpatches/config-docker.conf || exit 1
        fi

        # Create Docker file
        if [[ ! -f "${SRC}"/userpatches/Dockerfile ]]; then
                cp "${EXTER}"/config/templates/Dockerfile "${SRC}"/userpatches/Dockerfile || exit 1
        fi

        # Create Vagrant config
        if [[ ! -f "${SRC}"/userpatches/config-vagrant.conf ]]; then
                cp "${EXTER}"/config/templates/config-vagrant.conf "${SRC}"/userpatches/config-vagrant.conf || exit 1
        fi

        # Create Vagrant file
        if [[ ! -f "${SRC}"/userpatches/Vagrantfile ]]; then
                cp "${EXTER}"/config/templates/Vagrantfile "${SRC}"/userpatches/Vagrantfile || exit 1
        fi

fi

檢查是否存在示例配置檔案,如果都不存在:

  • 遷移舊配置檔案:正常不會進入該分支;
  • 建立示例配置檔案:如果 ./userpatches/config-example.conf 不存在,則從 ./external/config/templates/ 目錄複製 config-example.conf./userpatches/ 目錄,並建立一個指向config-example.conf的符號連結 config-default.conf
  • 建立Docker相關檔案:如果./userpatches/config-docker.conf./userpatches/Dockerfile不存在,則分別從 ./external/config/templates/目錄複製config-docker.confDockerfile./userpatches/目錄;
  • 建立Vagrant相關檔案:如果./userpatches/config-vagrant.conf./userpatches/Vagrantfile不存在,則分別從 ./external/config/templates/目錄複製config-vagrant.confVagrantfile${SRC}/userpatches/目錄。

因此執行完成後會在userpatches目錄下建立config-default.confconfig-docker.confconfig-example.confconfig-vagrant.confVagrantfile檔案;

root@ubuntu:/work/sambashare/rk3566/orangepi-build$ ll userpatches/
lrwxrwxrwx  1 root root    19  7月 10 14:20 config-default.conf -> config-example.conf
-rw-r--r--  1 root root  5846  7月 10 14:20 config-docker.conf
-rw-r--r--  1 root root  1274  7月 10 17:57 config-example.conf
-rw-r--r--  1 root root   715  7月 10 14:20 config-vagrant.conf
-rw-r--r--  1 root root  3111  7月 10 14:20 Dockerfile
-rw-r--r--  1 root root  1715  7月 10 14:20 Vagrantfile
1.4.2 使用預設配置

確定要使用的配置檔案路徑,並確保該配置檔案存在。如果未找到任何自定義配置檔案 ($1),則將使用預設配置檔案 (config-default.conf);

# 檢查自定義配置檔案的存在性,由於引數1為指定因此不會進入
if [[ -z "${CONFIG}" && -n "$1" && -f "${SRC}/userpatches/config-$1.conf" ]]; then
        CONFIG="userpatches/config-$1.conf"
        shift
fi

# usind default if custom not found
if [[ -z "${CONFIG}" && -f "${SRC}/userpatches/config-default.conf" ]]; then
        CONFIG="userpatches/config-default.conf"
fi

# source build configuration file, 獲取配置檔案絕對路徑,<SDK>/userpatches/config-example.conf
CONFIG_FILE="$(realpath "${CONFIG}")"

# 檢查配置檔案的實際存在性,由於檔案的確存在因此不會進入
if [[ ! -f "${CONFIG_FILE}" ]]; then
        display_alert "Config file does not exist" "${CONFIG}" "error"
        exit 254
fi

# 獲取配置檔案所在目錄,<SDK>/userpatches
CONFIG_PATH=$(dirname "${CONFIG_FILE}")

1.5 執行extensions.sh指令碼

接著是使用source命令執行extensions.sh指令碼,該指令碼位於<SDK>/scripts目錄下;

# Source the extensions manager library at this point, before sourcing the config.
# This allows early calls to enable_extension(), but initialization proper is done later.
# shellcheck source=scripts/extensions.sh
source "${SRC}"/scripts/extensions.sh

1.6 載入配置檔案

接著是輸出當前使用的配置資料夾資訊,然後切換工作目錄並載入配置檔案:

display_alert "Using config file" "${CONFIG_FILE}" "info"

# 將當前工作目錄切換到 ${CONFIG_PATH}
pushd "${CONFIG_PATH}" > /dev/null || exit

# shellcheck source=/dev/null,載入${CONFIG_FILE}中的shell指令碼
source "${CONFIG_FILE}"

# 恢復之前的工作目錄
popd > /dev/null || exit

# 設定USERPATCHES_PATH=${CONFIG_PATH}
[[ -z "${USERPATCHES_PATH}" ]] && USERPATCHES_PATH="${CONFIG_PATH}"

# Script parameters handling,由於未指定引數1因此不會進入
while [[ "${1}" == *=* ]]; do
        parameter=${1%%=*}
        value=${1##*=}
        shift
        display_alert "Command line: setting $parameter to" "${value:-(empty)}" "info"
        eval "$parameter=\"$value\""
done
1.6.1 config-example.conf

CONFIG_FILE被定義為了<SDK>/userpatches/config-example.conf,內容如下:

KERNEL_CONFIGURE=""                     # leave empty to select each time, set to "yes" or "no" to skip dialog prompt
CLEAN_LEVEL="debs,oldcache"             # comma-separated list of clean targets: "make" = make clean for selected kernel and u-boot,
                                        # "debs" = delete packages in "./output/debs" for current branch and family,
                                        # "alldebs" = delete all packages in "./output/debs", "images" = delete "./output/images",
                                        # "cache" = delete "./output/cache", "sources" = delete "./sources"
                                        # "oldcache" = remove old cached rootfs except for the newest 8 files

DEST_LANG="en_US.UTF-8"                 # sl_SI.UTF-8, en_US.UTF-8

# advanced
EXTERNAL_NEW="prebuilt"                 # compile and install or install prebuilt additional packages
INSTALL_HEADERS=""                      # install kernel headers package
LIB_TAG="master"                        # change to "branchname" to use any branch currently available.
USE_TORRENT="yes"                       # use torrent network for faster toolchain and cache download
DOWNLOAD_MIRROR="china"                 # set to "china" to use mirrors.tuna.tsinghua.edu.cn

BOARD=""
BRANCH=""
RELEASE=""
WIREGUARD="no"
BUILD_KSRC="no"
INSTALL_KSRC="no"
IGNORE_UPDATES="yes"
COMPRESS_OUTPUTIMAGE="no"
NO_APT_CACHER="yes"

#install_balena_etcher="yes"
#install_zfs="yes"
#install_docker="yes"
#install_chromium="yes"
#install_firefox="yes"

該指令碼中定義的一些變數將會被載入到當前shell中。

1.7 進入main.sh

指令碼的最後使用source命令執行main.sh指令碼;

if [[ "${BUILD_ALL}" == "yes" || "${BUILD_ALL}" == "demo" ]]; then
        # shellcheck source=scripts/build-all-ng.sh
        source "${SRC}"/scripts/build-all-ng.sh
else
        # shellcheck source=scripts/main.sh
        source "${SRC}"/scripts/main.sh
fi

二、general.sh分析

general.sh是一個通用指令碼,該指令碼位於<SDK>/scripts目錄下,指令碼提供了通用功能;

  • cleaning
  • exit_with_error
  • get_package_list_hash
  • create_sources_list
  • clean_up_git
  • waiter_local_git
  • fetch_from_repo
  • improved_git
  • distro_menu
  • addtorepo
  • repo-remove-old-packages
  • wait_for_package_manager
  • install_pkg_deb
  • prepare_host_basic
  • prepare_host
  • webseed
  • download_and_verify
  • show_developer_warning
  • show_checklist_variables

2.1 display_alert

display_alert用於在終端中顯示帶有不同型別標籤的警告資訊;

#--------------------------------------------------------------------------------------------------------------------------------
# Let's have unique way of displaying alerts
#--------------------------------------------------------------------------------------------------------------------------------
display_alert()
{
        # log function parameters to install.log
        [[ -n "${DEST}" ]] && echo "Displaying message: $@" >> "${DEST}"/${LOG_SUBPATH}/output.log

        local tmp=""
        [[ -n $2 ]] && tmp="[\e[0;33m $2 \x1B[0m]"

		# 根據第三個引數 $3 的不同取值,輸出不同型別的警告資訊
        case $3 in
                err)
                # 紅色文字
                echo -e "[\e[0;31m error \x1B[0m] $1 $tmp"
                ;;

                wrn)
                # 洋紅色文字
                echo -e "[\e[0;35m warn \x1B[0m] $1 $tmp"
                ;;

                ext)
                # 綠色文字
                echo -e "[\e[0;32m o.k. \x1B[0m] \e[1;32m$1\x1B[0m $tmp"
                ;;

                info)
                # 加粗綠色文字
                echo -e "[\e[0;32m o.k. \x1B[0m] $1 $tmp"
                ;;

                *)
                # 綠色樣式(作為通用資訊)
                echo -e "[\e[0;32m .... \x1B[0m] $1 $tmp"
                ;;
        esac
}

2.2 prepare_host_basic

prepare_host_basic為宿主機ubuntu 22.04系統安裝基礎包,比如dialoguuiduuid-runtime等;

# prepare_host_basic
#
# * installs only basic packages
#
prepare_host_basic()
{
        # command:package1 package2 ...
        # list of commands that are neeeded:packages where this command is
        local check_pack install_pack
        local checklist=(
                        "whiptail:whiptail"
                        "dialog:dialog"
                        "fuser:psmisc"
                        "getfacl:acl"
                        "uuid:uuid uuid-runtime"
                        "curl:curl"
                        "gpg:gnupg"
                        "gawk:gawk"
                        "git:git"
                        )

        for check_pack in "${checklist[@]}"; do
                # 使用which命令檢查 ${check_pack%:*}是否存在,如果不存在(即返回非零退出碼),則將${check_pack#*:}新增到install_pack變數中。
                # ${check_pack%:*}:刪除最後一個冒號:及其右側的部分,保留左側的命令名稱部分
                # ${check_pack#*:}:刪除第一個冒號:及其左側的部分,保留右側的軟體包名稱部分
                if ! which ${check_pack%:*} >/dev/null; then local install_pack+=${check_pack#*:}" "; fi
        done

		# 不為空,則顯示安裝基本軟體包
        if [[ -n $install_pack ]]; then
                display_alert "Installing basic packages" "$install_pack"
                sudo bash -c "apt-get -qq update && apt-get install -qq -y --no-install-recommends $install_pack"
        fi
}

三、extensions.sh分析

四、main.sh分析

main.sh指令碼位於<SDK>/scripts目錄下,該指令碼比較重要,可以認為就是編譯的主程式。

這裡我們去掉一些非重點程式碼(比如docker),內容如下:

點選檢視程式碼
#!/bin/bash
#
# Copyright (c) 2013-2021 Igor Pecovnik, igor.pecovnik@gma**.com
#
# This file is licensed under the terms of the GNU General Public
# License version 2. This program is licensed "as is" without any
# warranty of any kind, whether express or implied.
#
# Main program
#


cleanup_list() {
        local varname="${1}"
        local list_to_clean="${!varname}"
        list_to_clean="${list_to_clean#"${list_to_clean%%[![:space:]]*}"}"
        list_to_clean="${list_to_clean%"${list_to_clean##*[![:space:]]}"}"
        echo ${list_to_clean}
}




if [[ $(basename "$0") == main.sh ]]; then

        echo "Please use build.sh to start the build process"
        exit 255

fi




# default umask for root is 022 so parent directories won't be group writeable without this
# this is used instead of making the chmod in prepare_host() recursive
umask 002

# destination
if [ -d "$CONFIG_PATH/output" ]; then
        DEST="${CONFIG_PATH}"/output
else
        DEST="${SRC}"/output
fi

[[ -z $REVISION ]] && REVISION="3.0.8"

[[ $DOWNLOAD_MIRROR == "china" ]] && NTP_SERVER="cn.pool.ntp.org"

if [[ $BUILD_ALL != "yes" ]]; then
        # override stty size
        [[ -n $COLUMNS ]] && stty cols $COLUMNS
        [[ -n $LINES ]] && stty rows $LINES
        TTY_X=$(($(stty size | awk '{print $2}')-6))                    # determine terminal width
        TTY_Y=$(($(stty size | awk '{print $1}')-6))                    # determine terminal height
fi

# We'll use this title on all menus
backtitle="Orange Pi building script, http://www.orangepi.org"
titlestr="Choose an option"

# Warnings mitigation
[[ -z $LANGUAGE ]] && export LANGUAGE="en_US:en"            # set to english if not set
[[ -z $CONSOLE_CHAR ]] && export CONSOLE_CHAR="UTF-8"       # set console to UTF-8 if not set
# Libraries include

# shellcheck source=debootstrap.sh
source "${SRC}"/scripts/debootstrap.sh  # system specific install
# shellcheck source=image-helpers.sh
source "${SRC}"/scripts/image-helpers.sh        # helpers for OS image building
# shellcheck source=distributions.sh
source "${SRC}"/scripts/distributions.sh        # system specific install
# shellcheck source=desktop.sh
source "${SRC}"/scripts/desktop.sh              # desktop specific install
# shellcheck source=compilation.sh
source "${SRC}"/scripts/compilation.sh  # patching and compilation of kernel, uboot, ATF
# shellcheck source=compilation-prepare.sh
#source "${SRC}"/scripts/compilation-prepare.sh # drivers that are not upstreamed
# shellcheck source=makeboarddeb.sh
source "${SRC}"/scripts/makeboarddeb.sh         # board support package
# shellcheck source=general.sh
source "${SRC}"/scripts/general.sh              # general functions
# shellcheck source=chroot-buildpackages.sh
source "${SRC}"/scripts/chroot-buildpackages.sh # chroot packages building
# shellcheck source=pack.sh
source "${SRC}"/scripts/pack-uboot.sh


# set log path
LOG_SUBPATH=${LOG_SUBPATH:=debug}

# compress and remove old logs
mkdir -p "${DEST}"/${LOG_SUBPATH}
(cd "${DEST}"/${LOG_SUBPATH} && tar -czf logs-"$(<timestamp)".tgz ./*.log) > /dev/null 2>&1
rm -f "${DEST}"/${LOG_SUBPATH}/*.log > /dev/null 2>&1
date +"%d_%m_%Y-%H_%M_%S" > "${DEST}"/${LOG_SUBPATH}/timestamp

# delete compressed logs older than 7 days
(cd "${DEST}"/${LOG_SUBPATH} && find . -name '*.tgz' -mtime +7 -delete) > /dev/null

if [[ $PROGRESS_DISPLAY == none ]]; then

        OUTPUT_VERYSILENT=yes

elif [[ $PROGRESS_DISPLAY == dialog ]]; then

        OUTPUT_DIALOG=yes

fi

if [[ $PROGRESS_LOG_TO_FILE != yes ]]; then unset PROGRESS_LOG_TO_FILE; fi



SHOW_WARNING=yes
if [[ $USE_CCACHE != no ]]; then

        CCACHE=ccache
        export PATH="/usr/lib/ccache:$PATH"
        # private ccache directory to avoid permission issues when using build script with "sudo"
        # see https://ccache.samba.org/manual.html#_sharing_a_cache for alternative solution
        [[ $PRIVATE_CCACHE == yes ]] && export CCACHE_DIR=$EXTER/cache/ccache

else

        CCACHE=""

fi




if [[ -n $REPOSITORY_UPDATE ]]; then

                # select stable/beta configuration
                if [[ $BETA == yes ]]; then
                                DEB_STORAGE=$DEST/debs-beta
                                REPO_STORAGE=$DEST/repository-beta
                                REPO_CONFIG="aptly-beta.conf"
                else
                                DEB_STORAGE=$DEST/debs
                                REPO_STORAGE=$DEST/repository
                                REPO_CONFIG="aptly.conf"
                fi

                # For user override
                if [[ -f "${USERPATCHES_PATH}"/lib.config ]]; then
                                display_alert "Using user configuration override" "userpatches/lib.config" "info"
                        source "${USERPATCHES_PATH}"/lib.config
                fi

                repo-manipulate "$REPOSITORY_UPDATE"
                exit

fi



# if BUILD_OPT, KERNEL_CONFIGURE, BOARD, BRANCH or RELEASE are not set, display selection menu
if [[ -z $BUILD_OPT ]]; then

        options+=("u-boot"       "U-boot package")
        options+=("kernel"       "Kernel package")
        options+=("rootfs"       "Rootfs and all deb packages")
        options+=("image"        "Full OS image for flashing")

        menustr="Compile image | rootfs | kernel | u-boot"
        BUILD_OPT=$(whiptail --title "${titlestr}" --backtitle "${backtitle}" --notags \
                          --menu "${menustr}" "${TTY_Y}" "${TTY_X}" $((TTY_Y - 8))  \
                          --cancel-button Exit --ok-button Select "${options[@]}" \
                          3>&1 1>&2 2>&3)

        unset options
        [[ -z $BUILD_OPT ]] && exit_with_error "No option selected"
        [[ $BUILD_OPT == rootfs ]] && ROOT_FS_CREATE_ONLY="yes"
fi
if [[ ${BUILD_OPT} =~ kernel|image ]]; then

        if [[ -z $KERNEL_CONFIGURE ]]; then

                options+=("no" "Do not change the kernel configuration")
                options+=("yes" "Show a kernel configuration menu before compilation")

                menustr="Select the kernel configuration."
                KERNEL_CONFIGURE=$(whiptail --title "${titlestr}" --backtitle "$backtitle" --notags \
                                                 --menu "${menustr}" $TTY_Y $TTY_X $((TTY_Y - 8)) \
                                                 --cancel-button Exit --ok-button Select "${options[@]}" \
                                                 3>&1 1>&2 2>&3)

                unset options
                [[ -z $KERNEL_CONFIGURE ]] && exit_with_error "No option selected"
        fi
fi
if [[ -z $BOARD ]]; then

        #options+=("orangepir1"                 "Allwinner H2+ quad core 256MB RAM WiFi SPI 2xETH")
        #options+=("orangepizero"               "Allwinner H2+ quad core 256MB/512MB RAM WiFi SPI")
        #options+=("orangepipc"                 "Allwinner H3 quad core 1GB RAM")
        #options+=("orangepipcplus"             "Allwinner H3 quad core 1GB RAM WiFi eMMC")
        #options+=("orangepione"                        "Allwinner H3 quad core 512MB RAM")
        #options+=("orangepilite"               "Allwinner H3 quad core 512MB RAM WiFi")
        #options+=("orangepiplus"               "Allwinner H3 quad core 1GB/2GB RAM WiFi GBE eMMC")
        #options+=("orangepiplus2e"             "Allwinner H3 quad core 2GB RAM WiFi GBE eMMC")
        #options+=("orangepizeroplus2h3"        "Allwinner H3 quad core 512MB RAM WiFi/BT eMMC")
        #options+=("orangepipch5"                "Allwinner H5 quad core 1GB RAM")
        #options+=("orangepipc2"                        "Allwinner H5 quad core 1GB RAM GBE SPI")
        #options+=("orangepioneh5"               "Allwinner H5 quad core 512MB/1GB RAM")
        #options+=("orangepiprime"              "Allwinner H5 quad core 2GB RAM GBE WiFi/BT")
        #options+=("orangepizeroplus"           "Allwinner H5 quad core 512MB RAM GBE WiFi SPI")
        #options+=("orangepizeroplus2h5"                "Allwinner H5 quad core 512MB RAM WiFi/BT eMMC")
        options+=("orangepi3"                   "Allwinner H6 quad core 1GB/2GB RAM GBE WiFi/BT eMMC USB3")
        options+=("orangepi3-lts"               "Allwinner H6 quad core 2GB RAM GBE WiFi/BT-AW859A eMMC USB3")
        #options+=("orangepilite2"              "Allwinner H6 quad core 1GB RAM WiFi/BT USB3")
        #options+=("orangepioneplus"            "Allwinner H6 quad core 1GB RAM GBE")
        options+=("orangepizero2"               "Allwinner H616 quad core 512MB/1GB RAM WiFi/BT GBE SPI")
        #options+=("orangepizero2-b"            "Allwinner H616 quad core 512MB/1GB RAM WiFi/BT GBE SPI")
        #options+=("orangepizero2-lts"           "Allwinner H616 quad core 1.5GB RAM WiFi/BT GBE SPI")
        options+=("orangepizero3"               "Allwinner H618 quad core 1GB/1.5GB/2GB/4GB RAM WiFi/BT GBE SPI")
        options+=("orangepizero2w"              "Allwinner H618 quad core 1GB/1.5GB/2GB/4GB RAM WiFi/BT SPI")
        #options+=("orangepir1b"                        "Allwinner H618 quad core 1.5GB/2GB/4GB RAM WiFi/BT GBE SPI")
        #options+=("orangepi400"                        "Allwinner H616 quad core 4GB RAM WiFi/BT GBE eMMC VGA")
        options+=("orangepi4"                   "Rockchip  RK3399 hexa core 4GB RAM GBE eMMC USB3 USB-C WiFi/BT")
        options+=("orangepi4-lts"                 "Rockchip  RK3399 hexa core 4GB RAM GBE eMMC USB3 USB-C WiFi/BT")
        options+=("orangepi800"                 "Rockchip  RK3399 hexa core 4GB RAM GBE eMMC USB3 USB-C WiFi/BT VGA")
        options+=("orangepi5"                 "Rockchip  RK3588S octa core 4-16GB RAM GBE USB3 USB-C NVMe")
        options+=("orangepicm5"                 "Rockchip  RK3588S octa core 4-16GB RAM GBE USB3 USB-C")
        options+=("orangepicm5-tablet"           "Rockchip  RK3588S octa core 4-16GB RAM USB3 USB-C WiFi/BT")
        options+=("orangepi5b"                 "Rockchip  RK3588S octa core 4-16GB RAM GBE USB3 USB-C WiFi/BT eMMC")
        #options+=("orangepitab"                 "Rockchip  RK3588S octa core 4-16GB RAM USB-C WiFi/BT NVMe")
        #options+=("orangepi900"                 "Rockchip  RK3588 octa core 4-16GB RAM 2.5GBE USB3 USB-C WiFi/BT NVMe")
        options+=("orangepi5pro"                 "Rockchip  RK3588S octa core 4-16GB RAM GBE USB3 WiFi/BT NVMe eMMC")
        options+=("orangepi5max"                 "Rockchip  RK3588 octa core 4-16GB RAM 2.5GBE USB3 WiFi/BT NVMe eMMC")
        options+=("orangepi5plus"                 "Rockchip  RK3588 octa core 4-32GB RAM 2.5GBE USB3 USB-C WiFi/BT NVMe eMMC")
        options+=("orangepicm4"                 "Rockchip  RK3566 quad core 2-8GB RAM GBE eMMC USB3 NvMe WiFi/BT")
        options+=("orangepi3b"                  "Rockchip  RK3566 quad core 2-8GB RAM GBE eMMC USB3 NvMe WiFi/BT")
        #options+=("orangepir1plus"              "Rockchip  RK3328 quad core 1GB RAM 2xGBE USB2 SPI")
        #options+=("orangepi3plus"              "Amlogic S905D3 quad core 2/4GB RAM SoC eMMC GBE USB3 SPI WiFi/BT")

        menustr="Please choose a Board."
        BOARD=$(whiptail --title "${titlestr}" --backtitle "${backtitle}" \
                          --menu "${menustr}" "${TTY_Y}" "${TTY_X}" $((TTY_Y - 8))  \
                          --cancel-button Exit --ok-button Select "${options[@]}" \
                          3>&1 1>&2 2>&3)

        unset options
        [[ -z $BOARD ]] && exit_with_error "No option selected"
fi
BOARD_TYPE="conf"
# shellcheck source=/dev/null
source "${EXTER}/config/boards/${BOARD}.${BOARD_TYPE}"
LINUXFAMILY="${BOARDFAMILY}"

[[ -z $KERNEL_TARGET ]] && exit_with_error "Board configuration does not define valid kernel config"

if [[ -z $BRANCH ]]; then

        options=()
        [[ $KERNEL_TARGET == *current* ]] && options+=("current" "Recommended. Come with best support")
        [[ $KERNEL_TARGET == *legacy* ]] && options+=("legacy" "Old stable / Legacy")
        [[ $KERNEL_TARGET == *next* ]] && options+=("next" "Use the latest kernel")

        menustr="Select the target kernel branch\nExact kernel versions depend on selected board"
        # do not display selection dialog if only one kernel branch is available
        if [[ "${#options[@]}" == 2 ]]; then
                BRANCH="${options[0]}"
        else
                BRANCH=$(whiptail --title "${titlestr}" --backtitle "${backtitle}" \
                                  --menu "${menustr}" "${TTY_Y}" "${TTY_X}" $((TTY_Y - 8))  \
                                  --cancel-button Exit --ok-button Select "${options[@]}" \
                                  3>&1 1>&2 2>&3)
        fi
        unset options
        [[ -z $BRANCH ]] && exit_with_error "No kernel branch selected"
        [[ $BRANCH == dev && $SHOW_WARNING == yes ]] && show_developer_warning

fi

if [[ -z ${MEM_TYPE} && ${BOARD} =~ orangepizero3|orangepir1b|orangepizero2w && ${BUILD_OPT} =~ u-boot|image && ${BRANCH} == next ]]; then

        options+=("1500MB"    "1.5 GB Memory")
        options+=("Others"    "1/2/4 GB Memory")

        menustr="Please choose memory size for ${BOARD}."
        MEM_TYPE=$(whiptail --title "${titlestr}" --backtitle "${backtitle}" \
                          --menu "${menustr}" "${TTY_Y}" "${TTY_X}" $((TTY_Y - 8))  \
                          --cancel-button Exit --ok-button Select "${options[@]}" \
                          3>&1 1>&2 2>&3)

        unset options
        [[ -z $MEM_TYPE ]] && exit_with_error "No option selected"
fi

if [[ $BUILD_OPT =~ rootfs|image && -z $RELEASE ]]; then

        options=()

        distros_options

        menustr="Select the target OS release package base"
        RELEASE=$(whiptail --title "Choose a release package base" --backtitle "${backtitle}" \
                          --menu "${menustr}" "${TTY_Y}" "${TTY_X}" $((TTY_Y - 8))  \
                          --cancel-button Exit --ok-button Select "${options[@]}" \
                          3>&1 1>&2 2>&3)
        #echo "options : ${options}"
        [[ -z $RELEASE ]] && exit_with_error "No release selected"

        unset options
fi
# don't show desktop option if we choose minimal build
[[ $BUILD_MINIMAL == yes ]] && BUILD_DESKTOP=no

if [[ $BUILD_OPT =~ rootfs|image && -z $BUILD_DESKTOP ]]; then

        # read distribution support status which is written to the orangepi-release file
        set_distribution_status

        options=()
        options+=("no" "Image with console interface (server)")
        options+=("yes" "Image with desktop environment")

        menustr="Select the target image type"
        BUILD_DESKTOP=$(whiptail --title "Choose image type" --backtitle "${backtitle}" \
                          --menu "${menustr}" "${TTY_Y}" "${TTY_X}" $((TTY_Y - 8))  \
                          --cancel-button Exit --ok-button Select "${options[@]}" \
                          3>&1 1>&2 2>&3)
        unset options
        [[ -z $BUILD_DESKTOP ]] && exit_with_error "No option selected"
        if [[ ${BUILD_DESKTOP} == "yes" ]]; then
                BUILD_MINIMAL=no
                SELECTED_CONFIGURATION="desktop"
        fi

fi

if [[ $BUILD_OPT =~ rootfs|image && $BUILD_DESKTOP == no && -z $BUILD_MINIMAL ]]; then

        options=()
        options+=("no" "Standard image with console interface")
        options+=("yes" "Minimal image with console interface")
        menustr="Select the target image type"
        BUILD_MINIMAL=$(whiptail --title "Choose image type" --backtitle "${backtitle}" \
                          --menu "${menustr}" "${TTY_Y}" "${TTY_X}" $((TTY_Y - 8))  \
                          --cancel-button Exit --ok-button Select "${options[@]}" \
                          3>&1 1>&2 2>&3)
        unset options
        [[ -z $BUILD_MINIMAL ]] && exit_with_error "No option selected"
        if [[ $BUILD_MINIMAL == "yes" ]]; then
                SELECTED_CONFIGURATION="cli_minimal"
        else
                SELECTED_CONFIGURATION="cli_standard"
        fi

fi

#prevent conflicting setup
if [[ $BUILD_DESKTOP == "yes" ]]; then
        BUILD_MINIMAL=no
        SELECTED_CONFIGURATION="desktop"
elif [[ $BUILD_MINIMAL != "yes" || -z "${BUILD_MINIMAL}" ]]; then
        BUILD_MINIMAL=no # Just in case BUILD_MINIMAL is not defined
        BUILD_DESKTOP=no
        SELECTED_CONFIGURATION="cli_standard"
elif [[ $BUILD_MINIMAL == "yes" ]]; then
        BUILD_DESKTOP=no
        SELECTED_CONFIGURATION="cli_minimal"
fi
#[[ ${KERNEL_CONFIGURE} == prebuilt ]] && [[ -z ${REPOSITORY_INSTALL} ]] && \
#REPOSITORY_INSTALL="u-boot,kernel,bsp,orangepi-zsh,orangepi-config,orangepi-firmware${BUILD_DESKTOP:+,orangepi-desktop}"


#shellcheck source=configuration.sh
source "${SRC}"/scripts/configuration.sh

# optimize build time with 100% CPU usage
CPUS=$(grep -c 'processor' /proc/cpuinfo)
if [[ $USEALLCORES != no ]]; then

        CTHREADS="-j$((CPUS + CPUS/2))"

else

        CTHREADS="-j1"

fi

call_extension_method "post_determine_cthreads" "config_post_determine_cthreads" << 'POST_DETERMINE_CTHREADS'
*give config a chance modify CTHREADS programatically. A build server may work better with hyperthreads-1 for example.*
Called early, before any compilation work starts.
POST_DETERMINE_CTHREADS

if [[ $BETA == yes ]]; then
        IMAGE_TYPE=nightly
elif [[ $BETA != "yes" && $BUILD_ALL == yes && -n $GPG_PASS ]]; then
        IMAGE_TYPE=stable
else
        IMAGE_TYPE=user-built
fi

branch2dir() {
        [[ "${1}" == "head" ]] && echo "HEAD" || echo "${1##*:}"
}

BOOTSOURCEDIR="${BOOTDIR}/$(branch2dir "${BOOTBRANCH}")"
LINUXSOURCEDIR="${KERNELDIR}/$(branch2dir "${KERNELBRANCH}")"
[[ -n $ATFSOURCE ]] && ATFSOURCEDIR="${ATFDIR}/$(branch2dir "${ATFBRANCH}")"

BSP_CLI_PACKAGE_NAME="orangepi-bsp-cli-${BOARD}"
BSP_CLI_PACKAGE_FULLNAME="${BSP_CLI_PACKAGE_NAME}_${REVISION}_${ARCH}"
BSP_DESKTOP_PACKAGE_NAME="orangepi-bsp-desktop-${BOARD}"
BSP_DESKTOP_PACKAGE_FULLNAME="${BSP_DESKTOP_PACKAGE_NAME}_${REVISION}_${ARCH}"

CHOSEN_UBOOT=linux-u-boot-${BRANCH}-${BOARD}
CHOSEN_KERNEL=linux-image-${BRANCH}-${LINUXFAMILY}
CHOSEN_ROOTFS=${BSP_CLI_PACKAGE_NAME}
CHOSEN_DESKTOP=orangepi-${RELEASE}-desktop-${DESKTOP_ENVIRONMENT}
CHOSEN_KSRC=linux-source-${BRANCH}-${LINUXFAMILY}

do_default() {

start=$(date +%s)

# Check and install dependencies, directory structure and settings
# The OFFLINE_WORK variable inside the function
prepare_host

[[ "${JUST_INIT}" == "yes" ]] && exit 0

[[ $CLEAN_LEVEL == *sources* ]] && cleaning "sources"

# fetch_from_repo <url> <dir> <ref> <subdir_flag>
# ignore updates help on building all images - for internal purposes
if [[ ${IGNORE_UPDATES} != yes ]]; then

        display_alert "Downloading sources" "" "info"

        [[ $BUILD_OPT =~ u-boot|image ]] && fetch_from_repo "$BOOTSOURCE" "$BOOTDIR" "$BOOTBRANCH" "yes"
        [[ $BUILD_OPT =~ kernel|image ]] && fetch_from_repo "$KERNELSOURCE" "$KERNELDIR" "$KERNELBRANCH" "yes"

        if [[ -n ${ATFSOURCE} ]]; then

                [[ ${BUILD_OPT} =~ u-boot|image ]] && fetch_from_repo "$ATFSOURCE" "${EXTER}/cache/sources/$ATFDIR" "$ATFBRANCH" "yes"

        fi

        if [[ ${BOARD} =~ orangepi4|orangepi4-lts|orangepi800 && $BRANCH == legacy ]]; then

                [[ $BUILD_OPT =~ image ]] && fetch_from_repo "https://github.com/orangepi-xunlong/rk3399_gst_xserver_libs.git" "${EXTER}/cache/sources/rk3399_gst_xserver_libs" "branch:main"

        fi

        if [[ ${BOARD} =~ orangepi4|orangepi4-lts|orangepi800 && $RELEASE =~ focal|buster|bullseye|bookworm ]]; then

                [[ ${BUILD_OPT} == image ]] && fetch_from_repo "https://github.com/orangepi-xunlong/rk-rootfs-build.git" "${EXTER}/cache/sources/rk-rootfs-build-${RELEASE}" "branch:rk-rootfs-build-${RELEASE}"

        fi

        if [[ ${BOARDFAMILY} == "rockchip-rk3588" && $RELEASE =~ bullseye|bookworm|focal|jammy|raspi ]]; then

                [[ ${BUILD_OPT} == image ]] && fetch_from_repo "https://github.com/orangepi-xunlong/rk-rootfs-build.git" "${EXTER}/cache/sources/rk35xx_packages" "branch:rk35xx_packages"

        fi

        if [[ ${BOARDFAMILY} == "rockchip-rk356x" && $RELEASE =~ bullseye|focal|jammy|raspi ]]; then

                [[ ${BUILD_OPT} == image ]] && fetch_from_repo "https://github.com/orangepi-xunlong/rk-rootfs-build.git" "${EXTER}/cache/sources/rk35xx_packages" "branch:rk35xx_packages"

        fi

        if [[ ${BOARD} =~ orangepi3|orangepi3-lts && $RELEASE =~ bullseye && $BRANCH == current ]]; then

                [[ ${BUILD_OPT} == image ]] && fetch_from_repo "https://github.com/orangepi-xunlong/rk-rootfs-build.git" "${EXTER}/cache/sources/ffmpeg_kodi_${RELEASE}" "branch:ffmpeg_kodi_${RELEASE}"

        fi

        if [[ ${BOARD} =~ orangepi4|orangepi4-lts|orangepi800 && $RELEASE =~ jammy && $BRANCH == next ]]; then

                [[ ${BUILD_OPT} == image ]] && fetch_from_repo "https://github.com/orangepi-xunlong/rk-rootfs-build.git" "${EXTER}/cache/sources/ffmpeg_kodi_${RELEASE}" "branch:ffmpeg_kodi_${RELEASE}"

        fi

        call_extension_method "fetch_sources_tools"  <<- 'FETCH_SOURCES_TOOLS'
        *fetch host-side sources needed for tools and build*
        Run early to fetch_from_repo or otherwise obtain sources for needed tools.
        FETCH_SOURCES_TOOLS

        call_extension_method "build_host_tools"  <<- 'BUILD_HOST_TOOLS'
        *build needed tools for the build, host-side*
        After sources are fetched, build host-side tools needed for the build.
        BUILD_HOST_TOOLS
        if [[ ${BOARDFAMILY} == "rockchip-rk3588" ]]; then
                local rkbin_url="https://github.com/orangepi-xunlong/rk-rootfs-build/raw/rkbin/rk35"
                wget -nc -P ${EXTER}/cache/sources/rkbin-tools/rk35/ ${rkbin_url}/rk3588_bl31_v1.45_20240422.elf
        fi

fi

for option in $(tr ',' ' ' <<< "$CLEAN_LEVEL"); do
        [[ $option != sources ]] && cleaning "$option"
done

# Compile u-boot if packed .deb does not exist or use the one from Orange Pi
if [[ $BUILD_OPT == u-boot || $BUILD_OPT == image ]]; then

        if [[ ! -f "${DEB_STORAGE}"/u-boot/${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb ]]; then

                [[ -n "${ATFSOURCE}" && "${REPOSITORY_INSTALL}" != *u-boot* ]] && compile_atf

                [[ ${REPOSITORY_INSTALL} != *u-boot* ]] && compile_uboot
        fi

        if [[ $BUILD_OPT == "u-boot" ]]; then
                unset BUILD_MINIMAL BUILD_DESKTOP COMPRESS_OUTPUTIMAGE
                display_alert "U-boot build done" "@host" "info"
                display_alert "Target directory" "${DEB_STORAGE}/u-boot" "info"
                display_alert "File name" "${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb" "info"
        fi
fi

# Compile kernel if packed .deb does not exist or use the one from Orange Pi
if [[ $BUILD_OPT == kernel || $BUILD_OPT == image ]]; then

        if [[ ! -f ${DEB_STORAGE}/${CHOSEN_KERNEL}_${REVISION}_${ARCH}.deb ]]; then

                KDEB_CHANGELOG_DIST=$RELEASE
                [[ "${REPOSITORY_INSTALL}" != *kernel* ]] && compile_kernel
        fi

        if [[ $BUILD_OPT == "kernel" ]]; then
                unset BUILD_MINIMAL BUILD_DESKTOP COMPRESS_OUTPUTIMAGE
                display_alert "Kernel build done" "@host" "info"
                display_alert "Target directory" "${DEB_STORAGE}/" "info"
                display_alert "File name" "${CHOSEN_KERNEL}_${REVISION}_${ARCH}.deb" "info"
        fi
fi
if [[ $BUILD_OPT == rootfs || $BUILD_OPT == image ]]; then

        # Compile orangepi-config if packed .deb does not exist or use the one from Orange Pi
        if [[ ! -f ${DEB_STORAGE}/orangepi-config_${REVISION}_all.deb ]]; then

                [[ "${REPOSITORY_INSTALL}" != *orangepi-config* ]] && compile_orangepi-config
        fi

        # Compile orangepi-zsh if packed .deb does not exist or use the one from repository
        if [[ ! -f ${DEB_STORAGE}/orangepi-zsh_${REVISION}_all.deb ]]; then

                [[ "${REPOSITORY_INSTALL}" != *orangepi-zsh* ]] && compile_orangepi-zsh
        fi

        # Compile plymouth-theme-orangepi if packed .deb does not exist or use the one from repository
        if [[ ! -f ${DEB_STORAGE}/plymouth-theme-orangepi_${REVISION}_all.deb ]]; then

                [[ "${REPOSITORY_INSTALL}" != *plymouth-theme-orangepi* ]] && compile_plymouth-theme-orangepi
        fi

        # Compile orangepi-firmware if packed .deb does not exist or use the one from repository
        if [[ "${REPOSITORY_INSTALL}" != *orangepi-firmware* ]]; then

                if ! ls "${DEB_STORAGE}/orangepi-firmware_${REVISION}_all.deb" 1> /dev/null 2>&1; then

                        FULL=""
                        REPLACE="-full"
                        compile_firmware

                fi

                #if ! ls "${DEB_STORAGE}/orangepi-firmware-full_${REVISION}_all.deb" 1> /dev/null 2>&1; then

                        #FULL="-full"
                        #REPLACE=""
                        #compile_firmware

                #fi

        fi

        overlayfs_wrapper "cleanup"

        # create board support package
        [[ -n $RELEASE && ! -f ${DEB_STORAGE}/$RELEASE/${BSP_CLI_PACKAGE_FULLNAME}.deb ]] && create_board_package

        # create desktop package
        #[[ -n $RELEASE && $DESKTOP_ENVIRONMENT && ! -f ${DEB_STORAGE}/$RELEASE/${CHOSEN_DESKTOP}_${REVISION}_all.deb ]] && create_desktop_package
        #[[ -n $RELEASE && $DESKTOP_ENVIRONMENT && ! -f ${DEB_STORAGE}/${RELEASE}/${BSP_DESKTOP_PACKAGE_FULLNAME}.deb ]] && create_bsp_desktop_package
        [[ -n $RELEASE && $DESKTOP_ENVIRONMENT ]] && create_desktop_package
        [[ -n $RELEASE && $DESKTOP_ENVIRONMENT ]] && create_bsp_desktop_package

        # build additional packages
        [[ $EXTERNAL_NEW == compile ]] && chroot_build_packages

        [[ $BSP_BUILD != yes ]] && debootstrap_ng

fi
# hook for function to run after build, i.e. to change owner of $SRC
# NOTE: this will run only if there were no errors during build process
[[ $(type -t run_after_build) == function ]] && run_after_build || true

end=$(date +%s)
runtime=$(((end-start)/60))
display_alert "Runtime" "$runtime min" "info"

# Make it easy to repeat build by displaying build options used
[ "$(systemd-detect-virt)" == 'docker' ] && BUILD_CONFIG='docker'

display_alert "Repeat Build Options" "sudo ./build.sh ${BUILD_CONFIG} BOARD=${BOARD} BRANCH=${BRANCH} \
$([[ -n $BUILD_OPT ]] && echo "BUILD_OPT=${BUILD_OPT} ")\
$([[ -n $RELEASE ]] && echo "RELEASE=${RELEASE} ")\
$([[ -n $BUILD_MINIMAL ]] && echo "BUILD_MINIMAL=${BUILD_MINIMAL} ")\
$([[ -n $BUILD_DESKTOP ]] && echo "BUILD_DESKTOP=${BUILD_DESKTOP} ")\
$([[ -n $KERNEL_CONFIGURE ]] && echo "KERNEL_CONFIGURE=${KERNEL_CONFIGURE} ")\
$([[ -n $DESKTOP_ENVIRONMENT ]] && echo "DESKTOP_ENVIRONMENT=${DESKTOP_ENVIRONMENT} ")\
$([[ -n $DESKTOP_ENVIRONMENT_CONFIG_NAME  ]] && echo "DESKTOP_ENVIRONMENT_CONFIG_NAME=${DESKTOP_ENVIRONMENT_CONFIG_NAME} ")\
$([[ -n $DESKTOP_APPGROUPS_SELECTED ]] && echo "DESKTOP_APPGROUPS_SELECTED=\"${DESKTOP_APPGROUPS_SELECTED}\" ")\
$([[ -n $DESKTOP_APT_FLAGS_SELECTED ]] && echo "DESKTOP_APT_FLAGS_SELECTED=\"${DESKTOP_APT_FLAGS_SELECTED}\" ")\
$([[ -n $COMPRESS_OUTPUTIMAGE ]] && echo "COMPRESS_OUTPUTIMAGE=${COMPRESS_OUTPUTIMAGE} ")\
" "ext"

} # end of do_default()

if [[ -z $1 ]]; then
        do_default
else
        eval "$@"
f

相關文章