Compare commits
7 Commits
55b8574f8a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 5ecb188a04 | |||
| 8e7c1408f7 | |||
| 5b18af4279 | |||
| 7a4036490c | |||
| c72b16e7fe | |||
| 80edf30ce3 | |||
| 3d3513e056 |
6
.gitmodules
vendored
Normal file
6
.gitmodules
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
[submodule "zoost"]
|
||||||
|
path = zoost
|
||||||
|
url = https://www.sinxmiao.cn/taynpg/zoost
|
||||||
|
[submodule "cxxLibrary"]
|
||||||
|
path = cxxLibrary
|
||||||
|
url = https://www.sinxmiao.cn/taynpg/cxxLibrary
|
||||||
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@@ -1,9 +1,9 @@
|
|||||||
{
|
{
|
||||||
"files.autoSave": "onFocusChange",
|
"files.autoSave": "onFocusChange",
|
||||||
"editor.fontSize": 14,
|
"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",
|
"editor.wordWrap": "on",
|
||||||
"terminal.integrated.fontFamily": "'Maple Mono NL NF CN Light'",
|
"terminal.integrated.fontFamily": "'Source Code Pro'",
|
||||||
"cmake.configureOnOpen": true,
|
"cmake.configureOnOpen": true,
|
||||||
//"C_Cpp.intelliSenseEngine": "disabled",
|
//"C_Cpp.intelliSenseEngine": "disabled",
|
||||||
"cmake.debugConfig": {
|
"cmake.debugConfig": {
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"-Wno-dev"
|
"-Wno-dev"
|
||||||
],
|
],
|
||||||
"cmake.configureSettings": {
|
"cmake.configureSettings": {
|
||||||
"CMAKE_TOOLCHAIN_FILE": "${env:VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake"
|
//"CMAKE_TOOLCHAIN_FILE": "${env:VCPKG_DIR}/scripts/buildsystems/vcpkg.cmake"
|
||||||
},
|
},
|
||||||
"cmake.options.statusBarVisibility": "visible",
|
"cmake.options.statusBarVisibility": "visible",
|
||||||
"cmake.generator": "Ninja",
|
"cmake.generator": "Ninja",
|
||||||
|
|||||||
@@ -11,5 +11,23 @@ if (MSVC)
|
|||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
endif()
|
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(cxxLibrary)
|
||||||
add_subdirectory(strReplace)
|
add_subdirectory(strReplace)
|
||||||
add_subdirectory(fileUpdater)
|
add_subdirectory(fileUpdater)
|
||||||
366
LibUse.md
Normal file
366
LibUse.md
Normal file
@@ -0,0 +1,366 @@
|
|||||||
|
# Spdlog
|
||||||
|
|
||||||
|
## sink
|
||||||
|
|
||||||
|
spdlog定义了几种sinks用于不同场景(也可自定义)下的日志输出,sink中主要包含:
|
||||||
|
|
||||||
|
- `set_pattern(const std::string&)`:设置日志输出的内容格式。
|
||||||
|
- `set_level(level_enum)`: 设置日志输出的最低等级。
|
||||||
|
- `log(log_msg)`:由logger自动调用,外部不会主动调用。
|
||||||
|
|
||||||
|
## logger
|
||||||
|
|
||||||
|
一个logger对象中存储有多个sink,当调用*logger*的日志输出函数时,*logger*会调用自身存储的所有*sink*对象的log(log_msg) 函数进行输出。logger中主要包括:
|
||||||
|
|
||||||
|
- `set_pattern(const std::string&)`:设置logger包含的所有sink的日志输出内容格式。
|
||||||
|
- `set_level(level_enum)`:设置logger日志输出最低等级,如果logger包含的sink没有设置日志等级的话,则会为其设置日志等级。
|
||||||
|
- `log(level_enum level,log_msg content)`:按照level等级进行输出content,logger其中日志输出最低等级小于或等于level的sink会进行执行输出操作。
|
||||||
|
- `trace(content,arg1,arg2…)`:按照trace等级进行输出,输出内容由content与后面的参数格式化而成。同类的函数还包括:debug/info/warn…。
|
||||||
|
|
||||||
|
## 输出格式pattern
|
||||||
|
|
||||||
|
通过`set_pattern`可设定日志格式,如`set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l](%@): %v");`
|
||||||
|
|
||||||
|
输出标记flag:
|
||||||
|
|
||||||
|
| flag | meaning | example |
|
||||||
|
| ----- | ------------------------------------------------------------ | ---------------------------------------------------------- |
|
||||||
|
| %v | 日志内容 | “my log test content” |
|
||||||
|
| %t | 线程ID | “123” |
|
||||||
|
| %P | 进程ID | “234” |
|
||||||
|
| %n | 记录器Logger名 | “basicLogger” |
|
||||||
|
| %l | 日志级别 | “debug”, “info”, etc |
|
||||||
|
| %L | 日志级别简称 | “D”, “I”, etc |
|
||||||
|
| %a | 星期几(简称) | “Thu” |
|
||||||
|
| %A | 星期几 | “Thursday” |
|
||||||
|
| %b | 月份简称 | “Aug” |
|
||||||
|
| %B | 月份 | “August” |
|
||||||
|
| %c | 日期时间 | “Thu Aug 23 15:35:46 2014” |
|
||||||
|
| %C | 年(两位) | “14” |
|
||||||
|
| %Y | 年 | “2014” |
|
||||||
|
| %D %x | 日期简写 | “08/23/14” |
|
||||||
|
| %m | 月份(数字) | “11” |
|
||||||
|
| %d | 日(数组) | “29” |
|
||||||
|
| %H | 小时(24制) | “23” |
|
||||||
|
| %I | 小时(12制) | “11” |
|
||||||
|
| %M | 分钟 | “59” |
|
||||||
|
| %S | 秒 | “58” |
|
||||||
|
| %e | 毫秒 | “678” |
|
||||||
|
| %f | 微秒 | “056789” |
|
||||||
|
| %F | 纳秒 | “256789123” |
|
||||||
|
| %p | AM/PM | “AM” |
|
||||||
|
| %r | 时间(12制) | “02:55:02 pm” |
|
||||||
|
| %R | 时分(24制) | “23:55” |
|
||||||
|
| %T %X | 时间(24制) | “23:55:59” |
|
||||||
|
| %z | 时区(偏移) | “+02:00” |
|
||||||
|
| %E | epoch(秒) | “1528834770” |
|
||||||
|
| %% | 百分号 | “%” |
|
||||||
|
| %+ | 默认格式 | “[2014-10-31 23:46:59.678] [mylogger] [info] Some message” |
|
||||||
|
| %^ | start color range (can be used only once) | “[mylogger] [info(green)] Some message” |
|
||||||
|
| %$ | end color range (for example %^[+++]%$ %v) (can be used only once) | [+++] Some message |
|
||||||
|
| %@ | 文件名与行数 | my_file.cpp:123 |
|
||||||
|
| %s | 文件名 | my_file.cpp |
|
||||||
|
| %g | 文件名(含路径) | /some/dir/my_file.cpp |
|
||||||
|
| %# | 行数 | 123 |
|
||||||
|
| %! | 函数名 | my_func |
|
||||||
|
| %o | 相对上一条记录的时间间隔(毫秒) | 456 |
|
||||||
|
| %i | 相对上一条记录的时间间隔(微秒) | 456 |
|
||||||
|
| %u | 相对上一条记录的时间间隔(纳秒) | 11456 |
|
||||||
|
| %O | 相对上一条记录的时间间隔(秒) | 4 |
|
||||||
|
|
||||||
|
日志输出中要携带文件名、行数或函数名时,必须使用`SPDLOG_LOGGER_*`宏,且要激活对应的级别(哪些级别以上的日志会被记录):
|
||||||
|
|
||||||
|
```text
|
||||||
|
// 记录INFO及以上级别日志
|
||||||
|
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
|
SPDLOG_LOGGER_INFO(myLogger, "Support for floats {:03.2f}", 1.23456);
|
||||||
|
SPDLOG_LOGGER_WARN(myLogger, "Easy padding in numbers like {:08d}", 12);
|
||||||
|
```
|
||||||
|
|
||||||
|
### 对齐方式
|
||||||
|
|
||||||
|
每个flag都可携带对齐方式(最多支持64字符),
|
||||||
|
|
||||||
|
| align | meaning | example | result |
|
||||||
|
| --------------- | ------- | ------- | -------- |
|
||||||
|
| %<width><flag> | 右对齐 | %8l | " info" |
|
||||||
|
| %-<width><flag> | 左对齐 | %-8l | "info " |
|
||||||
|
| %=<width><flag> | 居中 | %=8l | " info " |
|
||||||
|
|
||||||
|
### 截断
|
||||||
|
|
||||||
|
通过!可设定对应输出的最大长度:
|
||||||
|
|
||||||
|
| align | meaning | example | result |
|
||||||
|
| ---------------- | ------------ | ------- | ------ |
|
||||||
|
| %<width>!<flag> | 右对齐且截断 | %3!l | “inf” |
|
||||||
|
| %-<width>!<flag> | 左对齐且截断 | %-2!l | “in” |
|
||||||
|
| %=<width>!<flag> | 居中且截断 | %=1!l | “i” |
|
||||||
|
|
||||||
|
## 字符串格式化fmt
|
||||||
|
|
||||||
|
spdlog中字符串格式化使用fmt([https://github.com/fmtlib/fmt](https://link.zhihu.com/?target=https%3A//github.com/fmtlib/fmt))库。
|
||||||
|
|
||||||
|
格式化方式:`{ [arg_id] [: (format_spec | chrono_format_spec)] }`
|
||||||
|
|
||||||
|
- arg_id:参数标识;
|
||||||
|
- 忽略(为空时),依次对应每一个参数;
|
||||||
|
- 索引(数字,从0开始),引用第几个索引;
|
||||||
|
- 名称,命名参数;
|
||||||
|
- format_spec:参数格式化方式(类型、对齐、填充等);
|
||||||
|
|
||||||
|
### Format Specification
|
||||||
|
|
||||||
|
格式化符说明:
|
||||||
|
|
||||||
|
```text
|
||||||
|
format_spec ::= [[fill]align][sign]["#"]["0"][width]["." precision]["L"][type]
|
||||||
|
fill ::= <a character other than '{' or '}'>
|
||||||
|
align ::= "<" | ">" | "^" // 左、右、居中对齐
|
||||||
|
sign ::= "+" | "-" | " "
|
||||||
|
width ::= integer | {[arg_id]} // 宽度:数字或指定的参数
|
||||||
|
precision ::= integer | {[arg_id]} // 精度:数字或指定的参数
|
||||||
|
type ::= "a" | "A" | "b" | "B" | "c" | "d" | "e" | "E" | "f" | "F"
|
||||||
|
| "g" | "G" | "o" | "p" | "s" | "x" | "X"
|
||||||
|
```
|
||||||
|
|
||||||
|
`#`不同的转换下有不同的意义:
|
||||||
|
|
||||||
|
- 整数时,表示前面添加进制前缀,如0x, 0b等;
|
||||||
|
- 浮点数时:总是有小数点(即使没有小数部分);
|
||||||
|
|
||||||
|
`L`只对数字有效,根据本地设置来输出:如,
|
||||||
|
|
||||||
|
```text
|
||||||
|
auto s = fmt::format(std::locale("en_US.UTF-8"), "{:L}", 1234567890);
|
||||||
|
// s == "1,234,567,890"
|
||||||
|
```
|
||||||
|
|
||||||
|
格式化类型:
|
||||||
|
|
||||||
|
格式化类型:
|
||||||
|
|
||||||
|
| type | meaning |
|
||||||
|
| ---- | ---------------------------------------- |
|
||||||
|
| s | 字符串 |
|
||||||
|
| c | 字符 |
|
||||||
|
| b/B | 二进制 |
|
||||||
|
| d | 数字(十进制) |
|
||||||
|
| o | 八进制 |
|
||||||
|
| x/X | 十六进制 |
|
||||||
|
| a/A | 十六进制浮点数(p表示指数) |
|
||||||
|
| e/E | 科学计数 |
|
||||||
|
| f/F | 浮点数(包括NAN,INF),固定小数位数输出 |
|
||||||
|
| g/G | 浮点数输出 |
|
||||||
|
| p | 指针 |
|
||||||
|
|
||||||
|
示例:
|
||||||
|
|
||||||
|
```text
|
||||||
|
fmt::format("{:*^30}", "centered"); // use '*' as a fill char
|
||||||
|
// Result: "***********centered***********"
|
||||||
|
|
||||||
|
fmt::format("{:#04x}", 0);
|
||||||
|
// Result: "0x00"
|
||||||
|
|
||||||
|
fmt::print(
|
||||||
|
"┌{0:─^{2}}┐\n"
|
||||||
|
"│{1: ^{2}}│\n"
|
||||||
|
"└{0:─^{2}}┘\n", "", "Hello, world!", 20);
|
||||||
|
┌────────────────────┐
|
||||||
|
│ Hello, world! │
|
||||||
|
└────────────────────┘
|
||||||
|
```
|
||||||
|
|
||||||
|
## spdlog使用
|
||||||
|
|
||||||
|
spdlog默认日志输出级别是INFO。
|
||||||
|
|
||||||
|
默认情况下,日志是同步模式的,可通过以下方法开启异步模式:
|
||||||
|
|
||||||
|
```text
|
||||||
|
size_t q_size = 4096; //queue size must be power of 2
|
||||||
|
spdlog::set_async_mode(q_size);
|
||||||
|
```
|
||||||
|
|
||||||
|
在异步模式下,日志先存入队列(队列占用的内存 = 设置的队列大小 * slot的大小, 64位系统下slot大小为104字节。),再由工作者线程从队列中取出并输出。当队列满时,会根据设定策略处理:
|
||||||
|
|
||||||
|
- 阻塞新来的日志,直到队列中有剩余空间(默认处理方式);
|
||||||
|
- 丢弃新来的日志,需要如下设定策略:
|
||||||
|
|
||||||
|
```text
|
||||||
|
spdlog::set_async_mode(q_size, spdlog::async_overflow_policy::discard_log_msg);
|
||||||
|
```
|
||||||
|
|
||||||
|
## 异常处理
|
||||||
|
|
||||||
|
当输出日志时发生异常时,spdlog会向std::err 打印一条语句,为了避免输出的异常语句刷屏,打印频率被限制在每分钟一条。可通过set_error_handler来设定异常处理函数:
|
||||||
|
|
||||||
|
```text
|
||||||
|
//can be set globaly or per logger(logger->set_error_handler(..))
|
||||||
|
spdlog::set_error_handler([](const std::string& msg)
|
||||||
|
{
|
||||||
|
std::cerr << "my err handler: " << msg << std::endl;
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## logger
|
||||||
|
|
||||||
|
默认情况下,spdlog的默认logger为输出到stdout:
|
||||||
|
|
||||||
|
```text
|
||||||
|
# ifdef _WIN32
|
||||||
|
auto color_sink = std::make_shared<sinks::wincolor_stdout_sink_mt>();
|
||||||
|
# else
|
||||||
|
auto color_sink = std::make_shared<sinks::ansicolor_stdout_sink_mt>();
|
||||||
|
# endif
|
||||||
|
```
|
||||||
|
|
||||||
|
在使用完logger后,要关闭掉以释放(否则无再建立同名logger)
|
||||||
|
|
||||||
|
```text
|
||||||
|
spdlog::drop_all(); // 关闭所有logger
|
||||||
|
spd::drop("basic_logger"); // 关闭指定logger
|
||||||
|
```
|
||||||
|
|
||||||
|
### 基础用法
|
||||||
|
|
||||||
|
spdlog中使用`{}`(里面可指定格式)作为格式化符
|
||||||
|
|
||||||
|
以下方式把日志输出到默认logger上:
|
||||||
|
|
||||||
|
```text
|
||||||
|
//#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_DEBUG
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
spdlog::info("{:<30}", "left aligned");
|
||||||
|
spdlog::warn("Easy padding in numbers like {:08d}", 12);
|
||||||
|
spdlog::error("Some error message with arg: {}", 1);
|
||||||
|
spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
|
||||||
|
|
||||||
|
spdlog::set_level(spdlog::level::debug); // Set global log level to debug
|
||||||
|
spdlog::debug("This message should be displayed..");
|
||||||
|
|
||||||
|
// change log pattern
|
||||||
|
spdlog::set_pattern("[%H:%M:%S %z] [%n] [%^---%L---%$] [thread %t] %v");
|
||||||
|
|
||||||
|
// Compile time log levels
|
||||||
|
// define SPDLOG_ACTIVE_LEVEL to desired level
|
||||||
|
SPDLOG_TRACE("Some trace message with param {}", 42);
|
||||||
|
SPDLOG_DEBUG("Some debug message");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### stdout日志
|
||||||
|
|
||||||
|
以彩色方式输出到标准输出设备上:
|
||||||
|
|
||||||
|
```text
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "spdlog/sinks/stdout_color_sinks.h"
|
||||||
|
|
||||||
|
void stdout_example()
|
||||||
|
{
|
||||||
|
// create color multi threaded logger
|
||||||
|
auto console = spdlog::stdout_color_mt("console");
|
||||||
|
auto err_logger = spdlog::stderr_color_mt("stderr");
|
||||||
|
spdlog::get("console")->info("loggers can be retrieved from a global registry using the spdlog::get(logger_name)");
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 文件日志
|
||||||
|
|
||||||
|
### 基本文件
|
||||||
|
|
||||||
|
最简单的日志文件:
|
||||||
|
|
||||||
|
```text
|
||||||
|
#include "spdlog/sinks/basic_file_sink.h"
|
||||||
|
void basic_logfile_example()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
auto logger = spdlog::basic_logger_mt("basic_logger", "logs/basic-log.txt");
|
||||||
|
}
|
||||||
|
catch (const spdlog::spdlog_ex &ex)
|
||||||
|
{
|
||||||
|
std::cout << "Log init failed: " << ex.what() << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 循环文件
|
||||||
|
|
||||||
|
日志文件超过指定大小后,自动生成一个新的;并且只保留最多指定数量的日志文件:
|
||||||
|
|
||||||
|
```text
|
||||||
|
#include "spdlog/sinks/rotating_file_sink.h"
|
||||||
|
void rotating_example()
|
||||||
|
{
|
||||||
|
// Create a file rotating logger with 5mb size max and 3 rotated files
|
||||||
|
auto max_size = 1024*1024 * 5;
|
||||||
|
auto max_files = 3;
|
||||||
|
auto logger = spdlog::rotating_logger_mt("some_logger_name", "logs/rotating.txt", max_size, max_files);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 每日文件
|
||||||
|
|
||||||
|
每天指定时间生成一个新的日志文件:
|
||||||
|
|
||||||
|
```text
|
||||||
|
#include "spdlog/sinks/daily_file_sink.h"
|
||||||
|
void daily_example()
|
||||||
|
{
|
||||||
|
// Create a daily logger - a new file is created every day on 2:30am
|
||||||
|
auto logger = spdlog::daily_logger_mt("daily_logger", "logs/daily.txt", 2, 30);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 示例
|
||||||
|
|
||||||
|
设定默认日志记录文件并在不同地方获取使用:
|
||||||
|
|
||||||
|
```text
|
||||||
|
#define SPDLOG_ACTIVE_LEVEL SPDLOG_LEVEL_INFO
|
||||||
|
|
||||||
|
#include "spdlog/spdlog.h"
|
||||||
|
#include "spdlog/sinks/rotating_file_sink.h"
|
||||||
|
|
||||||
|
|
||||||
|
void writeLog(int n) {
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
// 获取logger后输出日志
|
||||||
|
auto myLogger = spdlog::get("baseLogger");
|
||||||
|
myLogger->info("{}: Hello, {}!", i + 1, "World");
|
||||||
|
myLogger->info("Welcome to spdlog!");
|
||||||
|
myLogger->error("Some error message with arg: {}", 1);
|
||||||
|
|
||||||
|
// 带文件名与行号的日志输出
|
||||||
|
SPDLOG_LOGGER_INFO(myLogger, "Support for floats {:03.2f}", 1.23456);
|
||||||
|
SPDLOG_LOGGER_WARN(myLogger, "Easy padding in numbers like {:08d}", 12);
|
||||||
|
|
||||||
|
// 输出到默认日志中
|
||||||
|
spdlog::critical("Support for int: {0:d}; hex: {0:x}; oct: {0:o}; bin: {0:b}", 42);
|
||||||
|
spdlog::error("Some error message with arg: {}", 1);
|
||||||
|
spdlog::warn("Easy padding in numbers like {:08d}", 12);
|
||||||
|
spdlog::info("Support for floats {:03.2f}", 1.23456);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void testSPDLog() {
|
||||||
|
// 设定日志最大100k,且最多保留10个
|
||||||
|
auto myLogger = spdlog::rotating_logger_mt("baseLogger", "logs/basic.log", 1024 * 100, 10);
|
||||||
|
spdlog::set_default_logger(myLogger);
|
||||||
|
myLogger->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l](%@): %v"); // 非通过宏输出的日志%@输出为空
|
||||||
|
myLogger->set_level(spdlog::level::info);
|
||||||
|
|
||||||
|
myLogger->info("Hello, {}!", "World");
|
||||||
|
|
||||||
|
writeLog(10);
|
||||||
|
}
|
||||||
|
```
|
||||||
10
Tools.h.in
Normal file
10
Tools.h.in
Normal 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
|
||||||
1
cxxLibrary
Submodule
1
cxxLibrary
Submodule
Submodule cxxLibrary added at d1b8734ccc
@@ -10,38 +10,8 @@ if (MSVC)
|
|||||||
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
add_definitions(-D_CRT_SECURE_NO_WARNINGS)
|
||||||
endif()
|
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)
|
|
||||||
find_package(spdlog REQUIRED)
|
|
||||||
find_package(Boost REQUIRED COMPONENTS locale filesystem nowide)
|
|
||||||
|
|
||||||
add_executable(fileUpdater main.cpp)
|
add_executable(fileUpdater main.cpp)
|
||||||
target_link_libraries(fileUpdater PRIVATE
|
target_link_libraries(fileUpdater PRIVATE cxxLibrary zoost)
|
||||||
fmt::fmt
|
|
||||||
Boost::locale
|
|
||||||
Boost::filesystem
|
|
||||||
Boost::nowide
|
|
||||||
CLI11::CLI11
|
|
||||||
spdlog::spdlog
|
|
||||||
tinyxml2::tinyxml2
|
|
||||||
)
|
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
install(TARGETS fileUpdater
|
install(TARGETS fileUpdater
|
||||||
|
|||||||
@@ -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
|
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
#include <CLI/CLI.hpp>
|
#include <CLI11.hpp>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/nowide/filesystem.hpp>
|
|
||||||
#include <boost/nowide/iostream.hpp>
|
#include <boost/nowide/iostream.hpp>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <fileUpdaterVer.h>
|
#include <Tools.h>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <spdlog/sinks/rotating_file_sink.h>
|
||||||
#include <spdlog/sinks/stdout_color_sinks.h>
|
#include <spdlog/sinks/stdout_color_sinks.h>
|
||||||
#include <spdlog/spdlog.h>
|
#include <spdlog/spdlog.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tinyxml2.h>
|
#include <tinyxml2.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <zoost.h>
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace fs = boost::filesystem;
|
namespace fs = std::filesystem;
|
||||||
namespace xml = tinyxml2;
|
namespace xml = tinyxml2;
|
||||||
|
|
||||||
// 文件映射结构
|
// 文件映射结构
|
||||||
@@ -52,19 +52,41 @@ private:
|
|||||||
std::vector<FileMapping> mappings;
|
std::vector<FileMapping> mappings;
|
||||||
std::shared_ptr<spdlog::logger> logger;
|
std::shared_ptr<spdlog::logger> logger;
|
||||||
std::string markerDir; // 标记目录名
|
std::string markerDir; // 标记目录名
|
||||||
|
std::string logPath_;
|
||||||
|
std::string logName_{"fileUpdater.log"};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AutoUpdateTool()
|
AutoUpdateTool()
|
||||||
{
|
{
|
||||||
logger = spdlog::stdout_color_mt("AutoUpdate");
|
zoostPath zp;
|
||||||
logger->set_pattern("[%Y-%m-%d %H:%M:%S.%e] [%^%l%$] %v");
|
if (!zp.GetConfigFile("fileUpdater", logName_, logPath_)) {
|
||||||
|
boost::nowide::cerr << "获取日志文件路径失败。" << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (!zoostFs::exists((zp.GetParentPath(logPath_)))) {
|
||||||
|
if (!zp.CreateConfigDir("fileUpdater")) {
|
||||||
|
boost::nowide::cerr << "创建配置目录失败。" << std::endl;
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto file_sink = std::make_shared<spdlog::sinks::rotating_file_sink_mt>(logPath_, 1024 * 1024 * 50, 3);
|
||||||
|
auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
|
||||||
|
file_sink->set_pattern("[%Y-%m-%d %H:%M:%S.%e][%l]: %v");
|
||||||
|
console_sink->set_pattern("[%H:%M:%S.%e] %^[%l] %v%$");
|
||||||
|
|
||||||
|
std::vector<spdlog::sink_ptr> sinks{file_sink, console_sink};
|
||||||
|
logger = std::make_shared<spdlog::logger>(logName_, sinks.begin(), sinks.end());
|
||||||
|
logger->set_level(spdlog::level::debug);
|
||||||
|
spdlog::register_logger(logger);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析命令行参数
|
// 解析命令行参数
|
||||||
bool parseArguments(int argc, char** argv)
|
bool parseArguments(int argc, char** argv)
|
||||||
{
|
{
|
||||||
auto msg = fmt::format("fileUpdater - 文件更新工具 \n\n {} on {} at {} {}", VERSION_GIT_COMMIT, VERSION_GIT_BRANCH,
|
auto notice = "使用特殊参数 default 可生成一个默认配置文件模板。";
|
||||||
__DATE__, __TIME__);
|
auto msg = fmt::format("fileUpdater - 文件更新工具 \n\n {} on {} at {} {}\n{}", VERSION_GIT_COMMIT, VERSION_GIT_BRANCH,
|
||||||
|
__DATE__, __TIME__, notice);
|
||||||
CLI::App app{msg};
|
CLI::App app{msg};
|
||||||
argv = app.ensure_utf8(argv);
|
argv = app.ensure_utf8(argv);
|
||||||
|
|
||||||
@@ -94,6 +116,14 @@ public:
|
|||||||
backupDir = fs::absolute(backupDir);
|
backupDir = fs::absolute(backupDir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string rec;
|
||||||
|
for (int i = 1; i < argc; i++) {
|
||||||
|
rec += argv[i];
|
||||||
|
rec += " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
logger->debug("原始参数: {}", rec);
|
||||||
|
logger->debug("CMD目录: {}", zoostFs::current_path().string());
|
||||||
logger->info("工作目录: {}", workDir.string());
|
logger->info("工作目录: {}", workDir.string());
|
||||||
logger->info("更新目录: {}", updateDir.string());
|
logger->info("更新目录: {}", updateDir.string());
|
||||||
logger->info("备份目录: {}", backupDir.string());
|
logger->info("备份目录: {}", backupDir.string());
|
||||||
@@ -447,11 +477,31 @@ public:
|
|||||||
|
|
||||||
int main(int argc, char** argv)
|
int main(int argc, char** argv)
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
zoostCommon::SetOutputU8();
|
||||||
SetConsoleOutputCP(CP_UTF8);
|
zoostCommon::SetStdLibrayU8();
|
||||||
#endif
|
|
||||||
|
if (argc > 1) {
|
||||||
|
std::string specialStr = argv[1];
|
||||||
|
if (specialStr == "default") {
|
||||||
|
std::string defaultContent =
|
||||||
|
R"(<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<AutoUpdate>
|
||||||
|
<!-- 文件映射配置 -->
|
||||||
|
<FileMapping m="a.txt" n="c/d/a.txt" type="file" ext=""/>
|
||||||
|
<FileMapping m="" n="mm" type="dir" ext="txt|xml"/>
|
||||||
|
</AutoUpdate>)";
|
||||||
|
std::ifstream ifs("fileUpdater.xml");
|
||||||
|
if (!ifs) {
|
||||||
|
std::ofstream ofs("fileUpdater.xml");
|
||||||
|
ofs << defaultContent;
|
||||||
|
ofs.close();
|
||||||
|
}
|
||||||
|
ifs.close();
|
||||||
|
boost::nowide::cout << "已生成默认配置文件: fileUpdater.xml" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
boost::nowide::nowide_filesystem();
|
|
||||||
AutoUpdateTool tool;
|
AutoUpdateTool tool;
|
||||||
|
|
||||||
if (tool.parseArguments(argc, argv)) {
|
if (tool.parseArguments(argc, argv)) {
|
||||||
|
|||||||
28
script/AutoPack.bat
Normal file
28
script/AutoPack.bat
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
echo Config CMake...
|
||||||
|
cmake -B..\build -S..\ -DCMAKE_BUILD_TYPE=Release -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
292
script/package.py
Normal 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()
|
||||||
@@ -2,7 +2,5 @@ cmake_minimum_required(VERSION 3.16)
|
|||||||
|
|
||||||
project(strReplace LANGUAGES CXX)
|
project(strReplace LANGUAGES CXX)
|
||||||
|
|
||||||
find_package(Boost REQUIRED)
|
|
||||||
|
|
||||||
add_executable(strReplace main.cpp)
|
add_executable(strReplace main.cpp)
|
||||||
target_link_libraries(strReplace PRIVATE Boost::headers)
|
target_link_libraries(strReplace PRIVATE cxxLibrary zoost)
|
||||||
1
zoost
Submodule
1
zoost
Submodule
Submodule zoost added at 78c9c4b887
Reference in New Issue
Block a user