如何给中间件和可执行程序打上GIT版本和编译时间

2020-11-12 14:30:30 浏览数 (1)

问题背景:

平时开发很多的C/C 后台服务或者中间件,这些成果物以可执行的二进制程序或者以动态库、静态库的形式部署在线上。一旦将该服务上线,出问题后一般都需要我们确定该程序的版本分支和版本号,下面介绍一种简单方法将程序的编译信息硬编译到二进制成果物中。


解决目标:

给成果物符号文件中加上git提交版本号和编译日期,允许通过strings或者nm命令查询该成果物的符号文件,然后通过grep过滤编译信息。


解决思路:

1. 通过shell脚本获取代码的提交分支git信息,获取系统当时编译日期和时间;

2. 能够将1步骤上获取到的编译信息用一个模板文件version.h文件的宏进行定义;

3. 代码入口处include该头文件,同时将该宏赋值给const char*字符常量指针;

4. makefile编译之前进行123步骤,将获取到的编译信息编译到成果物的符号文件中;

5. 线上出问题后,需要确定成果物的编译信息时,通过strings和grep命令组合查询即可。


具体实现:

1. 获取编译信息compile_info.sh的shell脚本位于Build文件夹下面:

先看下我本地程序目录结构,大致如下:

compile_info.sh文件内容如下:

代码解释:

第1行:说明这是个shell脚本

第2行:这就是我们要生成的文件,如果以前的老文件存在,则强制删除毕竟我们需要这次编译生成最细的编译信息;

第3行:获取当前编译时间并格式化;

第5行:运行 git 命令。git rev-list HEAD 获取推送到服务器内容的提交列表,然后使用管道 | 将其结果发送给 sort 命令进行排序,之后使用 > 作输出重定向,生成 config.git-hash 文件;

第6行:调用一个 shell 命令:使用 wc 计算 config.git-hash 的行数,然后使用 awk 将其输出到一个变量 LOCALVER 中;

第8行到第20行:如果 LOCALVER > 1 —— 注意有 > 的转义;并且,在变量赋值时无需 —— 那么使用“git rev-list origin/master | sort | join config.git-hash – | wc -l | awk ‘{print 1}’”对 VER 进行赋值。这一段命令我们前面已经解释过,这里不解释。如果 VER != LOCALVER,则将 VER 与 LOCALVER 拼接在一起。然后我们检查 git status 是不是 modified,如果是的话则在后面添加一个 M。然后,我们使用 cut 命令取前七位。最后,我们将这个值赋GIT_VERSION。注意,我们在 VER 前面增加了一个 r,当然你也可以不加,根据自己的需要;第21行到第24行,如果 LOCALVER <= 1,则直接给 GIT_VERSION 和 VER 初始值;

第27行,删除 config.git-hash 文件;


2. 生成头文件:

第28行:使用 cat 命令打开模板文件,利用管道将其传递给 sed(一个无需打开文件即可编辑的编辑)发给 sed 的命令是“s/FULL_VERSION/FULL_VERSION/g”,s 代表替换,s/AAA/BBB/ 表示将 AAA 用 BBB 替换,g 表示全局。注意,这里的 AAA 是正则表达式,因此,我们在查找文件中的 FULL_VERSION 的时候,需要将 转义。而后面的

其中我们通过该脚本的执行,已经将git提交前八位版本号和编译时间已经用宏VERSION_NUMBER进行了定义,后面只需要在代码包含该头文件和使用该宏即可,即可以把其打印到日志里也可以硬编译到二进制符号文件中。


3. 代码中获取头文件中的宏并赋值给const char*常量:


4. 我们可以在后面日志中打印该符号常量,这样当出现问题时,查看日志即可获得当时的编译信息;


5. 编译出来的成果物中查询过滤:

由于赋值给字符常量指针,我们可以在成果物的符号文件中用命令行查找该宏的信息:

strings 成果物名称|grep "成果物前缀_version"

如果你还要好的方法,可以分享出来哈。

0 人点赞