#!/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 [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 # ==============================================================================