d777714fd1
因为 llvm clang源码cmakelist 不支持 里面汇编也不支持
947 lines
26 KiB
Bash
947 lines
26 KiB
Bash
#!/usr/bin/env bash
|
||
set -euo pipefail
|
||
|
||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||
# shellcheck source=../action/action.sh
|
||
source "$PROJECT_ROOT/scripts/action/action.sh"
|
||
LIBRARY_GIT_SOURCED=0
|
||
|
||
# INTERNAL: library_source_git()
|
||
# 作用: 按需加载 Git 操作函数。
|
||
# 参数: 无。
|
||
# 返回: 无。
|
||
# 注意: list-ops/list-cmake-ops/list-git-ops/--help 不需要加载 git.sh。Windows 下如果 git.sh 或其换行存在问题,不能影响操作枚举。
|
||
library_source_git() {
|
||
if [[ "$LIBRARY_GIT_SOURCED" == "0" ]]; then
|
||
# shellcheck source=../git/git.sh
|
||
source "$PROJECT_ROOT/scripts/git/git.sh"
|
||
LIBRARY_GIT_SOURCED=1
|
||
fi
|
||
}
|
||
|
||
library_usage() {
|
||
cat <<'USAGE'
|
||
usage:
|
||
library.sh list-ops
|
||
library.sh list-cmake-ops
|
||
library.sh list-git-ops
|
||
library.sh cmake-options --data-dir <dir> [--config <config>] [target...]
|
||
library.sh <op> --data-dir <dir> [--config <config>] [target...]
|
||
|
||
operations are implemented in Bash. CMake only prepares registry/global data and invokes this script.
|
||
USAGE
|
||
}
|
||
|
||
library_list_cmake_self_ops() {
|
||
# 每个 echo 独立一行,不使用 here-doc 或反斜杠续行,避免 Windows/Git Bash 下 CRLF 影响操作枚举输出。
|
||
# 这些是不递归依赖的单对象操作;传入哪个库 id,就只操作哪个库 id。
|
||
echo 'source'
|
||
echo 'build'
|
||
echo 'install'
|
||
echo 'auto'
|
||
echo 'rebuild'
|
||
echo 'reinstall'
|
||
echo 'reset'
|
||
echo 'clean-source'
|
||
echo 'clean-build'
|
||
echo 'clean-install'
|
||
echo 'clean-all'
|
||
}
|
||
|
||
library_list_git_self_ops() {
|
||
# Git 操作默认也是单对象操作,不递归依赖。
|
||
echo 'git-fetch'
|
||
echo 'git-pull'
|
||
echo 'git-checkout'
|
||
echo 'git-branches'
|
||
echo 'git-current-branch'
|
||
}
|
||
|
||
library_list_cmake_ops() {
|
||
# 查询操作不递归执行,不生成 with_rely_ 版本。
|
||
echo 'list-targets'
|
||
echo 'deps'
|
||
echo 'cmake-options'
|
||
library_list_cmake_self_ops
|
||
library_list_cmake_self_ops | action_list_with_rely_ops_from
|
||
}
|
||
|
||
library_list_git_ops() {
|
||
library_list_git_self_ops
|
||
library_list_git_self_ops | action_list_with_rely_ops_from
|
||
}
|
||
|
||
library_list_ops() {
|
||
library_list_cmake_ops
|
||
library_list_git_ops
|
||
}
|
||
|
||
# INTERNAL: library_strip_line_cr(<value>)
|
||
# 作用: 去掉从 Windows CRLF 文本文件读取时残留在行尾的 CR。
|
||
# 参数: value 是原始行或原始字段。
|
||
# 返回: stdout 输出去掉一个行尾 CR 后的值。
|
||
# 注意: 只清理文件行尾 CR,不等同于 codec 解码;编码值里的 %0D 会保留给 library_codec_decode 还原。
|
||
library_strip_line_cr() {
|
||
local value="$1"
|
||
# Windows/Git Bash may read CMake-generated files with CRLF.
|
||
# Some test/workflow paths can rewrite CRLF repeatedly and produce CRCRLF.
|
||
# Strip every trailing CR so values never become `cmake.exe\r`, `core\r`, or `%00\r`.
|
||
while [[ "$value" == *$'\r' ]]; do
|
||
value="${value%$'\r'}"
|
||
done
|
||
printf '%s' "$value"
|
||
}
|
||
|
||
library_codec_decode() {
|
||
local value="$1"
|
||
value="$(library_strip_line_cr "$value")"
|
||
if [[ "$value" == "%00" ]]; then
|
||
printf ''
|
||
return 0
|
||
fi
|
||
|
||
value="${value//%0D/$'\r'}"
|
||
value="${value//%0A/$'\n'}"
|
||
value="${value//%7C/|}"
|
||
value="${value//%3B/;}"
|
||
value="${value//%5C/\\}"
|
||
value="${value//%25/%}"
|
||
printf '%s' "$value"
|
||
}
|
||
|
||
library_map_get_raw() {
|
||
local file="$1"
|
||
local key="$2"
|
||
local line rest line_key value
|
||
|
||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||
line="$(library_strip_line_cr "$line")"
|
||
[[ "$line" == K\|* ]] || continue
|
||
rest="${line#K|}"
|
||
line_key="${rest%%|*}"
|
||
value="${rest#*|}"
|
||
if [[ "$line_key" == "$key" ]]; then
|
||
printf '%s' "$value"
|
||
return 0
|
||
fi
|
||
done <"$file"
|
||
|
||
printf ''
|
||
}
|
||
|
||
library_map_get() {
|
||
local file="$1"
|
||
local key="$2"
|
||
local raw
|
||
raw="$(library_map_get_raw "$file" "$key")"
|
||
library_codec_decode "$raw"
|
||
}
|
||
|
||
library_global_get() {
|
||
local key="$1"
|
||
library_map_get "$LIBRARY_DATA_DIR/globals.txt" "$key"
|
||
}
|
||
|
||
library_registry_graph() {
|
||
printf '%s/registry/graph.txt' "$LIBRARY_DATA_DIR"
|
||
}
|
||
|
||
library_registry_map_id() {
|
||
local target="$1"
|
||
local line rest node data
|
||
|
||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||
line="$(library_strip_line_cr "$line")"
|
||
[[ "$line" == N\|* ]] || continue
|
||
rest="${line#N|}"
|
||
node="${rest%%|*}"
|
||
data="${rest#*|}"
|
||
if [[ "$node" == "$target" ]]; then
|
||
printf '%s' "$data"
|
||
return 0
|
||
fi
|
||
done <"$(library_registry_graph)"
|
||
|
||
printf ''
|
||
}
|
||
|
||
library_target_node_dir() {
|
||
local target="$1"
|
||
local map_id
|
||
map_id="$(library_registry_map_id "$target")"
|
||
printf '%s/registry/nodes/%s' "$LIBRARY_DATA_DIR" "$map_id"
|
||
}
|
||
|
||
library_target_map_file() {
|
||
local target="$1"
|
||
printf '%s/map.txt' "$(library_target_node_dir "$target")"
|
||
}
|
||
|
||
library_registry_get() {
|
||
local target="$1"
|
||
local key="$2"
|
||
library_map_get "$(library_target_map_file "$target")" "$key"
|
||
}
|
||
|
||
library_target_get_or_global() {
|
||
local target="$1"
|
||
local key="$2"
|
||
local value
|
||
value="$(library_registry_get "$target" "$key")"
|
||
if [[ -z "$value" ]]; then
|
||
value="$(library_global_get "$key")"
|
||
fi
|
||
printf '%s' "$value"
|
||
}
|
||
|
||
library_all_targets() {
|
||
local line
|
||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||
line="$(library_strip_line_cr "$line")"
|
||
[[ -n "$line" ]] && printf '%s\n' "$line"
|
||
done <"$LIBRARY_DATA_DIR/build_order.txt"
|
||
}
|
||
|
||
library_direct_deps() {
|
||
local target="$1"
|
||
local line rest from to
|
||
|
||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||
line="$(library_strip_line_cr "$line")"
|
||
[[ "$line" == E\|* ]] || continue
|
||
rest="${line#E|}"
|
||
from="${rest%%|*}"
|
||
rest="${rest#*|}"
|
||
to="${rest%%|*}"
|
||
if [[ "$from" == "$target" ]]; then
|
||
printf '%s\n' "$to"
|
||
fi
|
||
done <"$(library_registry_graph)"
|
||
}
|
||
|
||
library_resolve_targets() {
|
||
if [[ "$#" -eq 0 ]]; then
|
||
library_all_targets
|
||
return 0
|
||
fi
|
||
|
||
local requested=()
|
||
local target dep line
|
||
declare -A want=()
|
||
|
||
requested=("$@")
|
||
for target in "${requested[@]}"; do
|
||
want["$target"]=1
|
||
if [[ -f "$LIBRARY_DATA_DIR/dependencies/$target.txt" ]]; then
|
||
while IFS= read -r dep || [[ -n "$dep" ]]; do
|
||
dep="$(library_strip_line_cr "$dep")"
|
||
[[ -n "$dep" ]] && want["$dep"]=1
|
||
done <"$LIBRARY_DATA_DIR/dependencies/$target.txt"
|
||
fi
|
||
done
|
||
|
||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||
line="$(library_strip_line_cr "$line")"
|
||
[[ -n "$line" ]] || continue
|
||
if [[ -n "${want[$line]+x}" ]]; then
|
||
printf '%s\n' "$line"
|
||
fi
|
||
done <"$LIBRARY_DATA_DIR/build_order.txt"
|
||
}
|
||
|
||
library_resolve_self_targets() {
|
||
if [[ "$#" -eq 0 ]]; then
|
||
library_all_targets
|
||
return 0
|
||
fi
|
||
|
||
local target
|
||
for target in "$@"; do
|
||
target="$(library_strip_line_cr "$target")"
|
||
[[ -n "$target" ]] && printf '%s\n' "$target"
|
||
done
|
||
}
|
||
|
||
library_resolve_dependencies() {
|
||
if [[ "$#" -eq 0 ]]; then
|
||
library_all_targets
|
||
return 0
|
||
fi
|
||
|
||
local target dep line
|
||
declare -A want=()
|
||
|
||
for target in "$@"; do
|
||
if [[ -f "$LIBRARY_DATA_DIR/dependencies/$target.txt" ]]; then
|
||
while IFS= read -r dep || [[ -n "$dep" ]]; do
|
||
dep="$(library_strip_line_cr "$dep")"
|
||
[[ -n "$dep" ]] && want["$dep"]=1
|
||
done <"$LIBRARY_DATA_DIR/dependencies/$target.txt"
|
||
fi
|
||
done
|
||
|
||
while IFS= read -r line || [[ -n "$line" ]]; do
|
||
line="$(library_strip_line_cr "$line")"
|
||
[[ -n "$line" ]] || continue
|
||
if [[ -n "${want[$line]+x}" ]]; then
|
||
printf '%s\n' "$line"
|
||
fi
|
||
done <"$LIBRARY_DATA_DIR/build_order.txt"
|
||
}
|
||
|
||
library_cache_root() {
|
||
local key="$1"
|
||
local value
|
||
value="$(library_global_get "$key")"
|
||
printf '%s' "$value"
|
||
}
|
||
|
||
library_source_dir() {
|
||
printf '%s/%s' "$(library_cache_root SOURCE_CACHE_ROOT)" "$1"
|
||
}
|
||
|
||
library_build_dir() {
|
||
printf '%s/%s' "$(library_cache_root BUILD_CACHE_ROOT)" "$1"
|
||
}
|
||
|
||
library_install_dir() {
|
||
printf '%s/%s' "$(library_cache_root INSTALL_CACHE_ROOT)" "$1"
|
||
}
|
||
|
||
library_lock_file() {
|
||
local step="$1"
|
||
local target="$2"
|
||
local dir
|
||
case "$step" in
|
||
source) dir="$(library_source_dir "$target")" ;;
|
||
build) dir="$(library_build_dir "$target")" ;;
|
||
install) dir="$(library_install_dir "$target")" ;;
|
||
*) dir="$(library_target_node_dir "$target")" ;;
|
||
esac
|
||
printf '%s/%s.success' "$dir" "$step"
|
||
}
|
||
|
||
library_log_file() {
|
||
local step="$1"
|
||
local target="$2"
|
||
printf '%s/%s.log' "$(library_target_node_dir "$target")" "$step"
|
||
}
|
||
|
||
library_log() {
|
||
local step="$1"
|
||
local target="$2"
|
||
local message="$3"
|
||
local log
|
||
log="$(library_log_file "$step" "$target")"
|
||
mkdir -p "$(dirname "$log")"
|
||
printf '[%s][%s][%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$target" "$step" "$message" | tee -a "$log"
|
||
}
|
||
|
||
library_mark_success() {
|
||
local step="$1"
|
||
local target="$2"
|
||
local lock
|
||
lock="$(library_lock_file "$step" "$target")"
|
||
mkdir -p "$(dirname "$lock")"
|
||
printf 'success %s %s\n' "$step" "$(date '+%Y-%m-%d %H:%M:%S')" >"$lock"
|
||
}
|
||
|
||
library_is_success() {
|
||
local step="$1"
|
||
local target="$2"
|
||
[[ -f "$(library_lock_file "$step" "$target")" ]]
|
||
}
|
||
|
||
library_print_command() {
|
||
printf '[command]'
|
||
printf ' %q' "$@"
|
||
printf '\n'
|
||
}
|
||
|
||
library_run_logged() {
|
||
local step="$1"
|
||
local target="$2"
|
||
shift 2
|
||
local log rc
|
||
log="$(library_log_file "$step" "$target")"
|
||
mkdir -p "$(dirname "$log")"
|
||
library_print_command "$@" | tee -a "$log"
|
||
set +e
|
||
"$@" 2>&1 | tee -a "$log"
|
||
rc=${PIPESTATUS[0]}
|
||
set -e
|
||
if [[ "$rc" -ne 0 ]]; then
|
||
library_log "$step" "$target" "command failed with exit code $rc"
|
||
return "$rc"
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
library_run_logged_in_dir() {
|
||
local step="$1"
|
||
local target="$2"
|
||
local dir="$3"
|
||
shift 3
|
||
local log rc
|
||
log="$(library_log_file "$step" "$target")"
|
||
mkdir -p "$(dirname "$log")"
|
||
printf '[cwd] %s\n' "$dir" | tee -a "$log"
|
||
library_print_command "$@" | tee -a "$log"
|
||
set +e
|
||
(cd "$dir" && "$@") 2>&1 | tee -a "$log"
|
||
rc=${PIPESTATUS[0]}
|
||
set -e
|
||
if [[ "$rc" -ne 0 ]]; then
|
||
library_log "$step" "$target" "command failed with exit code $rc"
|
||
return "$rc"
|
||
fi
|
||
return 0
|
||
}
|
||
|
||
library_source_one() {
|
||
local target="$1"
|
||
local dest local_source git_url git_branch
|
||
dest="$(library_source_dir "$target")"
|
||
|
||
if library_is_success source "$target"; then
|
||
library_log source "$target" 'source cache already successful, skip'
|
||
return 0
|
||
fi
|
||
|
||
mkdir -p "$dest"
|
||
local_source="$(library_registry_get "$target" LOCAL_SOURCE_DIR)"
|
||
git_url="$(library_registry_get "$target" GIT_URL)"
|
||
git_branch="$(library_registry_get "$target" GIT_BRANCH)"
|
||
|
||
library_log source "$target" "source start: dest=$dest"
|
||
|
||
if [[ -n "$local_source" ]]; then
|
||
mkdir -p "$dest"
|
||
library_run_logged source "$target" cp -a "$local_source/." "$dest/"
|
||
elif [[ -n "$git_url" ]]; then
|
||
library_source_git
|
||
library_run_logged source "$target" library_git_clone_or_update "$git_url" "$git_branch" "$dest"
|
||
else
|
||
library_log source "$target" 'no LOCAL_SOURCE_DIR or GIT_URL; created empty source cache'
|
||
fi
|
||
|
||
library_mark_success source "$target"
|
||
}
|
||
|
||
library_split_semicolon_words() {
|
||
local value="$1"
|
||
local old_ifs="$IFS"
|
||
IFS=';'
|
||
# shellcheck disable=SC2206
|
||
LIBRARY_SPLIT_RESULT=($value)
|
||
IFS="$old_ifs"
|
||
}
|
||
|
||
library_cmake_command() {
|
||
local value
|
||
value="$(library_global_get CMAKE_COMMAND)"
|
||
if [[ -z "$value" ]]; then
|
||
value="cmake"
|
||
fi
|
||
printf '%s' "$value"
|
||
}
|
||
|
||
library_build_config() {
|
||
local target="$1"
|
||
local value
|
||
value="$LIBRARY_CLI_CONFIG"
|
||
if [[ -z "$value" ]]; then
|
||
value="$(library_target_get_or_global "$target" CMAKE_BUILD_CONFIG)"
|
||
fi
|
||
if [[ -z "$value" ]]; then
|
||
value="$(library_target_get_or_global "$target" CMAKE_BUILD_TYPE)"
|
||
fi
|
||
printf '%s' "$value"
|
||
}
|
||
|
||
library_build_one() {
|
||
local target="$1"
|
||
local source source_root source_subdir build install cmake_cmd generator platform toolset toolchain build_type options configure_preset build_preset config dep dep_options
|
||
source_root="$(library_source_dir "$target")"
|
||
source_subdir="$(library_registry_get "$target" CMAKE_SOURCE_SUBDIR)"
|
||
source="$source_root"
|
||
if [[ -n "$source_subdir" ]]; then
|
||
source="$source_root/$source_subdir"
|
||
fi
|
||
build="$(library_build_dir "$target")"
|
||
install="$(library_install_dir "$target")"
|
||
cmake_cmd="$(library_cmake_command)"
|
||
|
||
if library_is_success build "$target"; then
|
||
library_log build "$target" 'build cache already successful, skip'
|
||
return 0
|
||
fi
|
||
|
||
mkdir -p "$build" "$install"
|
||
generator="$(library_target_get_or_global "$target" CMAKE_GENERATOR)"
|
||
platform="$(library_target_get_or_global "$target" CMAKE_GENERATOR_PLATFORM)"
|
||
toolset="$(library_target_get_or_global "$target" CMAKE_GENERATOR_TOOLSET)"
|
||
toolchain="$(library_target_get_or_global "$target" CMAKE_TOOLCHAIN_FILE)"
|
||
build_type="$(library_target_get_or_global "$target" CMAKE_BUILD_TYPE)"
|
||
options="$(library_registry_get "$target" CMAKE_OPTIONS)"
|
||
configure_preset="$(library_target_get_or_global "$target" CMAKE_CONFIGURE_PRESET)"
|
||
build_preset="$(library_target_get_or_global "$target" CMAKE_BUILD_PRESET)"
|
||
config="$(library_build_config "$target")"
|
||
|
||
local configure_cmd
|
||
if [[ -n "$configure_preset" ]]; then
|
||
configure_cmd=("$cmake_cmd" -S "$source" -B "$build" --preset "$configure_preset" -DCMAKE_INSTALL_PREFIX="$install")
|
||
else
|
||
configure_cmd=("$cmake_cmd" -S "$source" -B "$build" -DCMAKE_INSTALL_PREFIX="$install")
|
||
[[ -n "$generator" ]] && configure_cmd+=(-G "$generator")
|
||
[[ -n "$platform" ]] && configure_cmd+=(-A "$platform")
|
||
[[ -n "$toolset" ]] && configure_cmd+=(-T "$toolset")
|
||
[[ -n "$toolchain" ]] && configure_cmd+=(-DCMAKE_TOOLCHAIN_FILE="$toolchain")
|
||
[[ -n "$build_type" ]] && configure_cmd+=(-DCMAKE_BUILD_TYPE="$build_type")
|
||
fi
|
||
|
||
# OTHER_USE_OPT 是依赖库提供给“使用者”的 CMake configure 参数。
|
||
# 构建当前 target 时,先按 dependencies/<target>.txt 的依赖闭包顺序追加依赖库 OTHER_USE_OPT,
|
||
# 再追加当前 target 自己的 CMAKE_OPTIONS,让当前库的显式配置可以覆盖依赖库给出的默认使用参数。
|
||
while IFS= read -r dep || [[ -n "$dep" ]]; do
|
||
dep_options="$(library_registry_get "$dep" OTHER_USE_OPT)"
|
||
library_split_semicolon_words "$dep_options"
|
||
configure_cmd+=("${LIBRARY_SPLIT_RESULT[@]}")
|
||
done < <(library_resolve_dependencies "$target")
|
||
|
||
if [[ -n "$options" ]]; then
|
||
library_split_semicolon_words "$options"
|
||
configure_cmd+=("${LIBRARY_SPLIT_RESULT[@]}")
|
||
fi
|
||
|
||
library_log build "$target" "configure/build start: source_root=$source_root source_subdir=$source_subdir source=$source build=$build install=$install configure_preset=$configure_preset build_preset=$build_preset config=$config"
|
||
library_run_logged build "$target" "${configure_cmd[@]}"
|
||
|
||
local build_cmd
|
||
if [[ -n "$build_preset" ]]; then
|
||
build_cmd=("$cmake_cmd" --build --preset "$build_preset")
|
||
[[ -n "$config" ]] && build_cmd+=(--config "$config")
|
||
library_run_logged_in_dir build "$target" "$source" "${build_cmd[@]}"
|
||
else
|
||
build_cmd=("$cmake_cmd" --build "$build")
|
||
[[ -n "$config" ]] && build_cmd+=(--config "$config")
|
||
library_run_logged build "$target" "${build_cmd[@]}"
|
||
fi
|
||
|
||
library_mark_success build "$target"
|
||
}
|
||
|
||
library_cmake_options_one() {
|
||
local target="$1"
|
||
local source source_root source_subdir build install cmake_cmd generator platform toolset toolchain build_type options configure_preset config dep dep_options
|
||
source_root="$(library_source_dir "$target")"
|
||
if [[ ! -d "$source_root" ]]; then
|
||
rm -f "$(library_lock_file source "$target")"
|
||
fi
|
||
library_source_one "$target"
|
||
source_subdir="$(library_registry_get "$target" CMAKE_SOURCE_SUBDIR)"
|
||
source="$source_root"
|
||
if [[ -n "$source_subdir" ]]; then
|
||
source="$source_root/$source_subdir"
|
||
fi
|
||
build="$(library_build_dir "$target")"
|
||
install="$(library_install_dir "$target")"
|
||
cmake_cmd="$(library_cmake_command)"
|
||
mkdir -p "$build" "$install"
|
||
generator="$(library_target_get_or_global "$target" CMAKE_GENERATOR)"
|
||
platform="$(library_target_get_or_global "$target" CMAKE_GENERATOR_PLATFORM)"
|
||
toolset="$(library_target_get_or_global "$target" CMAKE_GENERATOR_TOOLSET)"
|
||
toolchain="$(library_target_get_or_global "$target" CMAKE_TOOLCHAIN_FILE)"
|
||
build_type="$(library_target_get_or_global "$target" CMAKE_BUILD_TYPE)"
|
||
options="$(library_registry_get "$target" CMAKE_OPTIONS)"
|
||
configure_preset="$(library_target_get_or_global "$target" CMAKE_CONFIGURE_PRESET)"
|
||
config="$(library_build_config "$target")"
|
||
|
||
local configure_cmd
|
||
if [[ -n "$configure_preset" ]]; then
|
||
configure_cmd=("$cmake_cmd" -S "$source" -B "$build" --preset "$configure_preset" -DCMAKE_INSTALL_PREFIX="$install")
|
||
else
|
||
configure_cmd=("$cmake_cmd" -S "$source" -B "$build" -DCMAKE_INSTALL_PREFIX="$install")
|
||
[[ -n "$generator" ]] && configure_cmd+=(-G "$generator")
|
||
[[ -n "$platform" ]] && configure_cmd+=(-A "$platform")
|
||
[[ -n "$toolset" ]] && configure_cmd+=(-T "$toolset")
|
||
[[ -n "$toolchain" ]] && configure_cmd+=(-DCMAKE_TOOLCHAIN_FILE="$toolchain")
|
||
[[ -n "$build_type" ]] && configure_cmd+=(-DCMAKE_BUILD_TYPE="$build_type")
|
||
fi
|
||
|
||
while IFS= read -r dep || [[ -n "$dep" ]]; do
|
||
dep_options="$(library_registry_get "$dep" OTHER_USE_OPT)"
|
||
library_split_semicolon_words "$dep_options"
|
||
configure_cmd+=("${LIBRARY_SPLIT_RESULT[@]}")
|
||
done < <(library_resolve_dependencies "$target")
|
||
|
||
if [[ -n "$options" ]]; then
|
||
library_split_semicolon_words "$options"
|
||
configure_cmd+=("${LIBRARY_SPLIT_RESULT[@]}")
|
||
fi
|
||
|
||
library_log cmake-options "$target" "configure/options start: source=$source build=$build install=$install configure_preset=$configure_preset config=$config"
|
||
library_run_logged cmake-options "$target" "${configure_cmd[@]}"
|
||
library_run_logged cmake-options "$target" "$cmake_cmd" -LAH -N "$build"
|
||
}
|
||
|
||
library_install_one() {
|
||
local target="$1"
|
||
local build install cmake_cmd install_preset config source_root source_subdir source
|
||
build="$(library_build_dir "$target")"
|
||
install="$(library_install_dir "$target")"
|
||
cmake_cmd="$(library_cmake_command)"
|
||
install_preset="$(library_target_get_or_global "$target" CMAKE_INSTALL_PRESET)"
|
||
config="$(library_build_config "$target")"
|
||
source_root="$(library_source_dir "$target")"
|
||
source_subdir="$(library_registry_get "$target" CMAKE_SOURCE_SUBDIR)"
|
||
source="$source_root"
|
||
if [[ -n "$source_subdir" ]]; then
|
||
source="$source_root/$source_subdir"
|
||
fi
|
||
|
||
if library_is_success install "$target"; then
|
||
library_log install "$target" 'install cache already successful, skip'
|
||
return 0
|
||
fi
|
||
|
||
mkdir -p "$install"
|
||
library_log install "$target" "install start: build=$build install=$install install_preset=$install_preset config=$config"
|
||
|
||
local install_cmd
|
||
if [[ -n "$install_preset" ]]; then
|
||
install_cmd=("$cmake_cmd" --install --preset "$install_preset")
|
||
[[ -n "$config" ]] && install_cmd+=(--config "$config")
|
||
library_run_logged_in_dir install "$target" "$source" "${install_cmd[@]}"
|
||
else
|
||
install_cmd=("$cmake_cmd" --install "$build" --prefix "$install")
|
||
[[ -n "$config" ]] && install_cmd+=(--config "$config")
|
||
library_run_logged install "$target" "${install_cmd[@]}"
|
||
fi
|
||
|
||
library_mark_success install "$target"
|
||
}
|
||
|
||
library_auto_one() {
|
||
local target="$1"
|
||
if library_is_success install "$target"; then
|
||
library_log install "$target" 'auto: install successful, skip target'
|
||
return 0
|
||
fi
|
||
|
||
if ! library_is_success build "$target"; then
|
||
if ! library_is_success source "$target"; then
|
||
library_source_one "$target"
|
||
fi
|
||
library_build_one "$target"
|
||
fi
|
||
|
||
library_install_one "$target"
|
||
}
|
||
|
||
library_clean_one() {
|
||
local step="$1"
|
||
local target="$2"
|
||
case "$step" in
|
||
source)
|
||
rm -rf "$(library_source_dir "$target")"
|
||
rm -f "$(library_lock_file source "$target")"
|
||
;;
|
||
build)
|
||
rm -rf "$(library_build_dir "$target")"
|
||
rm -f "$(library_lock_file build "$target")"
|
||
;;
|
||
install)
|
||
rm -rf "$(library_install_dir "$target")"
|
||
rm -f "$(library_lock_file install "$target")"
|
||
;;
|
||
all)
|
||
rm -rf "$(library_source_dir "$target")" "$(library_build_dir "$target")" "$(library_install_dir "$target")"
|
||
rm -f "$(library_lock_file source "$target")" "$(library_lock_file build "$target")" "$(library_lock_file install "$target")"
|
||
;;
|
||
esac
|
||
}
|
||
|
||
library_git_repo_for_target() {
|
||
local target="$1"
|
||
printf '%s' "$(library_source_dir "$target")"
|
||
}
|
||
|
||
library_git_fetch_one() {
|
||
library_source_git
|
||
local target="$1"
|
||
local repo
|
||
repo="$(library_git_repo_for_target "$target")"
|
||
library_log git-fetch "$target" "git fetch start: repo=$repo"
|
||
library_run_logged git-fetch "$target" library_git_fetch "$repo"
|
||
library_mark_success git-fetch "$target"
|
||
}
|
||
|
||
library_git_pull_one() {
|
||
library_source_git
|
||
local target="$1"
|
||
local repo
|
||
repo="$(library_git_repo_for_target "$target")"
|
||
library_log git-pull "$target" "git pull start: repo=$repo"
|
||
library_run_logged git-pull "$target" library_git_pull "$repo"
|
||
library_mark_success git-pull "$target"
|
||
}
|
||
|
||
library_git_checkout_one() {
|
||
library_source_git
|
||
local target="$1"
|
||
local repo branch
|
||
repo="$(library_git_repo_for_target "$target")"
|
||
branch="$(library_registry_get "$target" GIT_BRANCH)"
|
||
if [[ -n "$branch" ]]; then
|
||
library_log git-checkout "$target" "git checkout start: repo=$repo branch=$branch"
|
||
library_run_logged git-checkout "$target" library_git_checkout "$repo" "$branch"
|
||
library_mark_success git-checkout "$target"
|
||
else
|
||
library_log git-checkout "$target" 'GIT_BRANCH is empty, skip checkout'
|
||
library_mark_success git-checkout "$target"
|
||
fi
|
||
}
|
||
|
||
library_git_branches_one() {
|
||
library_source_git
|
||
local target="$1"
|
||
local repo
|
||
repo="$(library_git_repo_for_target "$target")"
|
||
echo "[$target]"
|
||
library_log git-branches "$target" "git branch list: repo=$repo"
|
||
library_run_logged git-branches "$target" library_git_branch_list "$repo"
|
||
library_mark_success git-branches "$target"
|
||
}
|
||
|
||
library_git_current_branch_one() {
|
||
library_source_git
|
||
local target="$1"
|
||
local repo
|
||
repo="$(library_git_repo_for_target "$target")"
|
||
library_log git-current-branch "$target" "git current branch: repo=$repo"
|
||
library_run_logged git-current-branch "$target" library_git_branch_current "$repo"
|
||
library_mark_success git-current-branch "$target"
|
||
}
|
||
|
||
library_run_operation() {
|
||
local op="$1"
|
||
shift
|
||
local targets=()
|
||
local with_rely=0
|
||
|
||
if action_is_with_rely "$op"; then
|
||
with_rely=1
|
||
op="$(action_strip_with_rely "$op")"
|
||
fi
|
||
|
||
case "$op" in
|
||
list-targets)
|
||
library_all_targets
|
||
return 0
|
||
;;
|
||
deps)
|
||
library_resolve_dependencies "$@"
|
||
return 0
|
||
;;
|
||
cmake-options)
|
||
local t
|
||
mapfile -t targets < <(library_resolve_self_targets "$@")
|
||
for t in "${targets[@]}"; do
|
||
library_cmake_options_one "$t"
|
||
done
|
||
return 0
|
||
;;
|
||
esac
|
||
|
||
if [[ "$with_rely" == "1" ]]; then
|
||
mapfile -t targets < <(library_resolve_targets "$@")
|
||
else
|
||
mapfile -t targets < <(library_resolve_self_targets "$@")
|
||
fi
|
||
|
||
case "$op" in
|
||
source)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_source_one "$t"
|
||
done
|
||
;;
|
||
build)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_source_one "$t"
|
||
library_build_one "$t"
|
||
done
|
||
;;
|
||
install)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_source_one "$t"
|
||
library_build_one "$t"
|
||
library_install_one "$t"
|
||
done
|
||
;;
|
||
auto)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_auto_one "$t"
|
||
done
|
||
;;
|
||
rebuild)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_clean_one build "$t"
|
||
library_clean_one install "$t"
|
||
library_source_one "$t"
|
||
library_build_one "$t"
|
||
library_install_one "$t"
|
||
done
|
||
;;
|
||
reinstall)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_clean_one install "$t"
|
||
library_install_one "$t"
|
||
done
|
||
;;
|
||
reset)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_clean_one all "$t"
|
||
library_source_one "$t"
|
||
library_build_one "$t"
|
||
library_install_one "$t"
|
||
done
|
||
;;
|
||
clean-source)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_clean_one source "$t"
|
||
done
|
||
;;
|
||
clean-build)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_clean_one build "$t"
|
||
done
|
||
;;
|
||
clean-install)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_clean_one install "$t"
|
||
done
|
||
;;
|
||
clean-all)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_clean_one all "$t"
|
||
done
|
||
;;
|
||
git-fetch)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_git_fetch_one "$t"
|
||
done
|
||
;;
|
||
git-pull)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_git_pull_one "$t"
|
||
done
|
||
;;
|
||
git-checkout)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_git_checkout_one "$t"
|
||
done
|
||
;;
|
||
git-branches)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_git_branches_one "$t"
|
||
done
|
||
;;
|
||
git-current-branch)
|
||
local t
|
||
for t in "${targets[@]}"; do
|
||
library_git_current_branch_one "$t"
|
||
done
|
||
;;
|
||
*)
|
||
echo "unknown operation: $op" >&2
|
||
return 2
|
||
;;
|
||
esac
|
||
}
|
||
|
||
main() {
|
||
if [[ "$#" -eq 0 ]]; then
|
||
library_usage >&2
|
||
return 2
|
||
fi
|
||
|
||
local op="$1"
|
||
shift
|
||
|
||
case "$op" in
|
||
list-ops)
|
||
library_list_ops
|
||
return 0
|
||
;;
|
||
list-cmake-ops)
|
||
library_list_cmake_ops
|
||
return 0
|
||
;;
|
||
list-git-ops)
|
||
library_list_git_ops
|
||
return 0
|
||
;;
|
||
-h | --help | help)
|
||
library_usage
|
||
return 0
|
||
;;
|
||
esac
|
||
|
||
LIBRARY_DATA_DIR=""
|
||
LIBRARY_CLI_CONFIG=""
|
||
local targets=()
|
||
while [[ "$#" -gt 0 ]]; do
|
||
case "$1" in
|
||
--data-dir)
|
||
LIBRARY_DATA_DIR="$2"
|
||
shift 2
|
||
;;
|
||
--config)
|
||
LIBRARY_CLI_CONFIG="$2"
|
||
shift 2
|
||
;;
|
||
--)
|
||
shift
|
||
while [[ "$#" -gt 0 ]]; do
|
||
targets+=("$1")
|
||
shift
|
||
done
|
||
;;
|
||
*)
|
||
targets+=("$1")
|
||
shift
|
||
;;
|
||
esac
|
||
done
|
||
|
||
if [[ -z "$LIBRARY_DATA_DIR" ]]; then
|
||
echo "--data-dir is required for operation: $op" >&2
|
||
return 2
|
||
fi
|
||
|
||
if [[ -z "$LIBRARY_CLI_CONFIG" ]]; then
|
||
LIBRARY_CLI_CONFIG="$(library_global_get CMAKE_BUILD_CONFIG)"
|
||
fi
|
||
|
||
library_run_operation "$op" "${targets[@]}"
|
||
}
|
||
|
||
main "$@"
|
||
exit $? |