通过cmake获取版本信息的方式

execute_process(
COMMAND git rev-parse --short=8 HEAD
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
OUTPUT_VARIABLE _GIT_COMMIT
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DGIT_COMMIT=\"${_GIT_COMMIT}\")

execute_process(
COMMAND date +%y%m%d.%H%M
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
OUTPUT_VARIABLE _COMPLITE_TIME
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DCOMPLITE_TIME=\"${_COMPLITE_TIME}\")

execute_process(
COMMAND cat data/config/meta.json
COMMAND grep sdk_name
COMMAND awk -F "\"" "{print $4}"
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
OUTPUT_VARIABLE _SDK_NAME
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DPROJECT_ID=\"${_SDK_NAME}\")

execute_process(
COMMAND cat data/config/meta.json
COMMAND grep sdk_version
COMMAND awk -F "\"" "{print $4}"
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
OUTPUT_VARIABLE _SDK_VERSION
ERROR_QUIET
OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DBASE_VERSION=\"${_SDK_VERSION}\")
message(STATUS "PROJECT_ID:${_SDK_NAME}, SDK_VERSION:${_SDK_VERSION}, GIT_COMMIT: ${_GIT_COMMIT}, COMPLITE_TIME: ${_COMPLITE_TIME}")

这段代码是CMake脚本,用于在构建过程中获取一些信息并设置为预处理器定义,以便在C/C++代码中使用。主要包括:Git提交哈希、编译时间、项目ID(SDK名称)和基础版本(SDK版本)。下面逐段解释:

 

### 1. 获取Git提交哈希

```cmake

execute_process(

COMMAND git rev-parse --short=8 HEAD

WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}

OUTPUT_VARIABLE _GIT_COMMIT

ERROR_QUIET

OUTPUT_STRIP_TRAILING_WHITESPACE

)

add_definitions(-DGIT_COMMIT=\"${_GIT_COMMIT}\")

```

- **作用**:执行Git命令获取当前仓库的最近一次提交的哈希值的前8个字符。

- `COMMAND git rev-parse --short=8 HEAD`:获取当前HEAD的8位短哈希。

- `WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}`:指定命令执行的工作目录为当前CMake文件所在目录。

- `OUTPUT_VARIABLE _GIT_COMMIT`:将命令的标准输出保存到变量`_GIT_COMMIT`中。

- `ERROR_QUIET`:忽略错误输出(即不显示错误信息)。

- `OUTPUT_STRIP_TRAILING_WHITESPACE`:删除输出末尾的空白字符(如换行符)。

- 然后使用`add_definitions`添加一个预处理器定义`GIT_COMMIT`,其值为获取的哈希字符串(用引号括起来)。

 

### 2. 获取编译时间

```cmake

execute_process(

COMMAND date +%y%m%d.%H%M

WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}

OUTPUT_VARIABLE _COMPLITE_TIME

ERROR_QUIET

OUTPUT_STRIP_TRAILING_WHITESPACE

)

add_definitions(-DCOMPLITE_TIME=\"${_COMPLITE_TIME}\")

```

- **作用**:执行系统命令`date`获取当前时间,格式为`年月日.时分`(例如:250611.1430表示2025年6月11日14点30分)。

- 注意:这里变量名`_COMPLITE_TIME`可能是拼写错误,应为`_COMPILE_TIME`(编译时间),但代码中保持一致即可。

- 同样,将获取的时间字符串定义为预处理器宏`COMPLITE_TIME`。

 

### 3. 获取项目ID(SDK名称)

```cmake

execute_process(

COMMAND cat data/config/meta.json

COMMAND grep sdk_name

COMMAND awk -F "\"" "{print $4}"

WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}

OUTPUT_VARIABLE _SDK_NAME

ERROR_QUIET

OUTPUT_STRIP_TRAILING_WHITESPACE

)

add_definitions(-DPROJECT_ID=\"${_SDK_NAME}\")

```

- **作用**:从`data/config/meta.json`文件中提取`sdk_name`字段的值。

- 使用管道操作:

1. `cat data/config/meta.json`:读取文件内容。

2. `grep sdk_name`:查找包含`sdk_name`的行。

3. `awk -F "\"" "{print $4}"`:以双引号作为字段分隔符,并打印第4个字段(因为JSON格式通常是`"key": "value"`,所以值在第4个字段)。

- 将提取的值存入变量`_SDK_NAME`,并定义为预处理器宏`PROJECT_ID`。

 

### 4. 获取SDK版本

```cmake

execute_process(

COMMAND cat data/config/meta.json

COMMAND grep sdk_version

COMMAND awk -F "\"" "{print $4}"

WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}

OUTPUT_VARIABLE _SDK_VERSION

ERROR_QUIET

OUTPUT_STRIP_TRAILING_WHITESPACE

)

add_definitions(-DBASE_VERSION=\"${_SDK_VERSION}\")

```

- **作用**:与上面类似,从同一文件中提取`sdk_version`字段的值。

- 同样使用`cat`、`grep`和`awk`命令提取版本字符串。

- 将提取的值存入变量`_SDK_VERSION`,并定义为预处理器宏`BASE_VERSION`。

 

### 5. 打印信息

```cmake

message(STATUS "PROJECT_ID:${_SDK_NAME}, SDK_VERSION:${_SDK_VERSION}, GIT_COMMIT: ${_GIT_COMMIT}, COMPLITE_TIME: ${_COMPLITE_TIME}")

```

- 在CMake配置过程中打印状态信息,显示获取到的项目ID、SDK版本、Git提交哈希和编译时间。

 

### 总结

这段脚本的目的是在构建时动态获取版本控制信息、构建时间和项目元数据,并将它们作为宏定义传递给编译器,这样在C/C++源代码中就可以使用这些宏来记录版本信息。例如,可以在软件中显示版本号和构建时间,便于追踪和调试。

 

### 注意点:

1. **依赖外部命令**:需要系统中有`git`、`date`、`cat`、`grep`和`awk`命令,且在CMake运行时可用。

2. **文件路径**:`meta.json`文件位于`data/config/`目录下,且相对于`${CMAKE_CURRENT_LIST_DIR}`存在。

3. **错误静默**:使用`ERROR_QUIET`会隐藏可能的错误(如文件不存在或命令不存在),在调试时可能需要去掉该选项以查看错误。

4. **拼写错误**:`_COMPLITE_TIME` 可能是 `_COMPILE_TIME` 的拼写错误,但代码中保持一致即可。

5. **跨平台问题**:`date`命令和管道操作在Unix-like系统(如Linux、macOS)上可用,但在Windows上可能不兼容(除非使用Cygwin/MSYS或Windows Subsystem for Linux)。

 

如果需要跨平台,可能需要使用CMake内置命令(如`string(TIMESTAMP ...)`)或编写更复杂的脚本来替代部分操作。

这段 CMake 脚本用于在构建过程中动态获取版本和构建信息,并将其定义为 C/C++ 预处理器宏。以下是逐部分解释:

1. 获取 Git 提交哈希

execute_process(
  COMMAND git rev-parse --short=8 HEAD
  WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
  OUTPUT_VARIABLE _GIT_COMMIT
  ERROR_QUIET
  OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DGIT_COMMIT=\"${_GIT_COMMIT}\")
  • 作用:获取当前 Git 仓库的 8 位短提交哈希

  • 命令:git rev-parse --short=8 HEAD

  • 输出处理:保存到变量 _GIT_COMMIT,去除末尾空格

  • 结果:添加编译器定义 -DGIT_COMMIT="a1b2c3d4"

2. 获取构建时间

execute_process(
  COMMAND date +%y%m%d.%H%M
  WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
  OUTPUT_VARIABLE _COMPLITE_TIME
  ERROR_QUIET
  OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DCOMPLITE_TIME=\"${_COMPLITE_TIME}\")
  • 作用:生成格式为 年月日.时分 的时间戳 (如 250611.1430)

  • 命令:date +%y%m%d.%H%M

  • 注意:变量名 _COMPLITE_TIME 可能是拼写错误 (应为 COMPILE)

  • 结果:添加编译器定义 -DCOMPLITE_TIME="250611.1430"

3. 获取项目 ID (SDK 名称)

execute_process(
  COMMAND cat data/config/meta.json
  COMMAND grep sdk_name
  COMMAND awk -F "\"" "{print $4}"
  WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
  OUTPUT_VARIABLE _SDK_NAME
  ERROR_QUIET
  OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DPROJECT_ID=\"${_SDK_NAME}\")
  • 作用:从 JSON 文件中提取 SDK 名称

  • 命令链:

    1. cat 读取文件

    2. grep 过滤包含 sdk_name 的行

    3. awk 以双引号为分隔符提取第 4 个字段 (值)

  • 示例输入:"sdk_name": "my_sdk"

  • 结果:添加编译器定义 -DPROJECT_ID="my_sdk"

4. 获取 SDK 版本

execute_process(
  COMMAND cat data/config/meta.json
  COMMAND grep sdk_version
  COMMAND awk -F "\"" "{print $4}"
  WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
  OUTPUT_VARIABLE _SDK_VERSION
  ERROR_QUIET
  OUTPUT_STRIP_TRAILING_WHITESPACE
)
add_definitions(-DBASE_VERSION=\"${_SDK_VERSION}\")
  • 作用:从 JSON 文件中提取 SDK 版本号

  • 流程:与获取项目 ID 相同,但查找 sdk_version 字段

  • 示例输入:"sdk_version": "1.2.3"

  • 结果:添加编译器定义 -DBASE_VERSION="1.2.3"

5. 打印汇总信息

message(STATUS "PROJECT_ID:${_SDK_NAME}, SDK_VERSION:${_SDK_VERSION}, GIT_COMMIT: ${_GIT_COMMIT}, COMPLITE_TIME: ${_COMPLITE_TIME}")
  • 输出示例:

    PROJECT_ID:my_sdk, SDK_VERSION:1.2.3, GIT_COMMIT: a1b2c3d4, COMPLITE_TIME: 250611.1430

整体作用

在编译时注入以下信息到程序中:

  1. 版本标识:通过 SDK 名称和版本号

  2. 精确构建信息:通过 Git 提交哈希

  3. 构建时间:精确到分钟的时间戳

使用场景

在 C/C++ 代码中可通过预定义宏访问:

printf("Build: %s/%s\n", PROJECT_ID, BASE_VERSION);
printf("Commit: %s\n", GIT_COMMIT);
printf("Time: %s\n", COMPLITE_TIME);
char const* GetVersionName(void) {
    static char ver[64];
    snprintf(ver, sizeof(ver), "%s_%s_%s_%s_%s", PROJECT_ID, MODULE_ID, BASE_VERSION, GIT_COMMIT,
             COMPLITE_TIME);
    return ver;
}

注意事项

  1. 跨平台问题:date/grep/awk 是 Unix 工具,Windows 需配置环境

  2. 依赖文件:要求 data/config/meta.json 存在且包含指定字段

  3. 错误静默:ERROR_QUIET 会隐藏可能的错误

  4. 拼写问题:COMPLITE_TIME 应为 COMPILE_TIME

  5. 构建一致性:这些值在每次构建时动态生成,确保版本信息实时更新

这种模式常用于生成包含精确构建信息的版本标识,特别适用于需要追踪具体构建版本的应用场景(如 SDK 分发、故障排查等)。

posted @ 2025-06-11 17:31  白伟碧一些小心得  阅读(141)  评论(0)    收藏  举报