程序项目代做,有需求私信(vue、React、Java、爬虫、电路板设计、嵌入式linux等)

Rockchip RK3566 - orangepi-build脚本分析

在《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
}

2.3 distros_options

distros_options函数用于获取Linux发行版的类型;

DISTRIBUTIONS_DESC_DIR="external/config/distributions"

function distro_menu ()
{
# create a select menu for choosing a distribution based EXPERT status

        local distrib_dir="${1}"
		# 查目录 ${distrib_dir}是否存在且包含文件${distrib_dir}/support
        if [[ -d "${distrib_dir}" && -f "${distrib_dir}/support" ]]; then
		        # 读取 ${distrib_dir}/support文件中的支持级别
                local support_level="$(cat "${distrib_dir}/support")"
                # 如果分发的支持级别不是"supported"并且EXPERT不等于"yes",则跳过该分发
                if [[ "${support_level}" != "supported" && $EXPERT != "yes" ]]; then
                        :
                else
                		# 读取分发的名称和全名
                        local distro_codename="$(basename "${distrib_dir}")"
                        local distro_fullname="$(cat "${distrib_dir}/name")"
                        local expert_infos=""
                        
                        # 不会进入
                        [[ $EXPERT == "yes" ]] && expert_infos="(${support_level})"
                        
                        # 根据BRANCH的值设置DISTRIB_TYPE变量
                        if [[ "${BRANCH}" == "legacy" ]]; then
                                DISTRIB_TYPE="${DISTRIB_TYPE_LEGACY}"
                                [[ -z "${DISTRIB_TYPE_LEGACY}" ]] && DISTRIB_TYPE="buster bionic focal"
                        elif [[ "${BRANCH}" == "current" ]]; then
                                DISTRIB_TYPE="${DISTRIB_TYPE_CURRENT}"
                                [[ -z "${DISTRIB_TYPE_CURRENT}" ]] && DISTRIB_TYPE="bullseye bookworm focal jammy"
                        elif [[ "${BRANCH}" == "next" ]]; then
                                if [[ -n "${DISTRIB_TYPE_NEXT}" ]]; then
                                        DISTRIB_TYPE="${DISTRIB_TYPE_NEXT}"
                                else
                                        DISTRIB_TYPE="${DISTRIB_TYPE_CURRENT}"
                                        [[ -z "${DISTRIB_TYPE_CURRENT}" ]] && DISTRIB_TYPE="bullseye bookworm focal jammy"
                                fi
                        fi

                        if [[ "${DISTRIB_TYPE}" =~ "${distro_codename}" ]]; then
                                options+=("${distro_codename}" "${distro_fullname} ${expert_infos}")
                        fi
                fi
        fi
}

function distros_options() {
        for distrib_dir in "${DISTRIBUTIONS_DESC_DIR}/"*; do
                distro_menu "${distrib_dir}"
        done
}

我们查看external/config/distributions目录;

root@ubuntu:/work/sambashare/rk3566/orangepi-build$ ll external/config/distributions
drwxr-xr-x  2 root root 4096  7月 10 13:40 bionic/
drwxr-xr-x  2 root root 4096  7月 10 13:40 bookworm/
drwxr-xr-x  2 root root 4096  7月 10 13:40 bullseye/
drwxr-xr-x  2 root root 4096  7月 10 13:40 buster/
drwxr-xr-x  2 root root 4096  7月 10 13:40 focal/
drwxr-xr-x  2 root root 4096  7月 10 13:40 jammy/
drwxr-xr-x  2 root root 4096  7月 10 13:40 raspi/
-rw-r--r--  1 root root  297  7月 10 13:40 README.md
drwxr-xr-x  2 root root 4096  7月 10 13:40 sid/
drwxr-xr-x  2 root root 4096  7月 10 13:40 stretch/
drwxr-xr-x  2 root root 4096  7月 10 13:40 xenial/

bullseye目录为例;

root@ubuntu:/work/sambashare/rk3566/orangepi-build$ ll external/config/distributions/bullseye/
-rw-r--r--  1 root root   19  7月 10 13:40 name
-rw-r--r--  1 root root   10  7月 10 13:40 support

查看support文件内容,这里为supported,所以support_level=supported

查看name文件内容,这里为Debian 11 Bullseye,所以distro_codename=bullseyedistro_fullname=Debian 11 Bullseye

所以当BRANCH=current时,设置DISTRIB_TYPE=bullseye bookworm focal jammy

DISTRIB_TYPE="${DISTRIB_TYPE_CURRENT}"
[[ -z "${DISTRIB_TYPE_CURRENT}" ]] && DISTRIB_TYPE="bullseye bookworm focal jammy"

函数最后设置:

options+=("${distro_codename}" "${distro_fullname} ${expert_infos}")
即:
bullseye Debian 11 Bullseye

三、compilation.sh分析

compilation.sh脚本位于<SDK>/scripts目录下,实现了各个功能模块源码的编译;

  • compile_atf
  • compile_uboot
  • compile_kernel;
  • compile_firmware;
  • compile_orangepi-config
  • compile_sunxi_tools
  • install_rkbin_tools
  • grab_version
  • find_toolchain
  • advanced_patch
  • process_patch_file
  • userpatch_create
  • overlayfs_wrapper

3.1 compile_uboot

compile_uboot()
{

        if [[ ${BOARDFAMILY} == "sun50iw9" && ${BRANCH} =~ legacy|current && $(dpkg --print-architecture) == arm64 ]]; then

                local uboot_name=${CHOSEN_UBOOT}_${REVISION}_${ARCH}.deb
                display_alert "Compile u-boot is not supported, only copy precompiled deb package" "$uboot_name" "info"
                cp "${EXTER}/cache/debs/h618/$uboot_name" "${DEB_STORAGE}/u-boot/"
        else

        # not optimal, but extra cleaning before overlayfs_wrapper should keep sources directory clean
        if [[ $CLEAN_LEVEL == *make* ]]; then
                display_alert "Cleaning" "$BOOTSOURCEDIR" "info"
                (cd $BOOTSOURCEDIR; make clean > /dev/null 2>&1)
        fi

        if [[ $USE_OVERLAYFS == yes ]]; then
                local ubootdir
                ubootdir=$(overlayfs_wrapper "wrap" "$BOOTSOURCEDIR" "u-boot_${LINUXFAMILY}_${BRANCH}")
        else
                local ubootdir="$BOOTSOURCEDIR"
        fi
        cd "${ubootdir}" || exit

        # read uboot version
        local version hash
        version=$(grab_version "$ubootdir")
        hash=$(improved_git --git-dir="$ubootdir"/.git rev-parse HEAD)

        display_alert "Compiling u-boot" "v$version" "info"

        # build aarch64
        if [[ $(dpkg --print-architecture) == amd64 ]]; then

                local toolchain
                toolchain=$(find_toolchain "$UBOOT_COMPILER" "$UBOOT_USE_GCC")
                [[ -z $toolchain ]] && exit_with_error "Could not find required toolchain" "${UBOOT_COMPILER}gcc $UBOOT_USE_GCC"

                if [[ -n $UBOOT_TOOLCHAIN2 ]]; then
                        local toolchain2_type toolchain2_ver toolchain2
                        toolchain2_type=$(cut -d':' -f1 <<< "${UBOOT_TOOLCHAIN2}")
                        toolchain2_ver=$(cut -d':' -f2 <<< "${UBOOT_TOOLCHAIN2}")
                        toolchain2=$(find_toolchain "$toolchain2_type" "$toolchain2_ver")
                        [[ -z $toolchain2 ]] && exit_with_error "Could not find required toolchain" "${toolchain2_type}gcc $toolchain2_ver"
                fi

                # build aarch64
        fi
        display_alert "Compiler version" "${UBOOT_COMPILER}gcc $(eval env PATH="${toolchain}:${toolchain2}:${PATH}" "${UBOOT_COMPILER}gcc" -dumpversion)" "info"
        [[ -n $toolchain2 ]] && display_alert "Additional compiler version" "${toolchain2_type}gcc $(eval env PATH="${toolchain}:${toolchain2}:${PATH}" "${toolchain2_type}gcc" -dumpversion)" "info"

        # create directory structure for the .deb package
        uboottempdir=$(mktemp -d)
        chmod 700 ${uboottempdir}
        trap "ret=\$?; rm -rf \"${uboottempdir}\" ; exit \$ret" 0 1 2 3 15
        local uboot_name=${CHOSEN_UBOOT}_${REVISION}_${ARCH}
        rm -rf $uboottempdir/$uboot_name
        mkdir -p $uboottempdir/$uboot_name/usr/lib/{u-boot,$uboot_name} $uboottempdir/$uboot_name/DEBIAN

        # process compilation for one or multiple targets
        while read -r target; do
                local target_make target_patchdir target_files
                target_make=$(cut -d';' -f1 <<< "${target}")
                target_patchdir=$(cut -d';' -f2 <<< "${target}")
                target_files=$(cut -d';' -f3 <<< "${target}")

                # needed for multiple targets and for calling compile_uboot directly
                #display_alert "Checking out to clean sources"
                #improved_git checkout -f -q HEAD

                if [[ $CLEAN_LEVEL == *make* ]]; then
                        display_alert "Cleaning" "$BOOTSOURCEDIR" "info"
                        (cd "${BOOTSOURCEDIR}"; make clean > /dev/null 2>&1)
                fi

                advanced_patch "u-boot" "$BOOTPATCHDIR" "$BOARD" "$target_patchdir" "$BRANCH" "${LINUXFAMILY}-${BOARD}-${BRANCH}"

                # create patch for manual source changes
                [[ $CREATE_PATCHES == yes ]] && userpatch_create "u-boot"

                if [[ -n $ATFSOURCE ]]; then
                        cp -Rv "${atftempdir}"/*.bin .
                        rm -rf "${atftempdir}"
                fi

                echo -e "\n\t== u-boot make $BOOTCONFIG ==\n" >> "${DEST}"/${LOG_SUBPATH}/compilation.log
                eval CCACHE_BASEDIR="$(pwd)" env PATH="${toolchain}:${toolchain2}:${PATH}" \
                        'make $CTHREADS $BOOTCONFIG \
                        CROSS_COMPILE="$CCACHE $UBOOT_COMPILER"' 2>> "${DEST}"/${LOG_SUBPATH}/compilation.log \
                        ${PROGRESS_LOG_TO_FILE:+' | tee -a $DEST/${LOG_SUBPATH}/compilation.log'} \
                        ${OUTPUT_VERYSILENT:+' >/dev/null 2>/dev/null'}

                if [[ "${version}" != 2014.07 ]]; then
                       # orangepi specifics u-boot settings
                        [[ -f .config ]] && sed -i 's/CONFIG_LOCALVERSION=""/CONFIG_LOCALVERSION="-orangepi"/g' .config
                        [[ -f .config ]] && sed -i 's/CONFIG_LOCALVERSION_AUTO=.*/# CONFIG_LOCALVERSION_AUTO is not set/g' .config

                        # for modern kernel and non spi targets
                        if [[ ${BOOTBRANCH} =~ ^tag:v201[8-9](.*) && ${target} != "spi" && -f .config ]]; then

                                sed -i 's/^.*CONFIG_ENV_IS_IN_FAT.*/# CONFIG_ENV_IS_IN_FAT is not set/g' .config
                                sed -i 's/^.*CONFIG_ENV_IS_IN_EXT4.*/CONFIG_ENV_IS_IN_EXT4=y/g' .config
                                sed -i 's/^.*CONFIG_ENV_IS_IN_MMC.*/# CONFIG_ENV_IS_IN_MMC is not set/g' .config
                                sed -i 's/^.*CONFIG_ENV_IS_NOWHERE.*/# CONFIG_ENV_IS_NOWHERE is not set/g' .config | echo \
                                "# CONFIG_ENV_IS_NOWHERE is not set" >> .config
                                echo 'CONFIG_ENV_EXT4_INTERFACE="mmc"' >> .config
                                echo 'CONFIG_ENV_EXT4_DEVICE_AND_PART="0:auto"' >> .config
                                echo 'CONFIG_ENV_EXT4_FILE="/boot/boot.env"' >> .config

                        fi

                        if [[ ${BOARDFAMILY} == "sun50iw9" && ${BRANCH} == "next" ]]; then
                                if [[ ${MEM_TYPE} == "1500MB" ]]; then

                                        sed -i 's/^.*CONFIG_DRAM_SUN50I_H616_TRIM_SIZE*/CONFIG_DRAM_SUN50I_H616_TRIM_SIZE=y/g' .config
                                else
                                        sed -i 's/^.*CONFIG_DRAM_SUN50I_H616_TRIM_SIZE*/# CONFIG_DRAM_SUN50I_H616_TRIM_SIZE is not set/g' .config
                                fi
                        fi

                        [[ -f tools/logos/udoo.bmp ]] && cp "${EXTER}"/packages/blobs/splash/udoo.bmp tools/logos/udoo.bmp
                        touch .scmversion

                        # $BOOTDELAY can be set in board family config, ensure autoboot can be stopped even if set to 0
                        [[ $BOOTDELAY == 0 ]] && echo -e "CONFIG_ZERO_BOOTDELAY_CHECK=y" >> .config
                        [[ -n $BOOTDELAY ]] && sed -i "s/^CONFIG_BOOTDELAY=.*/CONFIG_BOOTDELAY=${BOOTDELAY}/" .config || [[ -f .config ]] && echo "CONFIG_BOOTDELAY=${BOOTDELAY}" >> .config

                fi

                # workaround when two compilers are needed
                cross_compile="CROSS_COMPILE=$CCACHE $UBOOT_COMPILER";
                [[ -n $UBOOT_TOOLCHAIN2 ]] && cross_compile="ORANGEPI=foe"; # empty parameter is not allowed

                echo -e "\n\t== u-boot make $target_make ==\n" >> "${DEST}"/${LOG_SUBPATH}/compilation.log
                eval CCACHE_BASEDIR="$(pwd)" env PATH="${toolchain}:${toolchain2}:${PATH}" \
                        'make $target_make $CTHREADS \
                        "${cross_compile}"' 2>>"${DEST}"/${LOG_SUBPATH}/compilation.log \
                        ${PROGRESS_LOG_TO_FILE:+' | tee -a "${DEST}"/${LOG_SUBPATH}/compilation.log'} \
                        ${OUTPUT_DIALOG:+' | dialog --backtitle "$backtitle" --progressbox "Compiling u-boot..." $TTY_Y $TTY_X'} \
                        ${OUTPUT_VERYSILENT:+' >/dev/null 2>/dev/null'} ';EVALPIPE=(${PIPESTATUS[@]})'

                [[ ${EVALPIPE[0]} -ne 0 ]] && exit_with_error "U-boot compilation failed"

                [[ $(type -t uboot_custom_postprocess) == function ]] && uboot_custom_postprocess
                # copy files to build directory
                for f in $target_files; do
                        local f_src
                        f_src=$(cut -d':' -f1 <<< "${f}")
                        if [[ $f == *:* ]]; then
                                local f_dst
                                f_dst=$(cut -d':' -f2 <<< "${f}")
                        else
                                local f_dst
                                f_dst=$(basename "${f_src}")
                        fi
                        [[ ! -f $f_src ]] && exit_with_error "U-boot file not found" "$(basename "${f_src}")"
                        if [[ "${version}" =~ 2014.07|2011.09 ]]; then
                                cp "${f_src}" "$uboottempdir/packout/${f_dst}"
                        else
                                cp "${f_src}" "$uboottempdir/${uboot_name}/usr/lib/${uboot_name}/${f_dst}"
                        fi
                done
        done <<< "$UBOOT_TARGET_MAP"

        if [[ $PACK_UBOOT == "yes" ]];then
                if [[ $BOARDFAMILY =~ sun50iw1 ]]; then
                        if [[ $(type -t u-boot_tweaks) == function ]]; then
                                u-boot_tweaks ${uboot_name}
                        else
                                exit_with_error "U-boot pack failed"
                        fi
                else
                        pack_uboot
                        cp $uboottempdir/packout/{boot0_sdcard.fex,boot_package.fex} "${SRC}/.tmp/${uboot_name}/usr/lib/${uboot_name}/"
                        cp $uboottempdir/packout/dts/${BOARD}-u-boot.dts "${SRC}/.tmp/${uboot_name}/usr/lib/u-boot/"
                fi
                cd "${ubootdir}" || exit
        fi

        # declare -f on non-defined function does not do anything
        cat <<-EOF > "$uboottempdir/${uboot_name}/usr/lib/u-boot/platform_install.sh"
        DIR=/usr/lib/$uboot_name
        $(declare -f write_uboot_platform)
        $(declare -f write_uboot_platform_mtd)
        $(declare -f setup_write_uboot_platform)
        EOF

        # set up control file
        cat <<-EOF > "$uboottempdir/${uboot_name}/DEBIAN/control"
        Package: linux-u-boot-${BOARD}-${BRANCH}
        Version: $REVISION
        Architecture: $ARCH
        Maintainer: $MAINTAINER <$MAINTAINERMAIL>
        Installed-Size: 1
        Section: kernel
        Priority: optional
        Provides: orangepi-u-boot
        Replaces: orangepi-u-boot
        Conflicts: orangepi-u-boot, u-boot-sunxi
        Description: Uboot loader $version
        EOF

        # copy config file to the package
        # useful for FEL boot with overlayfs_wrapper
        [[ -f .config && -n $BOOTCONFIG ]] && cp .config "$uboottempdir/${uboot_name}/usr/lib/u-boot/${BOOTCONFIG}"
        # copy license files from typical locations
        [[ -f COPYING ]] && cp COPYING "$uboottempdir/${uboot_name}/usr/lib/u-boot/LICENSE"
        [[ -f Licenses/README ]] && cp Licenses/README "$uboottempdir/${uboot_name}/usr/lib/u-boot/LICENSE"
        [[ -n $atftempdir && -f $atftempdir/license.md ]] && cp "${atftempdir}/license.md" "$uboottempdir/${uboot_name}/usr/lib/u-boot/LICENSE.atf"

        display_alert "Building deb" "${uboot_name}.deb" "info"
        fakeroot dpkg-deb -b -Z${DEB_COMPRESS} "$uboottempdir/${uboot_name}" "$uboottempdir/${uboot_name}.deb" >> "${DEST}"/${LOG_SUBPATH}/output.log 2>&1
        rm -rf "$uboottempdir/${uboot_name}"
        [[ -n $atftempdir ]] && rm -rf "${atftempdir}"

        [[ ! -f $uboottempdir/${uboot_name}.deb ]] && exit_with_error "Building u-boot package failed"

        rsync --remove-source-files -rq "$uboottempdir/${uboot_name}.deb" "${DEB_STORAGE}/u-boot/"
        rm -rf "$uboottempdir"

        fi
}

3.2 compile_kernel

compile_kernel()
{
        if [[ $CLEAN_LEVEL == *make* ]]; then
                display_alert "Cleaning" "$LINUXSOURCEDIR" "info"
                (cd ${LINUXSOURCEDIR}; make ARCH="${ARCHITECTURE}" clean >/dev/null 2>&1)
        fi

        if [[ $USE_OVERLAYFS == yes ]]; then
                local kerneldir
                kerneldir=$(overlayfs_wrapper "wrap" "$LINUXSOURCEDIR" "kernel_${LINUXFAMILY}_${BRANCH}")
        else
                local kerneldir="$LINUXSOURCEDIR"
        fi
        cd "${kerneldir}" || exit

        rm -f localversion

        # read kernel version
        local version hash
        version=$(grab_version "$kerneldir")

        # read kernel git hash
        hash=$(improved_git --git-dir="$kerneldir"/.git rev-parse HEAD)

        # Apply a series of patches if a series file exists
        if test -f "${EXTER}"/patch/kernel/${KERNELPATCHDIR}/series.conf; then
                display_alert "series.conf file visible. Apply"
                series_conf="${SRC}"/patch/kernel/${KERNELPATCHDIR}/series.conf

                # apply_patch_series <target dir> <full path to series file>
                apply_patch_series "${kerneldir}" "$series_conf"
        fi

        # build 3rd party drivers
        # compilation_prepare

        advanced_patch "kernel" "$KERNELPATCHDIR" "$BOARD" "" "$BRANCH" "$LINUXFAMILY-$BRANCH"

        # create patch for manual source changes in debug mode
        [[ $CREATE_PATCHES == yes ]] && userpatch_create "kernel"

        # re-read kernel version after patching
        local version
        version=$(grab_version "$kerneldir")

        display_alert "Compiling $BRANCH kernel" "$version" "info"

        # compare with the architecture of the current Debian node
        # if it matches we use the system compiler
        if $(dpkg-architecture -e "${ARCH}"); then
                display_alert "Native compilation"
        elif [[ $(dpkg --print-architecture) == amd64 ]]; then
                local toolchain
                toolchain=$(find_toolchain "$KERNEL_COMPILER" "$KERNEL_USE_GCC")
                [[ -z $toolchain ]] && exit_with_error "Could not find required toolchain" "${KERNEL_COMPILER}gcc $KERNEL_USE_GCC"
        else
                exit_with_error "Architecture [$ARCH] is not supported"
        fi

        display_alert "Compiler version" "${KERNEL_COMPILER}gcc $(eval env PATH="${toolchain}:${PATH}" "${KERNEL_COMPILER}gcc" -dumpversion)" "info"

        # copy kernel config
        if [[ $KERNEL_KEEP_CONFIG == yes && -f "${DEST}"/config/$LINUXCONFIG.config ]]; then
                display_alert "Using previous kernel config" "${DEST}/config/$LINUXCONFIG.config" "info"
                cp -p "${DEST}/config/${LINUXCONFIG}.config" .config
        else
                if [[ -f $USERPATCHES_PATH/$LINUXCONFIG.config ]]; then
                        display_alert "Using kernel config provided by user" "userpatches/$LINUXCONFIG.config" "info"
                        cp -p "${USERPATCHES_PATH}/${LINUXCONFIG}.config" .config
                else
                        display_alert "Using kernel config file" "${EXTER}/config/kernel/$LINUXCONFIG.config" "info"
                        cp -p "${EXTER}/config/kernel/${LINUXCONFIG}.config" .config
                fi
        fi

        call_extension_method "custom_kernel_config" << 'CUSTOM_KERNEL_CONFIG'
*Kernel .config is in place, still clean from git version*
Called after ${LINUXCONFIG}.config is put in place (.config).
Before any olddefconfig any Kconfig make is called.
A good place to customize the .config directly.
CUSTOM_KERNEL_CONFIG


        # hack for deb builder. To pack what's missing in headers pack.
        cp "$EXTER"/patch/misc/headers-debian-byteshift.patch /tmp

        if [[ $KERNEL_CONFIGURE != yes ]]; then
                if [[ $BRANCH == legacy && ! $BOARDFAMILY =~ "rockchip-rk3588"|"rockchip-rk356x" ]]; then
                        eval CCACHE_BASEDIR="$(pwd)" env PATH="${toolchain}:${PATH}" \
                                'make ARCH=$ARCHITECTURE CROSS_COMPILE="$CCACHE $KERNEL_COMPILER" silentoldconfig'
                else
                        # TODO: check if required
                        eval CCACHE_BASEDIR="$(pwd)" env PATH="${toolchain}:${PATH}" \
                                'make ARCH=$ARCHITECTURE CROSS_COMPILE="$CCACHE $KERNEL_COMPILER" olddefconfig'
                fi
        else
                eval CCACHE_BASEDIR="$(pwd)" env PATH="${toolchain}:${PATH}" \
                        'make $CTHREADS ARCH=$ARCHITECTURE CROSS_COMPILE="$CCACHE $KERNEL_COMPILER" oldconfig'
                eval CCACHE_BASEDIR="$(pwd)" env PATH="${toolchain}:${PATH}" \
                        'make $CTHREADS ARCH=$ARCHITECTURE CROSS_COMPILE="$CCACHE $KERNEL_COMPILER" ${KERNEL_MENUCONFIG:-menuconfig}'

                [[ ${PIPESTATUS[0]} -ne 0 ]] && exit_with_error "Error kernel menuconfig failed"

                # store kernel config in easily reachable place
                display_alert "Exporting new kernel config" "$DEST/config/$LINUXCONFIG.config" "info"
                cp .config "${DEST}/config/${LINUXCONFIG}.config"
                cp .config "${EXTER}/config/kernel/${LINUXCONFIG}.config"
                # export defconfig too if requested
                if [[ $KERNEL_EXPORT_DEFCONFIG == yes ]]; then
                        eval CCACHE_BASEDIR="$(pwd)" env PATH="${toolchain}:${PATH}" \
                                'make ARCH=$ARCHITECTURE CROSS_COMPILE="$CCACHE $KERNEL_COMPILER" savedefconfig'
                        [[ -f defconfig ]] && cp defconfig "${DEST}/config/${LINUXCONFIG}.defconfig"
                fi
        fi

        # create linux-source package - with already patched sources
        # We will build this package first and clear the memory.
        if [[ $BUILD_KSRC != no ]]; then
                create_linux-source_package
        fi

        echo -e "\n\t== kernel ==\n" >> "${DEST}"/${LOG_SUBPATH}/compilation.log
        eval CCACHE_BASEDIR="$(pwd)" env PATH="${toolchain}:${PATH}" \
                'make $CTHREADS ARCH=$ARCHITECTURE \
                CROSS_COMPILE="$CCACHE $KERNEL_COMPILER" \
                $SRC_LOADADDR \
                LOCALVERSION="-$LINUXFAMILY" \
                $KERNEL_IMAGE_TYPE ${KERNEL_EXTRA_TARGETS:-modules dtbs} 2>>$DEST/${LOG_SUBPATH}/compilation.log' \
                ${PROGRESS_LOG_TO_FILE:+' | tee -a $DEST/${LOG_SUBPATH}/compilation.log'} \
                ${OUTPUT_DIALOG:+' | dialog --backtitle "$backtitle" \
                --progressbox "Compiling kernel..." $TTY_Y $TTY_X'} \
                ${OUTPUT_VERYSILENT:+' >/dev/null 2>/dev/null'}

        if [[ ${PIPESTATUS[0]} -ne 0 || ! -f arch/$ARCHITECTURE/boot/$KERNEL_IMAGE_TYPE ]]; then
                grep -i error $DEST/${LOG_SUBPATH}/compilation.log
                exit_with_error "Kernel was not built" "@host"
        fi

        # different packaging for 4.3+
        if linux-version compare "${version}" ge 4.3; then
                local kernel_packing="bindeb-pkg"
        else
                local kernel_packing="deb-pkg"
        fi

        #if [[ $BRANCH == legacy && $LINUXFAMILY =~ sun50iw2|sun50iw6|sun50iw9 ]]; then
        #       make -C modules/gpu LICHEE_MOD_DIR=${SRC}/.tmp/gpu_modules_${LINUXFAMILY} LICHEE_KDIR=${kerneldir} CROSS_COMPILE=$toolchain/$KERNEL_COMPILER ARCH=$ARCHITECTURE
        #fi

        display_alert "Creating packages"

        # produce deb packages: image, headers, firmware, dtb
        echo -e "\n\t== deb packages: image, headers, firmware, dtb ==\n" >> "${DEST}"/${LOG_SUBPATH}/compilation.log
        eval CCACHE_BASEDIR="$(pwd)" env PATH="${toolchain}:${PATH}" \
                'make $CTHREADS $kernel_packing \
                KDEB_PKGVERSION=$REVISION \
                KDEB_COMPRESS=${DEB_COMPRESS} \
                BRANCH=$BRANCH \
                LOCALVERSION="-${LINUXFAMILY}" \
                KBUILD_DEBARCH=$ARCH \
                ARCH=$ARCHITECTURE \
                DEBFULLNAME="$MAINTAINER" \
                DEBEMAIL="$MAINTAINERMAIL" \
                CROSS_COMPILE="$CCACHE $KERNEL_COMPILER" 2>>$DEST/${LOG_SUBPATH}/compilation.log' \
                ${PROGRESS_LOG_TO_FILE:+' | tee -a $DEST/${LOG_SUBPATH}/compilation.log'} \
                ${OUTPUT_DIALOG:+' | dialog --backtitle "$backtitle" --progressbox "Creating kernel packages..." $TTY_Y $TTY_X'} \
                ${OUTPUT_VERYSILENT:+' >/dev/null 2>/dev/null'}

        cd .. || exit
        # remove firmare image packages here - easier than patching ~40 packaging scripts at once
        rm -f linux-firmware-image-*.deb

        rsync --remove-source-files -rq ./*.deb "${DEB_STORAGE}/" || exit_with_error "Failed moving kernel DEBs"     
}

3.3 compile_firmware

compile_firmware()
{
        display_alert "Merging and packaging linux firmware" "@host" "info"

        local firmwaretempdir plugin_dir

        firmwaretempdir=$(mktemp -d)
        chmod 700 ${firmwaretempdir}
        trap "ret=\$?; rm -rf \"${firmwaretempdir}\" ; exit \$ret" 0 1 2 3 15
        plugin_dir="orangepi-firmware${FULL}"
        mkdir -p "${firmwaretempdir}/${plugin_dir}/lib/firmware"

        [[ $IGNORE_UPDATES != yes ]] && fetch_from_repo "https://github.com/orangepi-xunlong/firmware" "${EXTER}/cache/sources/orangepi-firmware-git" "branch:master"
        if [[ -n $FULL ]]; then
                [[ $IGNORE_UPDATES != yes ]] && fetch_from_repo "$MAINLINE_FIRMWARE_SOURCE" "${EXTER}/cache/sources/linux-firmware-git" "branch:master"
                # cp : create hardlinks
                cp -af --reflink=auto "${EXTER}"/cache/sources/linux-firmware-git/* "${firmwaretempdir}/${plugin_dir}/lib/firmware/"
        fi
        # overlay our firmware
        # cp : create hardlinks
        cp -af --reflink=auto "${EXTER}"/cache/sources/orangepi-firmware-git/* "${firmwaretempdir}/${plugin_dir}/lib/firmware/"

        # cleanup what's not needed for sure
        rm -rf "${firmwaretempdir}/${plugin_dir}"/lib/firmware/{amdgpu,amd-ucode,radeon,nvidia,matrox,.git}
        cd "${firmwaretempdir}/${plugin_dir}" || exit

        # set up control file
        mkdir -p DEBIAN
        cat <<-END > DEBIAN/control
        Package: orangepi-firmware${FULL}
        Version: $REVISION
        Architecture: all
        Maintainer: $MAINTAINER <$MAINTAINERMAIL>
        Installed-Size: 1
        Replaces: linux-firmware, firmware-brcm80211, firmware-ralink, firmware-samsung, firmware-realtek, orangepi-firmware${REPLACE}
        Section: kernel
        Priority: optional
        Description: Linux firmware${FULL}
        END

        cd "${firmwaretempdir}" || exit
        # pack
        mv "orangepi-firmware${FULL}" "orangepi-firmware${FULL}_${REVISION}_all"
        display_alert "Building firmware package" "orangepi-firmware${FULL}_${REVISION}_all" "info"
        fakeroot dpkg-deb -b -Z${DEB_COMPRESS} "orangepi-firmware${FULL}_${REVISION}_all" >> "${DEST}"/${LOG_SUBPATH}/install.log 2>&1
        mv "orangepi-firmware${FULL}_${REVISION}_all" "orangepi-firmware${FULL}"
        rsync -rq "orangepi-firmware${FULL}_${REVISION}_all.deb" "${DEB_STORAGE}/"

        # remove temp directory
        rm -rf "${firmwaretempdir}"
}

四、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}
}

# 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"

# 进入,根据终端的当前尺寸设置 TTY_X(宽度)和 TTY_Y(高度)
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

# 设置缓存目录
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 BUILD_OPT, KERNEL_CONFIGURE, BOARD, BRANCH or RELEASE are not set, display selection menu
# 创建了一个用户界面,用户可以从菜单中选择构建选项(u-boot、kernel、rootfs、image)
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

# 如果选择了kernel或image则进入,选择内核配置
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

# 加载板载配置文件external/config/boards/orangepi3b.conf
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

# 如果选择了kernel或image,并且未设置RELEASE则进入选择Linux发行版的类型
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,如果设置了Minimal版本版本
[[ $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

# 对于无桌面的镜像,选择Standard版本或者Minimal版本
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

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

# optimize build time with 100% CPU usage 定系统中的CPU核心数,并根据USEALLCORES的设置动态调整并行编译线程数
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 [[ ${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

        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
        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 ]] && 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

接下来我们针对该脚本内容从上往下依次分析。

4.1 确定目标路径

确定编译输出目标路径,设置为<SDK>/output

# destination 确定目标路径
if [ -d "$CONFIG_PATH/output" ]; then
        DEST="${CONFIG_PATH}"/output
else
        DEST="${SRC}"/output  # 走这里
fi

4.2 加载若干脚本函数

接着是使用source命令执行若干*.sh脚本,脚本均位于<SDK>/scripts目录下;

# 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

这些脚本都是定义了若干个函数,这些脚本中定义的函数将会被加载到当前shell中。

4.3 设置日志路径

接着设置日志输出路径:

# 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

日志输出路径被设置为debug,位于<SDK>/output目录下;

root@ubuntu:/work/sambashare/rk3566/orangepi-build$ ll output/debug/
-rw-rw-r-- 1 root sudo  6100  7月 10 15:24 logs-10_07_2024-14_20_17.tgz
-rw-rw-r-- 1 root sudo   246  7月 10 15:26 logs-10_07_2024-15_24_55.tgz
-rw-rw-r-- 1 root sudo   254  7月 10 15:30 logs-10_07_2024-15_26_21.tgz
-rw-rw-r-- 1 root sudo  2253  7月 10 15:42 logs-10_07_2024-15_30_06.tgz
-rw-rw-r-- 1 root sudo  6296  7月 10 16:53 logs-10_07_2024-15_42_43.tgz
-rw-rw-r-- 1 root sudo   246  7月 10 16:55 logs-10_07_2024-16_53_05.tgz
-rw-rw-r-- 1 root sudo  4630  7月 10 17:40 logs-10_07_2024-16_55_36.tgz
-rw-rw-r-- 1 root sudo  3659  7月 10 17:45 logs-10_07_2024-17_40_27.tgz
-rw-rw-r-- 1 root sudo  3714  7月 10 17:57 logs-10_07_2024-17_45_03.tgz
-rw-rw-r-- 1 root sudo 30427  7月 10 20:20 logs-10_07_2024-17_57_14.tgz
-rw-rw-r-- 1 root root    45  7月 10 14:20 logs-.tgz
-rw-rw-r-- 1 root sudo   198  7月 10 20:20 output.log
-rw-rw-r-- 1 root root    20  7月 10 20:20 timestamp

在该路径下存放在一周内的编译日志。

4.4 设置缓存路径

这段脚本片段的作用是根据条件设置ccache的相关环境变量和路径:

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

由于未设置USE_CCACHE,因此CCACHE=""

4.5 选择编译选项

接着创建了一个用户界面,用户可以从菜单中选择构建选项(u-bootkernelrootfsimage);

# 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

假如我们选择了Full OS image for flashing,则会设置BUILD_OPT=image

img

4.6 选择内核配置

假如上一步我们选择了Linux镜像,接下来会让我们选择内核配置;

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

如果不需要修改内核配置,则选择第一个即可,如果需要修改内核配置,则选择第二个;

img

假如我们选择了第一个,那么KERNEL_CONFIGURE=no

4.7 选择开发板型号

接着是选择开发板的型号;

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+=("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

假如我们选择了orangepi3b,那么将会设置BOARD=orangepi3b

4.8 加载板载配置

假如我们选择的开发板型号为orangepi3b,那么将会加载板载配置文件external/config/boards/orangepi3b.conf

BOARD_TYPE="conf"
# shellcheck source=/dev/null
source "${EXTER}/config/boards/${BOARD}.${BOARD_TYPE}"

# 设置为rockchip-rk356x
LINUXFAMILY="${BOARDFAMILY}"

# 不会进入
[[ -z $KERNEL_TARGET ]] && exit_with_error "Board configuration does not define valid kernel config"

orangepi3b.conf内容如下:

# Rockchip RK3566 hexa core 4GB RAM SoC GBE eMMC USB3 USB-C WiFi/BT
BOARD_NAME="OPI 3B"
BOARDFAMILY="rockchip-rk356x"
BOOTCONFIG="orangepi-3b-rk3566_defconfig"
KERNEL_TARGET="legacy,current"
BOOT_LOGO="desktop"
BOOT_SUPPORT_SPI="yes"
DISTRIB_TYPE_LEGACY="focal jammy bullseye bookworm raspi"
BOOTFS_TYPE="fat"
IMAGE_PARTITION_TABLE="gpt"
REVISION="1.0.6"

4.9 选择内核版本

接着是选择内核版本;

# 进入,选择源码分支
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

由于KERNEL_TARGET="legacy,current",因此支持的选项如下;

img

假如我们选择了current,那么BRANCH=current

4.10 选择Linux发行版的类型

4.10.1 Linux发行版

首先是选择Linux发行版的类型;

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

distros_options定义在general.sh中,用于获取Linux发行版的类型;

img

假如我们选择了bullseye Debian 11 Bullseye,那么RELEASE=bullseye

4.10.2 镜像类型

接着是选择镜像的类型;

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

Image with console interface (server)表示服务器版的镜像,体积比较小;

Image with desktop environmen表示带桌面的镜像,体积比较大。

如果我们选择Image with console interface (server)BUILD_DESKTOP=no

img
4.10.3 Standard/Minimal

如果是编译服务器版的镜像,还可以选择编译Standard版本或者Minimal版本,Minimal版本预装的软件会比Standard版本少很多(没特殊需求请不要选择Minimal版本,因为很多东西默认没有预装,部分功能可能用不了);

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

如果我们选择了Standard image with console interfaceBUILD_MINIMAL=no

img

4.11 加载configuration.sh

接着是使用source命令执行configuration.sh脚本,脚本位于<SDK>/scripts目录下,该脚本内容也比较多,后面我们单独介绍。

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

4.12 变量定义

接着是一些变量定义:

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

# <SDK>/u-boot/v2017.09-rk3588
BOOTSOURCEDIR="${BOOTDIR}/$(branch2dir "${BOOTBRANCH}")"
# <SDK>/u-boot/orange-pi-6.6-rk35xx
LINUXSOURCEDIR="${KERNELDIR}/$(branch2dir "${KERNELBRANCH}")"
[[ -n $ATFSOURCE ]] && ATFSOURCEDIR="${ATFDIR}/$(branch2dir "${ATFBRANCH}")"

# orangepi-bsp-cli-orangepi3b
BSP_CLI_PACKAGE_NAME="orangepi-bsp-cli-${BOARD}"
# orangepi-bsp-cli-orangepi3b_1.0.6_arm64
BSP_CLI_PACKAGE_FULLNAME="${BSP_CLI_PACKAGE_NAME}_${REVISION}_${ARCH}"
# orangepi-bsp-desktop--orangepi3b
BSP_DESKTOP_PACKAGE_NAME="orangepi-bsp-desktop-${BOARD}"
# orangepi-bsp-desktop--orangepi3b_1.0.6_arm64
BSP_DESKTOP_PACKAGE_FULLNAME="${BSP_DESKTOP_PACKAGE_NAME}_${REVISION}_${ARCH}"

# linux-u-boot-current-orangepi3b
CHOSEN_UBOOT=linux-u-boot-${BRANCH}-${BOARD}
# linux-image-current-rockchip-rk356x
CHOSEN_KERNEL=linux-image-${BRANCH}-${LINUXFAMILY}
# orangepi-bsp-cli-orangepi3b
CHOSEN_ROOTFS=${BSP_CLI_PACKAGE_NAME}

CHOSEN_DESKTOP=orangepi-${RELEASE}-desktop-${DESKTOP_ENVIRONMENT}
# linux-source-current-rockchip-rk356x
CHOSEN_KSRC=linux-source-${BRANCH}-${LINUXFAMILY}

4.13 do_default

文件最后调用了do_default函数。

4.13.1 源码下载

首先是源码下载:

# 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 [[ ${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

        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
fi

如果没有设置IGNORE_UPDATES="yes",将会通过调用fetch_from_repo 依次下载:

  • u-bootu-boot源码;
  • kernel;内核源码;
  • rootfs:从https://github.com/orangepi-xunlong/rk-rootfs-build.git下载根文件系统;
4.13.2 编译u-boot
# 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
4.13.3 编译kernel
# 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
4.13.4 编译rootfs
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
        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 ]] && 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
4.13.5 其它
# 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"

4.15 变量值

按照上面的流程执行下来,其中一些变量的值如下;

DEST=<SDK>/output
CCACHE=""
BUILD_OPT="image"
KERNEL_CONFIGURE="no"
BOARD="orangepi3b"
RELEASE="bullseye"
BUILD_DESKTOP="no"
BUILD_MINIMAL="no"

五、configuration.sh分析

posted @ 2024-07-10 21:34  大奥特曼打小怪兽  阅读(50)  评论(2编辑  收藏  举报
如果有任何技术小问题,欢迎大家交流沟通,共同进步