338 lines
12 KiB
Bash
338 lines
12 KiB
Bash
|
|
#!/bin/bash
|
|||
|
|
|
|||
|
|
# 项目注册基础设施
|
|||
|
|
# 所有函数定义。项目配置数据在 project_registry.sh 中。
|
|||
|
|
|
|||
|
|
ALL_PROJECTS=()
|
|||
|
|
|
|||
|
|
declare -A PROJECT_META=()
|
|||
|
|
declare -A PROJECT_COPY_SPECS=()
|
|||
|
|
declare -A PROJECT_OPTIONAL_COPY_SPECS=()
|
|||
|
|
|
|||
|
|
DEFAULT_VERSION_STRING="1.0.0"
|
|||
|
|
DEFAULT_BUILD_NUMBER="1"
|
|||
|
|
|
|||
|
|
# ===== 基础工具 =====
|
|||
|
|
|
|||
|
|
_list_items() { printf '%s\n' "$@"; }
|
|||
|
|
|
|||
|
|
_array_contains() {
|
|||
|
|
local expected=$1; shift
|
|||
|
|
local item
|
|||
|
|
for item in "$@"; do
|
|||
|
|
[ "$item" = "$expected" ] && return 0
|
|||
|
|
done
|
|||
|
|
return 1
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_trim_leading_spaces() { printf '%s' "${1#"${1%%[![:space:]]*}"}"; }
|
|||
|
|
|
|||
|
|
set_project_meta() { PROJECT_META["$1:$2"]=${3-}; }
|
|||
|
|
get_project_meta() { printf '%s' "${PROJECT_META["$1:$2"]:-}"; }
|
|||
|
|
|
|||
|
|
# ===== 项目查询 =====
|
|||
|
|
|
|||
|
|
list_projects() { _list_items "${ALL_PROJECTS[@]}"; }
|
|||
|
|
is_project() { _array_contains "$1" "${ALL_PROJECTS[@]}"; }
|
|||
|
|
|
|||
|
|
list_projects_by_kind() {
|
|||
|
|
local kind=$1 project
|
|||
|
|
for project in "${ALL_PROJECTS[@]}"; do
|
|||
|
|
[ "$(get_project_meta "$project" package_kind)" = "$kind" ] && printf '%s\n' "$project"
|
|||
|
|
done
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# ===== 元数据加载 =====
|
|||
|
|
|
|||
|
|
load_version_project_meta() {
|
|||
|
|
local project=$1
|
|||
|
|
is_project "$project" || return 1
|
|||
|
|
VERSION_PROJECT="$project"
|
|||
|
|
VERSION_FILE_REL="$(get_project_meta "$project" version_file_rel)"
|
|||
|
|
VERSION_MACRO="$(get_project_meta "$project" version_macro)"
|
|||
|
|
PUBLISH_NAME="$(get_project_meta "$project" publish_name)"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
load_package_project_meta() {
|
|||
|
|
local project=$1
|
|||
|
|
is_project "$project" || return 1
|
|||
|
|
PACKAGE_PROJECT="$project"
|
|||
|
|
PACKAGE_NAME="$(get_project_meta "$project" package_name)"
|
|||
|
|
PACKAGE_KIND="$(get_project_meta "$project" package_kind)"
|
|||
|
|
PACKAGE_DESCRIPTION="$(get_project_meta "$project" package_description)"
|
|||
|
|
PACKAGE_COMMENT="$(get_project_meta "$project" package_comment)"
|
|||
|
|
PACKAGE_VERSION_FILE_REL="$(get_project_meta "$project" version_file_rel)"
|
|||
|
|
PACKAGE_VERSION_MACRO="$(get_project_meta "$project" version_macro)"
|
|||
|
|
PACKAGE_BINARY_SOURCE_REL="$(get_project_meta "$project" package_binary_source_rel)"
|
|||
|
|
PACKAGE_BINARY_DEST_REL="$(get_project_meta "$project" package_binary_dest_rel)"
|
|||
|
|
PACKAGE_ICON_SOURCE_REL="$(get_project_meta "$project" package_icon_source_rel)"
|
|||
|
|
PACKAGE_ICON_DEST_REL="$(get_project_meta "$project" package_icon_dest_rel)"
|
|||
|
|
PACKAGE_SERVICE_SOURCE_REL="$(get_project_meta "$project" package_service_source_rel)"
|
|||
|
|
PACKAGE_SERVICE_DEST_REL="$(get_project_meta "$project" package_service_dest_rel)"
|
|||
|
|
PACKAGE_LD_CONF_EXTRA_LINES="$(get_project_meta "$project" package_ld_conf_extra_lines)"
|
|||
|
|
PACKAGE_OPENCV_PROFILE="$(get_project_meta "$project" package_opencv_profile)"
|
|||
|
|
|
|||
|
|
local serialized
|
|||
|
|
serialized="${PROJECT_COPY_SPECS[$project]:-}"
|
|||
|
|
PACKAGE_COPY_SPECS=()
|
|||
|
|
if [ -n "$serialized" ]; then
|
|||
|
|
while IFS= read -r line; do
|
|||
|
|
[ -n "$line" ] && PACKAGE_COPY_SPECS+=("$line")
|
|||
|
|
done <<< "$serialized"
|
|||
|
|
fi
|
|||
|
|
serialized="${PROJECT_OPTIONAL_COPY_SPECS[$project]:-}"
|
|||
|
|
PACKAGE_OPTIONAL_COPY_SPECS=()
|
|||
|
|
if [ -n "$serialized" ]; then
|
|||
|
|
while IFS= read -r line; do
|
|||
|
|
[ -n "$line" ] && PACKAGE_OPTIONAL_COPY_SPECS+=("$line")
|
|||
|
|
done <<< "$serialized"
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# ===== 版本读取 =====
|
|||
|
|
|
|||
|
|
read_project_version() {
|
|||
|
|
local version_file=$1 version_macro=$2
|
|||
|
|
local candidate value
|
|||
|
|
|
|||
|
|
PROJECT_VERSION="$DEFAULT_VERSION_STRING"
|
|||
|
|
PROJECT_BUILD="$DEFAULT_BUILD_NUMBER"
|
|||
|
|
|
|||
|
|
[ ! -f "$version_file" ] && return 0
|
|||
|
|
|
|||
|
|
for candidate in "${version_macro}_VERSION_STRING" "${version_macro}_APP_VERSION_STRING"; do
|
|||
|
|
value=$(grep -E "^#define[[:space:]]+${candidate}[[:space:]]+\"" "$version_file" | sed -E 's/.*"([^"]+)".*/\1/' | head -n 1 || true)
|
|||
|
|
if [ -n "$value" ]; then PROJECT_VERSION="$value"; break; fi
|
|||
|
|
done
|
|||
|
|
[ -z "$PROJECT_VERSION" ] && PROJECT_VERSION="$DEFAULT_VERSION_STRING"
|
|||
|
|
|
|||
|
|
for candidate in "${version_macro}_BUILD_STRING" "${version_macro}_VERSION_BUILD" "${version_macro}_APP_VERSION_BUILD"; do
|
|||
|
|
value=$(grep -E "^#define[[:space:]]+${candidate}[[:space:]]+\"" "$version_file" | sed -E 's/.*"([^"]+)".*/\1/' | head -n 1 || true)
|
|||
|
|
if [ -n "$value" ]; then PROJECT_BUILD="$value"; break; fi
|
|||
|
|
done
|
|||
|
|
[ -z "$PROJECT_BUILD" ] && PROJECT_BUILD="$DEFAULT_BUILD_NUMBER"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# ===== 内部注册函数 =====
|
|||
|
|
|
|||
|
|
_finalize_project_meta() {
|
|||
|
|
local project=$1
|
|||
|
|
local -n meta_ref=$2
|
|||
|
|
|
|||
|
|
if [ -n "${meta_ref[app_dir_rel]}" ]; then
|
|||
|
|
local app_binary_name package_slug
|
|||
|
|
app_binary_name=$(basename "${meta_ref[app_dir_rel]}")
|
|||
|
|
|
|||
|
|
# 服务项目: 先推导 package_name
|
|||
|
|
if [ "${meta_ref[package_kind]}" = "service" ] && [ "${meta_ref[package_name]}" = "$project" ]; then
|
|||
|
|
meta_ref[package_name]="$app_binary_name"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
package_slug=$(printf '%s' "${meta_ref[package_name]}" | tr '[:upper:]' '[:lower:]')
|
|||
|
|
|
|||
|
|
: "${meta_ref[version_file_rel]:=${meta_ref[app_dir_rel]}/Version.h}"
|
|||
|
|
: "${meta_ref[package_binary_source_rel]:=GrabBagPrj/buildarm/${meta_ref[app_dir_rel]}/${app_binary_name}}"
|
|||
|
|
|
|||
|
|
if [ -z "${meta_ref[package_binary_dest_rel]}" ]; then
|
|||
|
|
if [ "${meta_ref[package_kind]}" = "service" ]; then
|
|||
|
|
meta_ref[package_binary_dest_rel]="opt/${package_slug}/${app_binary_name}"
|
|||
|
|
else
|
|||
|
|
meta_ref[package_binary_dest_rel]="usr/local/bin/${app_binary_name}"
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
: "${meta_ref[package_icon_source_rel]:=${meta_ref[app_dir_rel]}/resource/logo.png}"
|
|||
|
|
|
|||
|
|
if [ "${meta_ref[package_kind]}" = "desktop" ]; then
|
|||
|
|
: "${meta_ref[package_icon_dest_rel]:=usr/share/pixmaps/${package_slug}.png}"
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
if [ "${meta_ref[package_kind]}" = "service" ]; then
|
|||
|
|
: "${meta_ref[package_service_source_rel]:=${meta_ref[app_dir_rel]}/${package_slug}.service}"
|
|||
|
|
: "${meta_ref[package_service_dest_rel]:=opt/${package_slug}/${package_slug}.service}"
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
|
|||
|
|
# publish_name 自动推导
|
|||
|
|
if [ -z "${meta_ref[publish_name]}" ]; then
|
|||
|
|
if [ "${meta_ref[package_kind]}" = "service" ]; then
|
|||
|
|
meta_ref[publish_name]="${meta_ref[package_name]}"
|
|||
|
|
else
|
|||
|
|
meta_ref[publish_name]="$project"
|
|||
|
|
fi
|
|||
|
|
fi
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_register_project() {
|
|||
|
|
local project=$1; shift
|
|||
|
|
|
|||
|
|
local -A meta=(
|
|||
|
|
[app_dir_rel]=""
|
|||
|
|
[version_file_rel]=""
|
|||
|
|
[version_macro]=""
|
|||
|
|
[publish_name]=""
|
|||
|
|
[package_name]="$project"
|
|||
|
|
[package_kind]="desktop"
|
|||
|
|
[package_description]=""
|
|||
|
|
[package_comment]=""
|
|||
|
|
[package_binary_source_rel]=""
|
|||
|
|
[package_binary_dest_rel]=""
|
|||
|
|
[package_icon_source_rel]=""
|
|||
|
|
[package_icon_dest_rel]=""
|
|||
|
|
[package_service_source_rel]=""
|
|||
|
|
[package_service_dest_rel]=""
|
|||
|
|
[package_ld_conf_extra_lines]=""
|
|||
|
|
[package_opencv_profile]=""
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
local kv key value
|
|||
|
|
for kv in "$@"; do
|
|||
|
|
key="${kv%%=*}"; value="${kv#*=}"
|
|||
|
|
if [[ -v "meta[$key]" ]]; then
|
|||
|
|
meta["$key"]="$value"
|
|||
|
|
else
|
|||
|
|
echo "Unknown field: ${key} (${project})" >&2; return 1
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
|
|||
|
|
_finalize_project_meta "$project" meta || return 1
|
|||
|
|
|
|||
|
|
ALL_PROJECTS+=("$project")
|
|||
|
|
|
|||
|
|
local k
|
|||
|
|
for k in "${!meta[@]}"; do
|
|||
|
|
set_project_meta "$project" "$k" "${meta[$k]}"
|
|||
|
|
done
|
|||
|
|
PROJECT_COPY_SPECS["$project"]=""
|
|||
|
|
PROJECT_OPTIONAL_COPY_SPECS["$project"]=""
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_register_desktop_project() {
|
|||
|
|
local project=$1 app_dir_rel=$2 version_macro=$3; shift 3
|
|||
|
|
_register_project "$project" "app_dir_rel=$app_dir_rel" "version_macro=$version_macro" "$@"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_register_service_project() {
|
|||
|
|
local project=$1 app_dir_rel=$2 version_macro=$3; shift 3
|
|||
|
|
_register_project "$project" "app_dir_rel=$app_dir_rel" "version_macro=$version_macro" "package_kind=service" "$@"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_set_copy_specs() {
|
|||
|
|
local project=$1; shift
|
|||
|
|
PROJECT_COPY_SPECS["$project"]="$(printf '%s\n' "$@")"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_set_optional_copy_specs() {
|
|||
|
|
local project=$1; shift
|
|||
|
|
PROJECT_OPTIONAL_COPY_SPECS["$project"]="$(printf '%s\n' "$@")"
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
# ===== 批量注册函数(读取 project_registry.sh 中定义的数组)=====
|
|||
|
|
|
|||
|
|
_parse_kv_overrides() {
|
|||
|
|
# 用法: _parse_kv_overrides fields_array start_index var1 var2 ...
|
|||
|
|
# 从 fields[start_index] 开始解析 key=value,赋值给同名变量
|
|||
|
|
local -n _fields=$1
|
|||
|
|
local _start=$2; shift 2
|
|||
|
|
local _allowed_keys=("$@")
|
|||
|
|
local _i _kv _key _value
|
|||
|
|
|
|||
|
|
for (( _i=_start; _i<${#_fields[@]}; _i++ )); do
|
|||
|
|
_kv="$(_trim_leading_spaces "${_fields[$_i]}")"
|
|||
|
|
[ -z "$_kv" ] && continue
|
|||
|
|
_key="${_kv%%=*}"; _value="${_kv#*=}"
|
|||
|
|
local _found=false _ak
|
|||
|
|
for _ak in "${_allowed_keys[@]}"; do
|
|||
|
|
if [ "$_key" = "$_ak" ]; then
|
|||
|
|
eval "$_key=\"\$_value\""
|
|||
|
|
_found=true; break
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
if [ "$_found" = false ]; then
|
|||
|
|
echo "Unknown override key: $_key" >&2
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_register_desktop_projects() {
|
|||
|
|
local entry fields name algo
|
|||
|
|
local app_dir version_macro opencv algo_copy device_copy extra_copy optional_copy ld_conf description comment
|
|||
|
|
|
|||
|
|
for entry in "${DESKTOP_PROJECTS[@]}"; do
|
|||
|
|
IFS=';' read -ra fields <<< "$entry"
|
|||
|
|
name="$(_trim_leading_spaces "${fields[0]}")"
|
|||
|
|
algo="$(_trim_leading_spaces "${fields[1]}")"
|
|||
|
|
|
|||
|
|
# 默认值
|
|||
|
|
app_dir="App/${name}/${name}App"
|
|||
|
|
version_macro=$(printf '%s' "$name" | tr '[:lower:]' '[:upper:]')
|
|||
|
|
opencv="" algo_copy="" device_copy="$COPY_VZNLSDK" extra_copy="" optional_copy=""
|
|||
|
|
ld_conf="" description="" comment=""
|
|||
|
|
|
|||
|
|
_parse_kv_overrides fields 2 \
|
|||
|
|
app_dir version_macro opencv algo_copy device_copy extra_copy optional_copy ld_conf description comment
|
|||
|
|
|
|||
|
|
: "${algo_copy:=glob|AppAlgo/${algo}/Arm/aarch64/*.so|usr/lib}"
|
|||
|
|
|
|||
|
|
# register
|
|||
|
|
local reg_args=()
|
|||
|
|
[ -n "$opencv" ] && reg_args+=("package_opencv_profile=$opencv")
|
|||
|
|
[ -n "$ld_conf" ] && reg_args+=("package_ld_conf_extra_lines=$ld_conf")
|
|||
|
|
[ -n "$description" ] && reg_args+=("package_description=$description")
|
|||
|
|
[ -n "$comment" ] && reg_args+=("package_comment=$comment")
|
|||
|
|
|
|||
|
|
_register_desktop_project "$name" "$app_dir" "$version_macro" "${reg_args[@]}"
|
|||
|
|
|
|||
|
|
# copy specs
|
|||
|
|
local specs=("$algo_copy")
|
|||
|
|
[ -n "$device_copy" ] && [ "$device_copy" != "none" ] && specs+=("$device_copy")
|
|||
|
|
[ -n "$extra_copy" ] && specs+=("$extra_copy")
|
|||
|
|
_set_copy_specs "$name" "${specs[@]}"
|
|||
|
|
|
|||
|
|
# optional copy
|
|||
|
|
if [ -n "$optional_copy" ]; then
|
|||
|
|
_set_optional_copy_specs "$name" "$optional_copy"
|
|||
|
|
elif [ "$device_copy" != "$COPY_VZNLSDK" ]; then
|
|||
|
|
_set_optional_copy_specs "$name" "$COPY_VZNLSDK"
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
_register_service_projects() {
|
|||
|
|
local entry fields name algo
|
|||
|
|
local app_suffix version_macro opencv device_copy description
|
|||
|
|
|
|||
|
|
for entry in "${SERVICE_PROJECTS[@]}"; do
|
|||
|
|
IFS=';' read -ra fields <<< "$entry"
|
|||
|
|
name="$(_trim_leading_spaces "${fields[0]}")"
|
|||
|
|
algo="$(_trim_leading_spaces "${fields[1]}")"
|
|||
|
|
|
|||
|
|
# 默认值
|
|||
|
|
app_suffix="Server" version_macro="" opencv=""
|
|||
|
|
device_copy="$COPY_VZNLSDK" description=""
|
|||
|
|
|
|||
|
|
_parse_kv_overrides fields 2 \
|
|||
|
|
app_suffix version_macro opencv device_copy description
|
|||
|
|
|
|||
|
|
: "${version_macro:=$(printf '%s' "$name" | tr '[:lower:]' '[:upper:]')}"
|
|||
|
|
|
|||
|
|
# register
|
|||
|
|
local reg_args=()
|
|||
|
|
[ -n "$opencv" ] && reg_args+=("package_opencv_profile=$opencv")
|
|||
|
|
[ -n "$description" ] && reg_args+=("package_description=$description")
|
|||
|
|
|
|||
|
|
_register_service_project "$name" "App/${name}/${name}${app_suffix}" "$version_macro" "${reg_args[@]}"
|
|||
|
|
_set_copy_specs "$name" "glob|AppAlgo/${algo}/Arm/aarch64/*.so|usr/lib" "$device_copy"
|
|||
|
|
|
|||
|
|
# 自动检测 config 目录
|
|||
|
|
local app_dir="App/${name}/${name}${app_suffix}"
|
|||
|
|
if [ -d "${SCRIPT_DIR}/../${app_dir}/config" ]; then
|
|||
|
|
local pkg_name
|
|||
|
|
pkg_name=$(get_project_meta "$name" package_name)
|
|||
|
|
local slug
|
|||
|
|
slug=$(printf '%s' "$pkg_name" | tr '[:upper:]' '[:lower:]')
|
|||
|
|
_set_optional_copy_specs "$name" "dir|${app_dir}/config|opt/${slug}/config"
|
|||
|
|
fi
|
|||
|
|
done
|
|||
|
|
}
|