512 lines
11 KiB
Bash
Executable File
512 lines
11 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
if [ -z "$BASH_SOURCE" ]; then
|
|
echo "Not in bash, switching to it..."
|
|
case "${@:-shell}" in
|
|
shell) ./build.sh shell ;;
|
|
*)
|
|
./build.sh $@
|
|
bash
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
usage()
|
|
{
|
|
echo "Usage: $(basename $BASH_SOURCE) [OPTIONS]"
|
|
echo "Available options:"
|
|
|
|
run_build_hooks usage
|
|
|
|
# Global options
|
|
echo -e "cleanall \tcleanup"
|
|
echo -e "post-rootfs <rootfs dir> \ttrigger post-rootfs hook scripts"
|
|
echo -e "shell \tsetup a shell for developing"
|
|
echo -e "help \tusage"
|
|
echo ""
|
|
echo "Default option is 'allsave'."
|
|
|
|
rm -f "$INITIAL_ENV"
|
|
exit 0
|
|
}
|
|
|
|
err_handler()
|
|
{
|
|
ret=${1:-$?}
|
|
[ "$ret" -eq 0 ] && return
|
|
|
|
echo "ERROR: Running $BASH_SOURCE - ${2:-${FUNCNAME[1]}} failed!"
|
|
echo "ERROR: exit code $ret from line ${BASH_LINENO[0]}:"
|
|
echo " ${3:-$BASH_COMMAND}"
|
|
echo "ERROR: call stack:"
|
|
for i in $(seq 1 $((${#FUNCNAME[@]} - 1))); do
|
|
SOURCE="${BASH_SOURCE[$i]}"
|
|
LINE=${BASH_LINENO[$(( $i - 1 ))]}
|
|
echo " $(basename "$SOURCE"): ${FUNCNAME[$i]}($LINE)"
|
|
done
|
|
exit $ret
|
|
}
|
|
|
|
# Export global functions
|
|
set -a
|
|
|
|
finish_build()
|
|
{
|
|
echo -e "\e[35mRunning $(basename "${BASH_SOURCE[1]}") - ${@:-${FUNCNAME[1]}} succeeded.\e[0m"
|
|
cd "$SDK_DIR"
|
|
}
|
|
|
|
load_config()
|
|
{
|
|
[ -r "$RK_CONFIG" ] || return 0
|
|
|
|
for var in $@; do
|
|
export $(grep "^$var=" "$RK_CONFIG" | \
|
|
tr -d '"' || true) &>/dev/null
|
|
done
|
|
}
|
|
|
|
check_config()
|
|
{
|
|
unset missing
|
|
for var in $@; do
|
|
eval [ \$$var ] && continue
|
|
|
|
missing="$missing $var"
|
|
done
|
|
|
|
[ -z "$missing" ] && return 0
|
|
|
|
echo "Skipping $(basename "${BASH_SOURCE[1]}") - ${FUNCNAME[1]} for missing configs: $missing."
|
|
return 1
|
|
}
|
|
|
|
kernel_version_real()
|
|
{
|
|
[ -d kernel ] || return 0
|
|
|
|
VERSION_KEYS="VERSION PATCHLEVEL"
|
|
VERSION=""
|
|
|
|
for k in $VERSION_KEYS; do
|
|
v=$(grep "^$k = " kernel/Makefile | cut -d' ' -f3)
|
|
VERSION=${VERSION:+${VERSION}.}$v
|
|
done
|
|
echo $VERSION
|
|
}
|
|
|
|
kernel_version()
|
|
{
|
|
[ -d kernel ] || return 0
|
|
|
|
KERNEL_DIR="$(basename "$(realpath kernel)")"
|
|
case "$KERNEL_DIR" in
|
|
kernel-*)
|
|
echo ${KERNEL_DIR#kernel-}
|
|
return 0
|
|
;;
|
|
esac
|
|
|
|
kernel_version_real
|
|
}
|
|
|
|
start_log()
|
|
{
|
|
LOG_FILE="$RK_LOG_DIR/${2:-$1_$(date +%F_%H-%M-%S)}.log"
|
|
ln -rsf "$LOG_FILE" "$RK_LOG_DIR/$1.log"
|
|
echo "# $(date +"%F %T")" >> "$LOG_FILE"
|
|
echo "$LOG_FILE"
|
|
}
|
|
|
|
get_toolchain()
|
|
{
|
|
TOOLCHAIN_ARCH="${1/arm64/aarch64}"
|
|
|
|
MACHINE=$(uname -m)
|
|
if [ "$MACHINE" = x86_64 ]; then
|
|
TOOLCHAIN_VENDOR="${2:-none}"
|
|
TOOLCHAIN_OS="${3:-linux}"
|
|
|
|
# RV1126 uses custom toolchain
|
|
if [ "$RK_CHIP_FAMILY" = "rv1126_rv1109" ]; then
|
|
TOOLCHAIN_VENDOR=rockchip
|
|
fi
|
|
|
|
TOOLCHAIN_DIR="$(realpath prebuilts/gcc/*/$TOOLCHAIN_ARCH)"
|
|
GCC="$(find "$TOOLCHAIN_DIR" \
|
|
-name "*$TOOLCHAIN_VENDOR-$TOOLCHAIN_OS-*-gcc" | \
|
|
head -n 1)"
|
|
if [ ! -x "$GCC" ]; then
|
|
echo "No prebuilt GCC toolchain!"
|
|
exit 1
|
|
fi
|
|
elif [ "$TOLLCHAIN_ARCH" = aarch64 -a "$MACHINE" != aarch64 ]; then
|
|
GCC=aarch64-linux-gnu-gcc
|
|
elif [ "$TOLLCHAIN_ARCH" = arm -a "$MACHINE" != armv7l ]; then
|
|
GCC=arm-linux-gnueabihf-gcc
|
|
else
|
|
GCC=gcc
|
|
fi
|
|
|
|
echo "${GCC%gcc}"
|
|
}
|
|
|
|
# For developing shell only
|
|
|
|
rroot()
|
|
{
|
|
cd "$SDK_DIR"
|
|
}
|
|
|
|
rout()
|
|
{
|
|
cd "$RK_OUTDIR"
|
|
}
|
|
|
|
rcommon()
|
|
{
|
|
cd "$COMMON_DIR"
|
|
}
|
|
|
|
rscript()
|
|
{
|
|
cd "$SCRIPTS_DIR"
|
|
}
|
|
|
|
rchip()
|
|
{
|
|
cd "$(realpath "$CHIP_DIR")"
|
|
}
|
|
|
|
set +a
|
|
# End of global functions
|
|
|
|
run_hooks()
|
|
{
|
|
DIR="$1"
|
|
shift
|
|
|
|
for dir in "$CHIP_DIR/$(basename "$DIR")/" "$DIR"; do
|
|
[ -d "$dir" ] || continue
|
|
|
|
for hook in $(find "$dir" -maxdepth 1 -name "*.sh" | sort); do
|
|
"$hook" $@ && continue
|
|
HOOK_RET=$?
|
|
err_handler $HOOK_RET "${FUNCNAME[0]} $*" "$hook $*"
|
|
exit $HOOK_RET
|
|
done
|
|
done
|
|
}
|
|
|
|
run_build_hooks()
|
|
{
|
|
# Don't log these hooks
|
|
case "$1" in
|
|
init | pre-build | make-* | usage | support-cmds)
|
|
run_hooks "$RK_BUILD_HOOK_DIR" $@ || true
|
|
return 0
|
|
;;
|
|
esac
|
|
|
|
LOG_FILE="$(start_log "$1")"
|
|
|
|
echo -e "# run hook: $@\n" >> "$LOG_FILE"
|
|
run_hooks "$RK_BUILD_HOOK_DIR" $@ 2>&1 | tee -a "$LOG_FILE"
|
|
HOOK_RET=${PIPESTATUS[0]}
|
|
if [ $HOOK_RET -ne 0 ]; then
|
|
err_handler $HOOK_RET "${FUNCNAME[0]} $*" "$@"
|
|
exit $HOOK_RET
|
|
fi
|
|
}
|
|
|
|
run_post_hooks()
|
|
{
|
|
LOG_FILE="$(start_log post-rootfs)"
|
|
|
|
echo -e "# run hook: $@\n" >> "$LOG_FILE"
|
|
run_hooks "$RK_POST_HOOK_DIR" $@ 2>&1 | tee -a "$LOG_FILE"
|
|
HOOK_RET=${PIPESTATUS[0]}
|
|
if [ $HOOK_RET -ne 0 ]; then
|
|
err_handler $HOOK_RET "${FUNCNAME[0]} $*" "$@"
|
|
exit $HOOK_RET
|
|
fi
|
|
}
|
|
|
|
option_check()
|
|
{
|
|
CMDS="$1"
|
|
shift
|
|
|
|
for opt in $@; do
|
|
for cmd in $CMDS; do
|
|
# NOTE: There might be patterns in commands
|
|
echo "${opt%%:*}" | grep -q "^$cmd$" || continue
|
|
return 0
|
|
done
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
main()
|
|
{
|
|
[ -z "$DEBUG" ] || set -x
|
|
|
|
trap 'err_handler' ERR
|
|
set -eE
|
|
|
|
# Save intial envionments
|
|
unset INITIAL_SESSION
|
|
INITIAL_ENV=$(mktemp -u)
|
|
if [ -z "$RK_SESSION" ]; then
|
|
INITIAL_SESSION=1
|
|
env > "$INITIAL_ENV"
|
|
fi
|
|
|
|
export LC_ALL=C
|
|
|
|
export SCRIPTS_DIR="$(dirname "$(realpath "$BASH_SOURCE")")"
|
|
export COMMON_DIR="$(realpath "$SCRIPTS_DIR/..")"
|
|
export SDK_DIR="$(realpath "$COMMON_DIR/../../..")"
|
|
export DEVICE_DIR="$SDK_DIR/device/rockchip"
|
|
export CHIPS_DIR="$DEVICE_DIR/.chips"
|
|
export CHIP_DIR="$DEVICE_DIR/.chip"
|
|
|
|
export RK_DATA_DIR="$COMMON_DIR/data"
|
|
export RK_TOOL_DIR="$COMMON_DIR/tools"
|
|
export RK_IMAGE_DIR="$COMMON_DIR/images"
|
|
export RK_KBUILD_DIR="$COMMON_DIR/linux-kbuild"
|
|
export RK_CONFIG_IN="$COMMON_DIR/configs/Config.in"
|
|
|
|
export RK_BUILD_HOOK_DIR="$COMMON_DIR/build-hooks"
|
|
export BUILD_HELPER="$RK_BUILD_HOOK_DIR/build-helper"
|
|
export RK_POST_HOOK_DIR="$COMMON_DIR/post-hooks"
|
|
export POST_HELPER="$RK_POST_HOOK_DIR/post-helper"
|
|
|
|
export PARTITION_HELPER="$SCRIPTS_DIR/partition-helper"
|
|
|
|
export RK_SESSION="${RK_SESSION:-$(date +%F_%H-%M-%S)}"
|
|
|
|
export RK_OUTDIR="$SDK_DIR/output"
|
|
export RK_SESSION_DIR="$RK_OUTDIR/sessions"
|
|
export RK_LOG_BASE_DIR="$RK_OUTDIR/log"
|
|
export RK_LOG_DIR="$RK_SESSION_DIR/$RK_SESSION"
|
|
export RK_INITIAL_ENV="$RK_LOG_DIR/initial.env"
|
|
export RK_CUSTOM_ENV="$RK_LOG_DIR/custom.env"
|
|
export RK_FINAL_ENV="$RK_LOG_DIR/final.env"
|
|
export RK_ROCKDEV_DIR="$SDK_DIR/rockdev"
|
|
export RK_FIRMWARE_DIR="$RK_OUTDIR/firmware"
|
|
export RK_SECURITY_FIRMWARE_DIR="$RK_OUTDIR/security-firmware"
|
|
export RK_CONFIG="$RK_OUTDIR/.config"
|
|
export RK_DEFCONFIG_LINK="$RK_OUTDIR/defconfig"
|
|
|
|
# For Makefile
|
|
case "$@" in
|
|
make-targets | make-usage)
|
|
run_build_hooks "$@"
|
|
rm -f "$INITIAL_ENV"
|
|
exit 0 ;;
|
|
esac
|
|
|
|
# Prepare firmware dirs
|
|
mkdir -p "$RK_FIRMWARE_DIR" "$RK_SECURITY_FIRMWARE_DIR"
|
|
|
|
cd "$SDK_DIR"
|
|
[ -f README.md ] || ln -rsf "$COMMON_DIR/README.md" .
|
|
|
|
# TODO: Remove it in the repo manifest.xml
|
|
rm -f envsetup.sh
|
|
|
|
OPTIONS="${@:-allsave}"
|
|
|
|
# Options checking
|
|
CMDS="$(run_build_hooks support-cmds all | xargs)"
|
|
for opt in $OPTIONS; do
|
|
case "$opt" in
|
|
help | h | -h | --help | usage | \?) usage ;;
|
|
shell | cleanall)
|
|
# Check single options
|
|
if [ "$opt" = "$OPTIONS" ]; then
|
|
break
|
|
fi
|
|
|
|
echo "ERROR: $opt cannot combine with other options!"
|
|
;;
|
|
post-rootfs)
|
|
if [ "$opt" = "$1" -a -d "$2" ]; then
|
|
# Hide other args from build stages
|
|
OPTIONS=$opt
|
|
break
|
|
fi
|
|
|
|
echo "ERROR: $opt should be the first option followed by rootfs dir!"
|
|
;;
|
|
*)
|
|
# Make sure that all options are handled
|
|
if option_check "$CMDS" $opt; then
|
|
continue
|
|
fi
|
|
|
|
echo "ERROR: Unhandled option: $opt"
|
|
;;
|
|
esac
|
|
|
|
usage
|
|
done
|
|
|
|
# Prepare log dirs
|
|
if [ ! -d "$RK_LOG_DIR" ]; then
|
|
rm -rf "$RK_LOG_BASE_DIR" "$RK_LOG_DIR" "$RK_SESSION_DIR/latest"
|
|
mkdir -p "$RK_LOG_DIR"
|
|
ln -rsf "$RK_SESSION_DIR" "$RK_LOG_BASE_DIR"
|
|
ln -rsf "$RK_LOG_DIR" "$RK_SESSION_DIR/latest"
|
|
echo -e "\e[33mLog saved at $RK_LOG_DIR\e[0m"
|
|
echo
|
|
fi
|
|
|
|
# Drop old logs
|
|
cd "$RK_LOG_BASE_DIR"
|
|
rm -rf $(ls -t | sed '1,10d')
|
|
cd "$SDK_DIR"
|
|
|
|
# Save initial envionments
|
|
if [ "$INITIAL_SESSION" ]; then
|
|
rm -f "$RK_INITIAL_ENV"
|
|
mv "$INITIAL_ENV" "$RK_INITIAL_ENV"
|
|
ln -rsf "$RK_INITIAL_ENV" "$RK_OUTDIR/"
|
|
fi
|
|
|
|
# Init stage (preparing SDK configs, etc.)
|
|
run_build_hooks init $OPTIONS
|
|
rm -f "$RK_OUTDIR/.tmpconfig*"
|
|
|
|
# No need to go further
|
|
CMDS="$(run_build_hooks support-cmds pre-build build \
|
|
post-build | xargs) shell cleanall post-rootfs"
|
|
option_check "$CMDS" $OPTIONS || return 0
|
|
|
|
# Force exporting config environments
|
|
set -a
|
|
|
|
# Load config environments
|
|
source "$RK_CONFIG"
|
|
cp "$RK_CONFIG" "$RK_LOG_DIR"
|
|
|
|
if [ -z "$INITIAL_SESSION" ]; then
|
|
# Inherit session environments
|
|
sed -n 's/^\(RK_.*=\)\(.*\)/\1"\2"/p' "$RK_FINAL_ENV" > \
|
|
"$INITIAL_ENV"
|
|
source "$INITIAL_ENV"
|
|
rm -f "$INITIAL_ENV"
|
|
else
|
|
# Detect and save custom environments
|
|
|
|
# Find custom environments
|
|
rm -f "$RK_CUSTOM_ENV"
|
|
for cfg in $(grep "^RK_" "$RK_INITIAL_ENV" || true); do
|
|
env | grep -q "^${cfg//\"/}$" || \
|
|
echo "$cfg" >> "$RK_CUSTOM_ENV"
|
|
done
|
|
|
|
# Allow custom environments overriding
|
|
if [ -e "$RK_CUSTOM_ENV" ]; then
|
|
ln -rsf "$RK_CUSTOM_ENV" "$RK_OUTDIR/"
|
|
|
|
echo -e "\e[31mWARN: Found custom environments: \e[0m"
|
|
cat "$RK_CUSTOM_ENV"
|
|
|
|
echo -e "\e[31mAssuming that is expected, please clear them if otherwise.\e[0m"
|
|
read -t 10 -p "Press enter to continue."
|
|
source "$RK_CUSTOM_ENV"
|
|
|
|
if grep -q "^RK_KERNEL_VERSION=" "$RK_CUSTOM_ENV"; then
|
|
echo -e "\e[31mCustom RK_KERNEL_VERSION ignored!\e[0m"
|
|
load_config RK_KERNEL_VERSION
|
|
fi
|
|
|
|
if grep -q "^RK_ROOTFS_SYSTEM=" "$RK_CUSTOM_ENV"; then
|
|
echo -e "\e[31mCustom RK_ROOTFS_SYSTEM ignored!\e[0m"
|
|
load_config RK_ROOTFS_SYSTEM
|
|
fi
|
|
fi
|
|
fi
|
|
|
|
source "$PARTITION_HELPER"
|
|
rk_partition_init
|
|
|
|
set +a
|
|
|
|
export PYTHON3=/usr/bin/python3
|
|
|
|
if [ "$RK_KERNEL_CFG" ]; then
|
|
export RK_KERNEL_TOOLCHAIN="$(get_toolchain "$RK_KERNEL_ARCH")"
|
|
|
|
CPUS=$(getconf _NPROCESSORS_ONLN 2>/dev/null || echo 1)
|
|
export KMAKE="make -C "$SDK_DIR/kernel/" -j$(( $CPUS + 1 )) \
|
|
CROSS_COMPILE=$RK_KERNEL_TOOLCHAIN ARCH=$RK_KERNEL_ARCH"
|
|
|
|
export RK_KERNEL_VERSION_REAL=$(kernel_version_real)
|
|
fi
|
|
|
|
# Handle special commands
|
|
case "$OPTIONS" in
|
|
shell)
|
|
echo -e "\e[35mDoing this is dangerous and for developing only.\e[0m"
|
|
# No error handling in develop shell.
|
|
set +e; trap ERR
|
|
/bin/bash
|
|
echo -e "\e[35mExit from $BASH_SOURCE shell.\e[0m"
|
|
exit 0 ;;
|
|
cleanall)
|
|
run_build_hooks clean
|
|
rm -rf "$RK_OUTDIR" "$SDK_DIR/rockdev"
|
|
finish_build cleanall
|
|
exit 0 ;;
|
|
post-rootfs)
|
|
shift
|
|
run_post_hooks $@
|
|
finish_build post-rootfs
|
|
exit 0 ;;
|
|
esac
|
|
|
|
# Save final environments
|
|
rm -f "$RK_FINAL_ENV"
|
|
env > "$RK_FINAL_ENV"
|
|
ln -rsf "$RK_FINAL_ENV" "$RK_OUTDIR/"
|
|
|
|
# Log configs
|
|
echo
|
|
echo "=========================================="
|
|
echo " Final configs"
|
|
echo "=========================================="
|
|
env | grep -E "^RK_.*=.+" | grep -vE "PARTITION_[0-9]" | \
|
|
grep -vE "=\"\"$|_DEFAULT=y" | \
|
|
grep -vE "^RK_CONFIG|_BASE_CFG=|_LINK=|DIR=|_ENV=|_NAME=" | sort
|
|
echo
|
|
|
|
# Pre-build stage (submodule configuring, etc.)
|
|
run_build_hooks pre-build $OPTIONS
|
|
|
|
# No need to go further
|
|
CMDS="$(run_build_hooks support-cmds build post-build | xargs)"
|
|
option_check "$CMDS" $OPTIONS || return 0
|
|
|
|
# Build stage (building, etc.)
|
|
run_build_hooks build $OPTIONS
|
|
|
|
# No need to go further
|
|
CMDS="$(run_build_hooks support-cmds post-build | xargs)"
|
|
option_check "$CMDS" $OPTIONS || return 0
|
|
|
|
# Post-build stage (firmware packing, etc.)
|
|
run_build_hooks post-build $OPTIONS
|
|
}
|
|
|
|
if [ "$0" != "$BASH_SOURCE" ]; then
|
|
# Sourced, executing it directly
|
|
"$BASH_SOURCE" ${@:-shell}
|
|
elif [ "$0" == "$BASH_SOURCE" ]; then
|
|
# Executed directly
|
|
main $@
|
|
fi
|