10.5 一个显示版本号的Hello World

    在本章的一开始为纪念前面的实践留了一个影,叫作old_practice。现在再次执行git describe看一下现在的版本号。


    $git describe old_practice-3-gc024f34

    也就是说:当前工作区的版本是“留影”后的第三个版本,提交ID是c024f34。

    下面的命令可以在提交日志中显示提交对应的里程碑(Tag)。其中参数—decorate可以在提交ID的旁边显示该提交关联的引用(里程碑或分支)。


    $git log—oneline—decorate-4 c024f34(HEAD,master)README is from welcome.txt. 63992f0 restore file:welcome.txt 7161977 delete trash files.(using:git add-u) 2b31c19(tag:old_practice)Merge commit 'acc2f69'

    命令git describe的输出可以作为软件版本号,这个功能非常有用。因为这样可以很容易地实现将发布的软件包版本和版本库中的代码对应在一起,当发现软件包包含Bug时,可以最快、最准确地对应到代码上。

    下面的Hello World程序就实现了这个功能。创建目录src,并在src目录下创建以下三个文件:

    (1)文件:src/main.c

    没错,下面几行代码就是这个程序的主代码,和输出相关的代码就两行,一行显示"Hello,world.",另外一行显示软件版本。在显示软件版本时用到了宏_VERSION,这个宏的来源参考下一个文件。


    #include "version.h" #include<stdio.h> int main() { printf("Hello,world.\n"); printf("version:%s.\n",_VERSION); return 0; }

    (2)文件:src/version.h.in

    没错,这个文件名的后缀是.h.in。这个文件其实是用于生成文件version.h的模板文件。在由此模板文件生成version.h的过程中,宏_VERSION的值"<version>"会动态替换。


    #ifndef HELLO_WORLD_VERSION_H #define HELLO_WORLD_VERSION_H #define_VERSION "<version>" #endif

    (3)文件:src/Makefile

    这个文件看起来很复杂,而且要注意所有缩进都是使用一个<Tab>键完成的缩进,千万不要错误地写成空格,因为这是Makefile的格式要求。这个文件除了定义如何由代码生成可执行文件hello之外,还定义了如何将模板文件version.h.in转换为version.h。在转换过程中用git describe命令的输出替换模板文件中的<version>字符串。


    OBJECTS=main.o TARGET=hello all:$(TARGET) $(TARGET):$(OBJECTS) $(CC)-o- ^ main.o:main.c version.h version.h:new_header new_header: @sed-e "s/<version>/$$(git describe)/g"\ <version.h.in>version.h.tmp @if diff-q version.h.tmp version.h>/dev/null 2>&1;\ then\ rm version.h.tmp;\ else\ echo "version.h.in=>version.h";\ mv version.h.tmp version.h;\ fi clean: rm-f$(TARGET)$(OBJECTS)version.h .PHONY:all clean

    上述三个文件创建完毕之后,进入到src目录,试着运行一下。先执行make编译,再运行编译后的程序hello。


    $cd src $make version.h.in=>version.h cc-c-o main.o main.c cc-o hello main.o $./hello Hello,world. version:old_practice-3-gc024f34.