458 lines
14 KiB
Bash
458 lines
14 KiB
Bash
#!/usr/bin/env bash
|
|
#
|
|
# SPDX-License-Identifier: GPL-2.0
|
|
#
|
|
# Copyright (c) 2026 AMLOGIC
|
|
#
|
|
# Common utility functions for AMLbian
|
|
|
|
|
|
function print_all_info_for_debug() {
|
|
# Only print debug info if DEBUG=yes
|
|
if [[ "${DEBUG:-no}" != "yes" ]]; then
|
|
return 0
|
|
fi
|
|
|
|
# close it in dev env
|
|
# return 0
|
|
|
|
# Use display_alert if available, otherwise use echo
|
|
local debug_output="echo"
|
|
if command -v display_alert >/dev/null 2>&1; then
|
|
debug_output="display_alert"
|
|
fi
|
|
|
|
$debug_output "DEBUG INFO" "========== START DEBUG VARIABLE DUMP ==========" "info"
|
|
|
|
# Get and print all variables
|
|
compgen -v | while read var_name; do
|
|
# Skip special variables that might contain sensitive data
|
|
[[ "$var_name" =~ ^(_|BASH_|FUNCNAME|LINENO|PIPESTATUS|RANDOM|SECONDS|UID|EUID|PPID|SHELLOPTS|SHLVL|TERM|PATH|HOME|USER|LOGNAME|HOSTNAME|HOSTTYPE|MACHTYPE|OSTYPE|PWD|OLDPWD|TMPDIR|TEMP|TMP|LANG|LC_|LANGUAGE|TZ|DISPLAY|XAUTHORITY|SSH_|GPG_|LESS_|LS_COLORS|EDITOR|VISUAL|PAGER|MAIL|COLOR|LS_|PROMPT|PS[0-9]|COMP_|FIGNORE|GLOBIGNORE|IGNOREEOF|INPUTRC|TIMEFORMAT|TMOUT|auto_resume|histchars|CDPATH|CHILD_MAX|FCEDIT|histverify|HOSTFILE|IFS|MAIL_WARNING|nocaseglob|nullglob|REPLY|SHELL|BASH) ]] && continue
|
|
|
|
# Get variable value
|
|
local var_value="${!var_name}"
|
|
|
|
# Skip empty values
|
|
[[ -z "$var_value" ]] && continue
|
|
|
|
# Truncate very long values for readability
|
|
if [[ ${#var_value} -gt 200 ]]; then
|
|
var_value="${var_value:0:200}... [truncated, length=${#var_value}]"
|
|
fi
|
|
|
|
$debug_output "DEBUG VAR" "$var_name=$var_value" "info"
|
|
done
|
|
|
|
$debug_output "DEBUG INFO" "========== END DEBUG VARIABLE DUMP ==========" "info"
|
|
|
|
return 0
|
|
}
|
|
|
|
function safe_install() {
|
|
# 最后一个参数是目标目录
|
|
local dest="${@: -1}"
|
|
|
|
# 前面是 install 参数 + 源
|
|
local args=()
|
|
local sources=()
|
|
|
|
# 拆分参数(简单规则:以 - 开头的是参数)
|
|
for arg in "${@:1:$#-1}"; do
|
|
if [[ "$arg" == -* ]]; then
|
|
args+=("$arg")
|
|
else
|
|
sources+=("$arg")
|
|
fi
|
|
done
|
|
|
|
# 启用 nullglob:无匹配时返回空,而不是原字符串
|
|
local old_nullglob
|
|
shopt -q nullglob && old_nullglob=1 || old_nullglob=0
|
|
shopt -s nullglob
|
|
|
|
local expanded=()
|
|
|
|
for src in "${sources[@]}"; do
|
|
# 这里让 shell 做 glob 展开
|
|
local matches=( $src )
|
|
|
|
if [ ${#matches[@]} -eq 0 ]; then
|
|
echo "WARNING: safe_install: no match for: $src" >&2
|
|
continue
|
|
fi
|
|
|
|
expanded+=("${matches[@]}")
|
|
done
|
|
|
|
# 恢复 nullglob
|
|
[ "$old_nullglob" -eq 0 ] && shopt -u nullglob
|
|
|
|
# 如果一个文件都没有,直接返回
|
|
if [ ${#expanded[@]} -eq 0 ]; then
|
|
echo "WARNING: safe_install: nothing to install -> $dest" >&2
|
|
return 0
|
|
fi
|
|
|
|
# 调用原始 install
|
|
command install "${args[@]}" "${expanded[@]}" "$dest"
|
|
}
|
|
|
|
# check_files_exist <pattern> [verbose]
|
|
# 返回值:
|
|
# 0 -> 存在
|
|
# 1 -> 不存在
|
|
# 参数:
|
|
# pattern : 文件通配符(必须加引号)
|
|
# verbose : 可选,1=打印详情
|
|
check_files_exist() {
|
|
local pattern="$1"
|
|
local verbose="${2:-no}"
|
|
|
|
shopt -s nullglob
|
|
local files=($pattern)
|
|
shopt -u nullglob
|
|
|
|
if [ ${#files[@]} -gt 0 ]; then
|
|
if [ "$verbose" = "yes" ]; then
|
|
echo "Found files:"
|
|
for f in "${files[@]}"; do
|
|
echo " $f"
|
|
done
|
|
fi
|
|
return 0
|
|
else
|
|
if [ "$verbose" = "yes" ]; then
|
|
echo "WARNING: No files match pattern: $pattern" >&2
|
|
fi
|
|
display_alert "AMLOGIC" "NO $pattern deb!!!" "err"
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
is_unit_enabled() {
|
|
local unit="$1"
|
|
|
|
for u in "${BUILD_UNITS[@]}"; do
|
|
if [ "$u" = "$unit" ]; then
|
|
return 0 # 在白名单中
|
|
fi
|
|
done
|
|
|
|
return 1 # 不在白名单
|
|
}
|
|
|
|
setup_git_safe_dir() {
|
|
if [[ "${ARMBIAN_RUNNING_IN_CONTAINER}" == "yes" ]]; then
|
|
local dir="$1"
|
|
|
|
# 基本校验
|
|
[ -d "$dir" ] || {
|
|
echo "[ERROR] safe.directory path not exist: $dir" >&2
|
|
return 1
|
|
}
|
|
|
|
# 避免重复添加
|
|
if git config --global --get-all safe.directory | grep -Fxq "$dir"; then
|
|
echo "[INFO] safe.directory already set: $dir"
|
|
return 0
|
|
fi
|
|
echo "[INFO] add safe.directory: $dir"
|
|
export GIT_AUTHOR_NAME="amlbian"
|
|
export GIT_AUTHOR_EMAIL="amlbian@amlogic.com"
|
|
export GIT_COMMITTER_NAME="$GIT_AUTHOR_NAME"
|
|
export GIT_COMMITTER_EMAIL="$GIT_AUTHOR_EMAIL"
|
|
|
|
git config --global --add safe.directory "$dir" || {
|
|
echo "[ERROR] failed to set safe.directory" >&2
|
|
return 1
|
|
}
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
# ==============================================================================
|
|
# Packaging Utilities
|
|
# ==============================================================================
|
|
|
|
# Create package manifest
|
|
function create_package_manifest() {
|
|
local output_dir="${1}"
|
|
local deb_file="${2}"
|
|
local package_type="${3}"
|
|
local manifest_file="${output_dir}/manifest-${package_type}.txt"
|
|
|
|
display_alert "PACKAGE-MANIFEST" "Creating package manifest: ${manifest_file}" "info"
|
|
|
|
cat >> "${manifest_file}" << EOF
|
|
# Amlbian ${package_type} Package Manifest
|
|
# Generated: $(date)
|
|
|
|
Package: ${deb_file}
|
|
Creation Time: $(date -r "${output_dir}/${deb_file}" 2>/dev/null || echo "unknown")
|
|
Size: $(du -h "${output_dir}/${deb_file}" | cut -f1)
|
|
|
|
## Package Info:
|
|
$(dpkg-deb -I "${output_dir}/${deb_file}" 2>/dev/null | sed 's/^/ /')
|
|
|
|
## Package Contents (first 10 files):
|
|
$(dpkg-deb -c "${output_dir}/${deb_file}" 2>/dev/null | head -10 | sed 's/^/ /')
|
|
|
|
---
|
|
EOF
|
|
|
|
display_alert "PACKAGE-MANIFEST" "Package manifest updated: ${manifest_file} success" "info"
|
|
}
|
|
|
|
|
|
|
|
# ==============================================================================
|
|
# Section 1: Display and Logging Functions
|
|
# ==============================================================================
|
|
|
|
# Display timestamp for logging
|
|
function amlbian_get_timestamp() {
|
|
date "+%Y-%m-%d %H:%M:%S"
|
|
}
|
|
|
|
# Display configuration summary
|
|
function amlbian_display_config() {
|
|
display_alert "AMLIbian Configuration Summary" "======================" "info"
|
|
display_alert "Board" "${BOARD:-not set}" "info"
|
|
display_alert "Board Family" "${BOARDFAMILY:-not set}" "info"
|
|
display_alert "Kernel Version" "${KERNEL_VERSION_FULL:-not set}" "info"
|
|
display_alert "U-Boot Version" "${UBOOT_VERSION:-not set}" "info"
|
|
display_alert "Release" "${RELEASE:-not set}" "info"
|
|
display_alert "Use Local Sources" "${USE_LOCAL_SOURCES:-not set}" "info"
|
|
display_alert "Local U-Boot Path" "${LOCAL_UBOOT_PATH:-not set}" "info"
|
|
display_alert "Local Kernel Path" "${LOCAL_KERNEL_PATH:-not set}" "info"
|
|
}
|
|
|
|
# ==============================================================================
|
|
# Section 2: Path Utility Functions
|
|
# ==============================================================================
|
|
|
|
# Get the absolute path of AMLbian directory
|
|
function amlbian_get_dir() {
|
|
local script_dir
|
|
script_dir="$(dirname "$(realpath "${BASH_SOURCE[0]}")")"
|
|
echo "$(dirname "${script_dir}")"
|
|
}
|
|
|
|
# Resolve path with multiple fallback locations
|
|
function amlbian_resolve_path() {
|
|
local filename="$1"
|
|
shift
|
|
local -a search_paths=("$@")
|
|
|
|
for path in "${search_paths[@]}"; do
|
|
if [[ -f "${path}" ]]; then
|
|
echo "${path}"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
display_alert "AMLOGIC TODO: Could not find" "${filename}" "err"
|
|
return 1
|
|
}
|
|
|
|
# ==============================================================================
|
|
# Section 3: Git Utility Functions
|
|
# ==============================================================================
|
|
|
|
# Get git commit hash
|
|
function amlbian_git_get_commit() {
|
|
local repo_dir="$1"
|
|
if [[ -d "${repo_dir}/.git" ]]; then
|
|
cd "${repo_dir}" && git rev-parse HEAD 2>/dev/null | cut -c1-12
|
|
else
|
|
echo "unknown"
|
|
fi
|
|
}
|
|
|
|
# Get git branch name
|
|
function amlbian_git_get_branch() {
|
|
local repo_dir="$1"
|
|
if [[ -d "${repo_dir}/.git" ]]; then
|
|
cd "${repo_dir}" && git rev-parse --abbrev-ref HEAD 2>/dev/null
|
|
else
|
|
echo "unknown"
|
|
fi
|
|
}
|
|
|
|
# Check if git repository is valid
|
|
function amlbian_git_check_repo() {
|
|
local repo_dir="$1"
|
|
if [[ ! -d "${repo_dir}" ]]; then
|
|
display_alert "AMLOGIC TODO: Repository directory not found" "${repo_dir}" "err"
|
|
return 1
|
|
fi
|
|
|
|
if [[ ! -d "${repo_dir}/.git" ]]; then
|
|
display_alert "AMLOGIC TODO: Not a git repository" "${repo_dir}" "warn"
|
|
return 0 # Allow non-git directories
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# ==============================================================================
|
|
# Section 4: File Utility Functions
|
|
# ==============================================================================
|
|
|
|
# Safe copy directory with error handling
|
|
function amlbian_safe_copy() {
|
|
local src="$1"
|
|
local dst="$2"
|
|
local description="${3:-copy}"
|
|
|
|
if [[ ! -d "${src}" ]]; then
|
|
display_alert "AMLOGIC TODO: Source directory not found" "${src}" "err"
|
|
return 1
|
|
fi
|
|
|
|
# Create destination directory
|
|
mkdir -p "${dst}"
|
|
|
|
# Clean destination if exists
|
|
if [[ -d "${dst}" ]] && [[ "${dst}" != "/" ]]; then
|
|
display_alert "AMLOGIC TODO: Cleaning destination" "${dst}" "debug"
|
|
rm -rf "${dst:?}"/*
|
|
fi
|
|
|
|
# Copy with progress
|
|
display_alert "AMLOGIC TODO: ${description}" "${src} -> ${dst}" "info"
|
|
cp -r "${src}/." "${dst}/" || {
|
|
display_alert "AMLOGIC TODO: Copy failed" "${src} -> ${dst}" "err"
|
|
return 1
|
|
}
|
|
|
|
return 0
|
|
}
|
|
|
|
# Safe remove directory
|
|
function amlbian_safe_remove() {
|
|
local path="$1"
|
|
local description="${2:-remove}"
|
|
|
|
if [[ -z "${path}" ]] || [[ "${path}" == "/" ]]; then
|
|
display_alert "AMLOGIC TODO: Refusing to remove root or empty path" "${path}" "err"
|
|
return 1
|
|
fi
|
|
|
|
if [[ -d "${path}" ]]; then
|
|
display_alert "AMLOGIC TODO: ${description}" "Removing ${path}" "debug"
|
|
rm -rf "${path:?}" 2>/dev/null
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# ==============================================================================
|
|
# Section 5: Build Utility Functions
|
|
# ==============================================================================
|
|
|
|
# Check if build should continue
|
|
function amlbian_check_build_prereq() {
|
|
display_alert "AMLOGIC TODO: Checking build prerequisites" "${BOARD}" "info"
|
|
|
|
# Check local sources if enabled
|
|
if [[ "${USE_LOCAL_SOURCES}" == "yes" ]]; then
|
|
if [[ -n "${LOCAL_UBOOT_PATH}" ]] && [[ ! -d "${LOCAL_UBOOT_PATH}" ]]; then
|
|
display_alert "AMLOGIC TODO: Local U-Boot path not found" "${LOCAL_UBOOT_PATH}" "err"
|
|
return 1
|
|
fi
|
|
|
|
if [[ -n "${LOCAL_KERNEL_PATH}" ]] && [[ ! -d "${LOCAL_KERNEL_PATH}" ]]; then
|
|
display_alert "AMLOGIC TODO: Local Kernel path not found" "${LOCAL_KERNEL_PATH}" "err"
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# ==============================================================================
|
|
# Section 6: Docker Utility Functions
|
|
# ==============================================================================
|
|
|
|
# Get AML_COMP_DIR for Docker environment
|
|
function amlbian_get_aml_comp_dir() {
|
|
if [[ "${ARMBIAN_RUNNING_IN_CONTAINER}" == "yes" ]]; then
|
|
echo "/aml-comp"
|
|
else
|
|
# Host environment - use relative path from amlbian dir
|
|
local amlbian_dir
|
|
amlbian_dir="$(amlbian_get_dir)"
|
|
echo "${amlbian_dir}/../aml-comp"
|
|
fi
|
|
}
|
|
|
|
function amlbian_checkout_toolchain() {
|
|
display_alert "Ignore check toolchain after set_external_toolchain in common setting"
|
|
return 0
|
|
|
|
# # Check default gcc version before switching toolchain
|
|
# local need_new_toolchain=1
|
|
# local default_gcc_version=""
|
|
|
|
# # Try to get default gcc version
|
|
# if command -v gcc &> /dev/null; then
|
|
# default_gcc_version=$(aarch64-linux-gnu-gcc --version | head -n1 | grep -oP '\d+\.\d+\.\d+' | head -n1)
|
|
# display_alert "AMLOGIC Default gcc version: ${default_gcc_version}" "info"
|
|
|
|
# # Check if version is >= 5.1.0
|
|
# if [[ -n "${default_gcc_version}" ]]; then
|
|
# # Simple version comparison
|
|
# local major_version=$(echo "${default_gcc_version}" | cut -d. -f1)
|
|
# local minor_version=$(echo "${default_gcc_version}" | cut -d. -f2)
|
|
|
|
# if [[ ${major_version} -gt 5 ]] || ([[ ${major_version} -eq 5 ]] && [[ ${minor_version} -ge 1 ]]); then
|
|
# display_alert "AMLOGIC Default gcc version ${default_gcc_version} >= 5.1.0, no need for new toolchain" "info"
|
|
# need_new_toolchain=0
|
|
# else
|
|
# display_alert "AMLOGIC Default gcc version ${default_gcc_version} < 5.1.0, will try new toolchain" "info"
|
|
# fi
|
|
# fi
|
|
# else
|
|
# display_alert "AMLOGIC gcc not found in PATH" "warn"
|
|
# fi
|
|
|
|
# # Only switch to new toolchain if needed
|
|
# if [[ ${need_new_toolchain} -eq 1 ]]; then
|
|
# local new_toolchain_path="/opt/gcc-arm-8.3-2019.03-x86_64-aarch64-linux-gnu/bin"
|
|
# if [[ -d "${new_toolchain_path}" ]]; then
|
|
# display_alert "AMLOGIC Using new toolchain from: ${new_toolchain_path}" "info"
|
|
# export PATH="${new_toolchain_path}:${PATH}"
|
|
# # Check if gcc exists in the new toolchain
|
|
# if [[ -f "${new_toolchain_path}/aarch64-linux-gnu-gcc" ]]; then
|
|
# display_alert "AMLOGIC Found cross-compiler: ${new_toolchain_path}/aarch64-linux-gnu-gcc" "info"
|
|
# else
|
|
# display_alert "AMLOGIC Cross-compiler not found in new toolchain, using default" "warn"
|
|
# fi
|
|
# else
|
|
# display_alert "AMLOGIC New toolchain directory not found: ${new_toolchain_path}" "warn"
|
|
# fi
|
|
# fi
|
|
}
|
|
|
|
function is_feature_contains() {
|
|
local features="$1"
|
|
local target="$2"
|
|
|
|
local item
|
|
for item in $features; do
|
|
if [ "$item" = "$target" ]; then
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
return 1
|
|
}
|
|
|
|
export -f create_package_manifest
|
|
export -f amlbian_checkout_toolchain
|
|
export -f is_feature_contains
|
|
|
|
# ==============================================================================
|
|
# End of function-common.sh
|
|
# ============================================================================== |