添加自动打包脚本。

This commit is contained in:
2026-03-17 14:21:59 +08:00
parent 5b18af4279
commit 8e7c1408f7
8 changed files with 349 additions and 26 deletions

View File

@@ -1,9 +1,9 @@
{
"files.autoSave": "onFocusChange",
"editor.fontSize": 14,
"editor.fontFamily": "'Maple Mono NL NF CN Light', 'Maple Mono NL NF CN Light', 'Maple Mono NL NF CN Light'",
"editor.fontFamily": "'Source Code Pro', 'Source Code Pro', 'Source Code Pro'",
"editor.wordWrap": "on",
"terminal.integrated.fontFamily": "'Maple Mono NL NF CN Light'",
"terminal.integrated.fontFamily": "'Source Code Pro'",
"cmake.configureOnOpen": true,
//"C_Cpp.intelliSenseEngine": "disabled",
"cmake.debugConfig": {

View File

@@ -11,6 +11,22 @@ if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
execute_process(
COMMAND git rev-parse --short HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE VERSION_GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE VERSION_GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
configure_file(Tools.h.in Tools.h)
message(STATUS "Version file config to: ${CMAKE_CURRENT_BINARY_DIR}")
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_subdirectory(zoost)
add_subdirectory(strReplace)
add_subdirectory(fileUpdater)

10
Tools.h.in Normal file
View File

@@ -0,0 +1,10 @@
#ifndef FILEUPDATER_VERSION_H
#define FILEUPDATER_VERSION_H
#define PROJECT_NAME "@PROJECT_NAME@"
#define VERSION_GIT_COMMIT "@VERSION_GIT_HASH@"
#define VERSION_GIT_BRANCH "@VERSION_GIT_BRANCH@"
#define CMAKE_RUNTIME_OUTPUT_DIRECTORY "@CMAKE_RUNTIME_OUTPUT_DIRECTORY@"
#define LIBRARY_OUTPUT_PATH "@LIBRARY_OUTPUT_PATH@"
#endif // FILEUPDATER_VERSION_H

View File

@@ -10,22 +10,6 @@ if (MSVC)
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif()
execute_process(
COMMAND git rev-parse --short HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE VERSION_GIT_HASH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
execute_process(
COMMAND git rev-parse --abbrev-ref HEAD
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE VERSION_GIT_BRANCH
OUTPUT_STRIP_TRAILING_WHITESPACE
)
configure_file(fileUpdaterVer.h.in fileUpdaterVer.h)
message(STATUS "Version file config to: ${CMAKE_CURRENT_BINARY_DIR}")
include_directories(${CMAKE_CURRENT_BINARY_DIR})
find_package(fmt REQUIRED)
find_package(tinyxml2 REQUIRED)
find_package(CLI11 REQUIRED)

View File

@@ -1,7 +0,0 @@
#ifndef FILEUPDATER_VERSION_H
#define FILEUPDATER_VERSION_H
#define VERSION_GIT_COMMIT "@VERSION_GIT_HASH@"
#define VERSION_GIT_BRANCH "@VERSION_GIT_BRANCH@"
#endif // FILEUPDATER_VERSION_H

View File

@@ -3,7 +3,7 @@
#include <boost/algorithm/string.hpp>
#include <boost/nowide/iostream.hpp>
#include <chrono>
#include <fileUpdaterVer.h>
#include <Tools.h>
#include <iomanip>
#include <iostream>
#include <spdlog/sinks/rotating_file_sink.h>

28
script/AutoPack.bat Normal file
View File

@@ -0,0 +1,28 @@
@echo off
echo Config CMake...
cmake -B..\build -S..\ -DCMAKE_BUILD_TYPE=Release -DCMAKE_TOOLCHAIN_FILE="%VCPKG_DIR%\scripts\buildsystems\vcpkg.cmake" -A x64
if errorlevel 1 (
echo CMake Failed.
pause
exit /b 1
)
echo Building...
cmake --build ..\build --config Release
if errorlevel 1 (
echo Build Failed.
pause
exit /b 1
)
echo Packing...
python package.py ..\build\Tools.h
if errorlevel 1 (
echo Pack Failed.
pause
exit /b 1
)
echo Done.
pause

292
script/package.py Normal file
View File

@@ -0,0 +1,292 @@
#!/usr/bin/env python3
"""
解析版本头文件并打包二进制文件的脚本
用法: python package_binaries.py <version_header_file>
"""
import os
import sys
import re
import zipfile
import tarfile
import platform
def parse_version_header(file_path):
"""
解析版本头文件,提取路径信息
返回字典包含解析结果
"""
if not os.path.exists(file_path):
raise FileNotFoundError(f"文件不存在: {file_path}")
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# 使用正则表达式提取信息
patterns = {
'PROJECT_NAME': r'#define\s+PROJECT_NAME\s+"([^"]+)"',
'VERSION_GIT_COMMIT': r'#define\s+VERSION_GIT_COMMIT\s+"([^"]+)"',
'VERSION_GIT_BRANCH': r'#define\s+VERSION_GIT_BRANCH\s+"([^"]+)"',
'CMAKE_RUNTIME_OUTPUT_DIRECTORY': r'#define\s+CMAKE_RUNTIME_OUTPUT_DIRECTORY\s+"([^"]+)"',
'LIBRARY_OUTPUT_PATH': r'#define\s+LIBRARY_OUTPUT_PATH\s+"([^"]+)"',
}
result = {}
for key, pattern in patterns.items():
match = re.search(pattern, content)
if match:
result[key] = match.group(1)
else:
# 尝试无引号的情况
pattern_no_quotes = pattern.replace(r'"([^"]+)"', r'(\S+)')
match = re.search(pattern_no_quotes, content)
if match:
result[key] = match.group(1)
else:
print(f"警告: 未找到 {key} 定义")
result[key] = ""
# 验证必要字段
required_fields = ['PROJECT_NAME', 'VERSION_GIT_COMMIT', 'VERSION_GIT_BRANCH']
for field in required_fields:
if not result.get(field):
raise ValueError(f"缺少必要字段: {field}")
return result
def normalize_path(path_str):
"""标准化路径,处理Windows/Unix路径差异"""
if not path_str:
return ""
# 替换反斜杠为正斜杠
path_str = path_str.replace('\\', '/')
# 移除可能的尾部斜杠
path_str = path_str.rstrip('/')
return path_str
def collect_binary_files(runtime_dir, library_dir):
"""
收集指定目录下的二进制文件
返回文件路径列表
"""
binary_files = []
dirs_to_search = []
if runtime_dir and os.path.exists(runtime_dir):
dirs_to_search.append(runtime_dir)
print(f"搜索运行时目录: {runtime_dir}")
if library_dir and os.path.exists(library_dir):
dirs_to_search.append(library_dir)
print(f"搜索库目录: {library_dir}")
# 支持的二进制文件扩展名
binary_extensions = {
'windows': ['.exe', '.dll', '.pdb', '.lib'],
'linux': ['', '.so', '.so.*', '.a'],
'darwin': ['', '.dylib', '.a', '.bundle']
}
current_os = platform.system().lower()
if 'windows' in current_os:
extensions = binary_extensions['windows']
elif 'linux' in current_os:
extensions = binary_extensions['linux']
elif 'darwin' in current_os:
extensions = binary_extensions['darwin']
else:
extensions = binary_extensions['linux'] # 默认
for search_dir in dirs_to_search:
if not os.path.exists(search_dir):
print(f"警告: 目录不存在: {search_dir}")
continue
for root, dirs, files in os.walk(search_dir):
for file in files:
file_path = os.path.join(root, file)
# 检查文件扩展名
should_include = False
for ext in extensions:
if ext.endswith('*'):
# 通配符匹配
if file.endswith(ext.rstrip('*')):
should_include = True
break
elif ext == '':
# 无扩展名文件(Linux可执行文件)
if not os.path.splitext(file)[1]:
should_include = True
break
else:
# 普通扩展名匹配
if file.lower().endswith(ext.lower()):
should_include = True
break
if should_include:
binary_files.append(file_path)
print(f" 找到: {os.path.relpath(file_path, search_dir)}")
return binary_files
def create_zip_package(files, output_filename, base_dirs):
"""
创建ZIP压缩包
"""
print(f"创建ZIP包: {output_filename}")
with zipfile.ZipFile(output_filename, 'w', zipfile.ZIP_DEFLATED) as zipf:
for file_path in files:
# 确定在ZIP中的相对路径
arcname = None
# 尝试找到最合适的基目录
for base_dir in base_dirs:
if base_dir and file_path.startswith(base_dir):
# 使用相对于基目录的路径
rel_path = os.path.relpath(file_path, base_dir)
# 保持目录结构
arcname = rel_path
break
# 如果没有找到合适的基目录,只使用文件名
if not arcname:
arcname = os.path.basename(file_path)
# 确保路径使用正斜杠
arcname = arcname.replace('\\', '/')
zipf.write(file_path, arcname)
print(f" 添加: {arcname}")
print(f"ZIP包创建完成: {output_filename}")
print(f"包含文件数: {len(files)}")
def create_tar_gz_package(files, output_filename, base_dirs):
"""
创建tar.gz压缩包
"""
print(f"创建tar.gz包: {output_filename}")
with tarfile.open(output_filename, "w:gz") as tar:
for file_path in files:
# 确定在tar中的相对路径
arcname = None
# 尝试找到最合适的基目录
for base_dir in base_dirs:
if base_dir and file_path.startswith(base_dir):
# 使用相对于基目录的路径
rel_path = os.path.relpath(file_path, base_dir)
# 保持目录结构
arcname = rel_path
break
# 如果没有找到合适的基目录,只使用文件名
if not arcname:
arcname = os.path.basename(file_path)
tar.add(file_path, arcname=arcname, recursive=False)
print(f" 添加: {arcname}")
print(f"tar.gz包创建完成: {output_filename}")
print(f"包含文件数: {len(files)}")
def main():
"""主函数"""
if len(sys.argv) != 2:
print("用法: python package_binaries.py <version_header_file>")
print("示例: python package_binaries.py Tools.h")
sys.exit(1)
header_file = sys.argv[1]
try:
# 1. 解析版本头文件
print(f"解析文件: {header_file}")
info = parse_version_header(header_file)
project_name = info['PROJECT_NAME']
git_commit = info['VERSION_GIT_COMMIT']
git_branch = info['VERSION_GIT_BRANCH']
runtime_dir = normalize_path(info.get('CMAKE_RUNTIME_OUTPUT_DIRECTORY', ''))
library_dir = normalize_path(info.get('LIBRARY_OUTPUT_PATH', ''))
print(f"项目: {project_name}")
print(f"分支: {git_branch}")
print(f"提交: {git_commit}")
print(f"运行时目录: {runtime_dir}")
print(f"库目录: {library_dir}")
# 2. 收集二进制文件
print("\n收集二进制文件...")
binary_files = collect_binary_files(runtime_dir, library_dir)
if not binary_files:
print("错误: 未找到任何二进制文件")
print(f"请检查以下目录:")
if runtime_dir:
print(f" - {runtime_dir}")
if library_dir:
print(f" - {library_dir}")
sys.exit(1)
print(f"找到 {len(binary_files)} 个二进制文件")
# 3. 创建输出文件名
# 清理分支名(替换特殊字符)
safe_branch = re.sub(r'[\\/*?:"<>|]', "_", git_branch)
output_basename = f"{project_name}-{safe_branch}-{git_commit}"
# 4. 根据操作系统选择压缩格式
current_os = platform.system().lower()
# 确定要搜索的基目录(用于保持相对路径)
base_dirs = []
if runtime_dir:
base_dirs.append(runtime_dir)
if library_dir:
base_dirs.append(library_dir)
if 'windows' in current_os:
output_file = f"{output_basename}.zip"
print(f"\n在Windows系统,创建ZIP包...")
create_zip_package(binary_files, output_file, base_dirs)
else:
output_file = f"{output_basename}.tar.gz"
print(f"\n{current_os.capitalize()}系统,创建tar.gz包...")
create_tar_gz_package(binary_files, output_file, base_dirs)
# 5. 输出结果
file_size = os.path.getsize(output_file) / (1024 * 1024) # MB
print(f"\n✓ 打包完成!")
print(f"输出文件: {output_file}")
print(f"文件大小: {file_size:.2f} MB")
print(f"包含文件: {len(binary_files)}")
# 显示文件列表
print("\n文件列表:")
for i, file_path in enumerate(binary_files, 1):
# 显示相对于工作目录的路径
rel_path = os.path.relpath(file_path)
print(f" {i:3d}. {rel_path}")
except FileNotFoundError as e:
print(f"错误: {e}", file=sys.stderr)
sys.exit(1)
except ValueError as e:
print(f"错误: {e}", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"未知错误: {e}", file=sys.stderr)
import traceback
traceback.print_exc()
sys.exit(1)
if __name__ == "__main__":
main()