#!/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
[--config ] [target...]
library.sh --data-dir [--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()
# 作用: 去掉从 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/.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 $?