首次提交
This commit is contained in:
@@ -0,0 +1,373 @@
|
||||
#!/bin/bash
|
||||
# shellcheck disable=SC2155
|
||||
if ! type "include" > /dev/null 2>&1; then
|
||||
include() {
|
||||
. "$(cd "$(dirname "$1")" && pwd)/${2}";
|
||||
};
|
||||
fi
|
||||
include "${BASH_SOURCE[0]}" ../pragma_once.bash
|
||||
if ! pragma_once ${BASH_SOURCE[0]}; then return 0; fi
|
||||
include "${BASH_SOURCE[0]}" ../base/export.bash
|
||||
false && source ../base/export.bash
|
||||
|
||||
|
||||
|
||||
|
||||
insert_after_match() {
|
||||
local file="$1"
|
||||
local pattern="$2"
|
||||
local insert_content="$3"
|
||||
if [[ ! -f "$file" ]]; then
|
||||
echo "File not found: $file"
|
||||
return 75
|
||||
fi
|
||||
local tmp="${file}.tmp"
|
||||
# 使用 awk 插入(比 sed 更稳) awk 是拓展正则表达式 \(是字面量
|
||||
echo "insert_content ${insert_content}"
|
||||
awk -v pat="$pattern" -v block="$insert_content" '
|
||||
{
|
||||
print
|
||||
if ($0 ~ pat && inserted != 1) {
|
||||
print block
|
||||
inserted=1
|
||||
}
|
||||
}
|
||||
END {
|
||||
if (inserted == 1)
|
||||
exit 0
|
||||
else
|
||||
exit 100
|
||||
}
|
||||
' "$file" >"$tmp"
|
||||
rc=$?
|
||||
if [[ $rc -eq 0 ]]; then
|
||||
mv "$tmp" "$file"
|
||||
echo "插入成功!"
|
||||
return 0
|
||||
else
|
||||
rm -f "$tmp"
|
||||
echo "插入失败没找到"
|
||||
return 76
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
|
||||
_collect_files() {
|
||||
local path_list="$1"
|
||||
local exclude_list="$2"
|
||||
local -n out_files="$3"
|
||||
local -n out_skipped="$4"
|
||||
|
||||
local paths=()
|
||||
local excludes=()
|
||||
local path=""
|
||||
local file=""
|
||||
local ex=""
|
||||
|
||||
out_files=()
|
||||
out_skipped=()
|
||||
|
||||
IFS=',' read -ra paths <<< "$path_list"
|
||||
IFS=',' read -ra excludes <<< "$exclude_list"
|
||||
|
||||
for path in "${paths[@]}"; do
|
||||
[[ -z "$path" ]] && continue
|
||||
|
||||
if [[ -f "$path" ]]; then
|
||||
local skip=0
|
||||
for ex in "${excludes[@]}"; do
|
||||
[[ -z "$ex" ]] && continue
|
||||
|
||||
if [[ "$path" == "$ex" ]] || \
|
||||
[[ "$(basename "$path")" == "$ex" ]] || \
|
||||
[[ "$path" == $ex ]]; then
|
||||
skip=1
|
||||
break
|
||||
fi
|
||||
|
||||
if [[ -d "$ex" ]]; then
|
||||
[[ "$path" == "$ex" || "$path" == "$ex"/* ]] && skip=1 && break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $skip -eq 1 ]]; then
|
||||
out_skipped+=("$path")
|
||||
else
|
||||
out_files+=("$path")
|
||||
fi
|
||||
|
||||
elif [[ -d "$path" ]]; then
|
||||
while IFS= read -r -d '' file; do
|
||||
|
||||
local skip=0
|
||||
for ex in "${excludes[@]}"; do
|
||||
[[ -z "$ex" ]] && continue
|
||||
|
||||
if [[ "$file" == "$ex" ]] || \
|
||||
[[ "$(basename "$file")" == "$ex" ]] || \
|
||||
[[ "$file" == $ex ]]; then
|
||||
skip=1
|
||||
break
|
||||
fi
|
||||
|
||||
if [[ -d "$ex" ]]; then
|
||||
[[ "$file" == "$ex" || "$file" == "$ex"/* ]] && skip=1 && break
|
||||
fi
|
||||
done
|
||||
|
||||
if [[ $skip -eq 1 ]]; then
|
||||
out_skipped+=("$file")
|
||||
else
|
||||
out_files+=("$file")
|
||||
fi
|
||||
|
||||
done < <(find "$path" -type f -print0)
|
||||
|
||||
else
|
||||
echo "WARNING: path not found, skip: $path"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
|
||||
sed_in_tree() {
|
||||
local path_list="$1"
|
||||
local search_str="$2"
|
||||
local replace_str="$3"
|
||||
local exclude_list="$4"
|
||||
|
||||
local files=()
|
||||
local skipped=()
|
||||
|
||||
_collect_files "$path_list" "$exclude_list" files skipped
|
||||
|
||||
[[ -z "$search_str" ]] && {
|
||||
log_error "search_str is empty"
|
||||
return 1
|
||||
}
|
||||
|
||||
# ================= sed 替换规则说明 =================
|
||||
# sed 替换基本格式:
|
||||
# s<分隔符>pattern<分隔符>replacement<分隔符>flags
|
||||
# --------------------------------------------------
|
||||
# 一、分隔符(delimiter)
|
||||
#
|
||||
# - 可以自定义为任意“单个字符”
|
||||
# - 常见:/ | # @
|
||||
# - 如果分隔符出现在 pattern 或 replacement 中,必须转义
|
||||
#
|
||||
# 示例:
|
||||
# s|/home/user|/tmp|g # 推荐(避免转义 /)
|
||||
#
|
||||
# --------------------------------------------------
|
||||
# 二、pattern(左边:正则表达式)
|
||||
#
|
||||
# 默认是 BRE(基本正则)
|
||||
#
|
||||
# 特殊字符:
|
||||
# . 任意字符
|
||||
# * 重复
|
||||
# ^ 行首
|
||||
# $ 行尾
|
||||
# [ ] 字符集合
|
||||
# \ 转义符
|
||||
#
|
||||
# 如果要匹配字面值,需要转义:
|
||||
# a.b -> a\.b
|
||||
#
|
||||
# --------------------------------------------------
|
||||
# 三、replacement(右边:替换内容)
|
||||
#
|
||||
# 特殊符号:
|
||||
# & 代表“整个匹配内容”
|
||||
# \1 第1个分组
|
||||
# \2 第2个分组
|
||||
# \ 转义符
|
||||
#
|
||||
# 示例:
|
||||
# s/b/&X/ -> b 变成 bX
|
||||
#
|
||||
# 如果要替换成字面 &:
|
||||
# \&
|
||||
#
|
||||
# --------------------------------------------------
|
||||
# 四、分隔符冲突
|
||||
#
|
||||
# 如果你用:
|
||||
# s|xxx|yyy|
|
||||
#
|
||||
# 那么:
|
||||
# | 出现在内容里必须写成 \|
|
||||
#
|
||||
# --------------------------------------------------
|
||||
# 五、shell 层注意(非常重要)
|
||||
#
|
||||
# 在 bash 中:
|
||||
# sed "s|$search|$replace|g"
|
||||
#
|
||||
# 实际有三层解析:
|
||||
# 1. shell 变量展开
|
||||
# 2. sed pattern(正则)
|
||||
# 3. sed replacement(特殊符号)
|
||||
#
|
||||
# 风险:
|
||||
# - pattern 被当正则(. * 等会生效)
|
||||
# - replacement 中 & 会被替换
|
||||
# - 分隔符冲突导致报错
|
||||
#
|
||||
# --------------------------------------------------
|
||||
# 六、结论
|
||||
#
|
||||
# - sed 转义符是:\
|
||||
# - 左边是正则,右边是替换语法
|
||||
# - 分隔符可以自定义,但要避免冲突
|
||||
#
|
||||
# ==================================================
|
||||
printf '%s\0' "${files[@]}" | xargs -0 sed -i "s|${search_str}|${replace_str}|g"
|
||||
log_debug "-----------------------------------"
|
||||
log_debug "【$search_str】 替换为 【$replace_str】"
|
||||
log_debug "Files : ${#files[@]}"
|
||||
log_debug "Files skipped : ${#skipped[@]}"
|
||||
}
|
||||
|
||||
|
||||
#gen_pth my.pth \
|
||||
# "D:\wyc\env\...\python3.12" \
|
||||
# "D:\wyc\env\...\lib-dynload"
|
||||
gen_python_pth() {
|
||||
local pth_file="$1"
|
||||
shift
|
||||
|
||||
if [ -z "$pth_file" ] || [ "$#" -eq 0 ]; then
|
||||
log_warn "Usage: gen_python_pth <output.pth> <path1> [path2 ...]" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local pth_dir
|
||||
pth_dir="$(cd "$(dirname "$pth_file")" 2>/dev/null && pwd)"
|
||||
if [ -z "$pth_dir" ]; then
|
||||
log_error "Error: cannot resolve pth file directory: $pth_file" >&2
|
||||
return 1
|
||||
fi
|
||||
|
||||
local p resolved
|
||||
|
||||
# 先检查,全部通过后再写文件,避免生成半截内容
|
||||
for p in "$@"; do
|
||||
case "$p" in
|
||||
/*|[A-Za-z]:[\\/]*)
|
||||
# 绝对路径:Linux /xxx 或 Windows C:\xxx / C:/xxx
|
||||
resolved="$p"
|
||||
;;
|
||||
*)
|
||||
# 相对路径:相对于 .pth 文件所在目录
|
||||
resolved="$pth_dir/$p"
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ ! -d "$resolved" ]; then
|
||||
log_error "Error: directory does not exist: $p" >&2
|
||||
log_error " resolved path: $resolved" >&2
|
||||
return 1
|
||||
fi
|
||||
done
|
||||
|
||||
: > "$pth_file" || {
|
||||
log_error "Error: cannot write to $pth_file" >&2
|
||||
return 1
|
||||
}
|
||||
|
||||
for p in "$@"; do
|
||||
echo "$p" >> "$pth_file"
|
||||
done
|
||||
|
||||
log_debug "Generated $pth_file"
|
||||
}
|
||||
|
||||
|
||||
# /ae/bash/gcc/env/win_arm_kylin_930/sysroot/usr/lib/aarch64-linux-gnu/cmake
|
||||
# sysroot/usr/lib/aarch64-linux-gnu/cmake
|
||||
|
||||
patch_system_qt5(){
|
||||
local SYSROOT="${1}"
|
||||
local CMAKE_DIR="${2}"
|
||||
local qt_host_tool_dir="${3}"
|
||||
check_directory_var qt_host_tool_dir
|
||||
check_file_ex "传入的qt_host_tool_dir不对,不包含必须文件moc.exe" "${qt_host_tool_dir}/moc.exe"
|
||||
|
||||
local dest="${SYSROOT}/usr/lib/qt5/bin"
|
||||
check_and_create_dir_var dest
|
||||
cp -r "${qt_host_tool_dir}/"* "${dest}"
|
||||
|
||||
|
||||
check_directory "${SYSROOT}"
|
||||
check_directory "${CMAKE_DIR}"
|
||||
local CMAKE_CURRENT_LIST_DIR="${CMAKE_DIR}/Qt5"
|
||||
check_directory "${CMAKE_CURRENT_LIST_DIR}"
|
||||
local exclude_list="${CMAKE_CURRENT_LIST_DIR}/Qt5Config.cmake"
|
||||
|
||||
|
||||
|
||||
|
||||
local Qt5WidgetsConfigExtras="${CMAKE_DIR}/Qt5Widgets/Qt5WidgetsConfigExtras.cmake"
|
||||
check_file_var Qt5WidgetsConfigExtras
|
||||
sed_in_tree \
|
||||
"${Qt5WidgetsConfigExtras}" \
|
||||
'bin/uic"' \
|
||||
'bin/uic.exe"' \
|
||||
""
|
||||
|
||||
|
||||
local Qt5CoreConfigExtras="${CMAKE_DIR}/Qt5Core/Qt5CoreConfigExtras.cmake"
|
||||
check_file_var Qt5CoreConfigExtras
|
||||
sed_in_tree \
|
||||
"${Qt5CoreConfigExtras}" \
|
||||
'bin/rcc"' \
|
||||
'bin/rcc.exe"' \
|
||||
""
|
||||
|
||||
sed_in_tree \
|
||||
"${Qt5CoreConfigExtras}" \
|
||||
'bin/moc"' \
|
||||
'bin/moc.exe"' \
|
||||
""
|
||||
#
|
||||
# sed_in_tree \
|
||||
# "${Qt5CoreConfigExtras}" \
|
||||
# 'bin/qmake"' \
|
||||
# 'bin/qmake.exe"' \
|
||||
# ""
|
||||
|
||||
|
||||
local QT5_DIR_LIST=""
|
||||
for d in "$CMAKE_DIR"/Qt5*; do
|
||||
[[ -d "$d" ]] || continue
|
||||
QT5_DIR_LIST+="${d},"
|
||||
done
|
||||
QT5_DIR_LIST="${QT5_DIR_LIST%,}"
|
||||
|
||||
sed_in_tree \
|
||||
"${QT5_DIR_LIST}" \
|
||||
'"/usr' \
|
||||
'"${_psc_sys_root}/usr' \
|
||||
"${exclude_list}"
|
||||
|
||||
|
||||
local rel_path=$(realpath --relative-to="${CMAKE_CURRENT_LIST_DIR}" "${SYSROOT}")
|
||||
insert_after_match \
|
||||
"${CMAKE_DIR}/Qt5/Qt5Config.cmake" \
|
||||
'get_filename_component[(]_qt5_install_prefix.*[)]' \
|
||||
"
|
||||
if(CMAKE_SYSROOT)
|
||||
set(_psc_sys_root \"\${CMAKE_SYSROOT}\")
|
||||
message(STATUS \"CMAKE_SYSROOT:psc_sys_root = \${_psc_sys_root} at \${CMAKE_CURRENT_LIST_FILE} \")
|
||||
else()
|
||||
set(_psc_sys_root \${CMAKE_CURRENT_LIST_DIR}/${rel_path})
|
||||
message(STATUS \"psc_sys_root = \${_psc_sys_root} at \${CMAKE_CURRENT_LIST_FILE} \")
|
||||
endif()
|
||||
"
|
||||
|
||||
log_info "patch_system_qt end!"
|
||||
}
|
||||
Reference in New Issue
Block a user