Files
BPI-CM9-Linux/amlbian/lib/function-common.sh
T
2026-08-24 10:03:24 +08:00

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="[email protected]"
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
# ==============================================================================