为构建过程添加自动递增的构建版本号

作者:Mitch Frazier

在构建软件时,为构建过程的每次迭代赋予一个唯一的编号通常很有用。许多 IDE 和 RAD 工具会自动为您执行此操作。如果您的工具没有此功能,并且您正在使用 make 文件来构建代码,则可以通过对 make 文件进行一些简单的更改,将自动递增的构建编号添加到您的项目中。

这里介绍的机制完全不需要修改您的源代码,它使用链接器符号将构建编号添加到您的程序中。但请注意,您可能需要修改源代码以显示构建编号,但这不是绝对必要的。

让我们从以下简单的 make 文件开始构建一个程序

# Makefile

OBJECTS=bnum.o

a.out: $(OBJECTS)
    $(CC) $(LDFLAGS) -o $@ $(OBJECTS)
此 make 文件构建a.out来自文件bnum.c(通过 make 内置规则)。

要将构建编号添加到 make 文件,我们将变量BUILD_NUMBER_FILE设置为将包含我们的构建编号值的文件名。然后我们添加BUILD_NUMBER_FILEa.out的依赖项中,添加BUILD_NUMBER_LDFLAGS到链接程序时使用的标志中,最后包含文件buildnumber.mak在 make 文件的末尾。转换后的 make 文件如下所示

# Makefile

# Name of text file containing build number.
BUILD_NUMBER_FILE=build-number.txt

OBJECTS=bnum.o

a.out: $(OBJECTS) $(BUILD_NUMBER_FILE)
    $(CC) $(LDFLAGS) $(BUILD_NUMBER_LDFLAGS) -o $@ $(OBJECTS)

# Include build number rules.
include buildnumber.mak

包含的文件buildnumber.mak如下所示

# Create an auto-incrementing build number.

BUILD_NUMBER_LDFLAGS  = -Xlinker --defsym -Xlinker __BUILD_DATE=$$(date +'%Y%m%d')
BUILD_NUMBER_LDFLAGS += -Xlinker --defsym -Xlinker __BUILD_NUMBER=$$(cat $(BUILD_NUMBER_FILE))

# Build number file.  Increment if any object file changes.
$(BUILD_NUMBER_FILE): $(OBJECTS)
    @if ! test -f $(BUILD_NUMBER_FILE); then echo 0 > $(BUILD_NUMBER_FILE); fi
    @echo $$(($$(cat $(BUILD_NUMBER_FILE)) + 1)) > $(BUILD_NUMBER_FILE)

    
前几行定义了链接器标志,该规则定义了递增构建编号的机制。

链接器标志使链接器创建两个符号__BUILD_NUMBER__BUILD_DATE它们将分别等于构建编号和构建日期。构建日期使用标准的date命令设置。构建编号只是构建编号文件中包含的值,该值使用标准的cat命令提取。

构建编号文件的 make 规则取决于所有项目对象文件,如果其中任何一个发生更改,则通过执行以下命令来递增构建编号

if ! test -f build-number.txt; then echo 0 > build-number.txt; fi
echo $(($(cat build-number.txt) + 1)) > build-number.txt
第一个命令检查构建编号文件是否存在。如果不存在,则将单行文本(零)写入其中。第二个命令使用cat来获取文本行,并使用 shell 的内置算术评估$((expr))来递增它并将其写回构建编号文件。

测试程序bnum.c仅写出构建编号和构建日期

#include <stdio.h>

extern char   __BUILD_DATE;
extern char   __BUILD_NUMBER;

main()
{
    printf("Build date  : %u\n", (unsigned long) &__BUILD_DATE);
    printf("Build number: %u\n", (unsigned long) &__BUILD_NUMBER);
}
请注意,链接器符号不是变量,它们没有分配用于维护值的内存,而是它们的地址是它们的值。

下面显示了一个迭代构建的示例

  $ rm bnum.o; make
  cc -c -o bnum.o bnum.c
  cc -Xlinker --defsym -Xlinker __BUILD_DATE=$(date +'%Y%m%d') \
     -Xlinker --defsym -Xlinker __BUILD_NUMBER=$(cat build-number.txt) -o a.out bnum.o
  $ ./a.out
  Build date  : 20080708
  Build number: 24
  $ rm bnum.o; make
  cc -c -o bnum.o bnum.c
  cc  -Xlinker --defsym -Xlinker __BUILD_DATE=$(date +'%Y%m%d') \
      -Xlinker --defsym -Xlinker __BUILD_NUMBER=$(cat build-number.txt) -o a.out bnum.o
  $ ./a.out
  Build date  : 20080708
  Build number: 25

自动递增的构建编号的一个注意事项是,仅仅因为您有两个具有不同构建编号的程序版本并不意味着它们在功能上有所不同。如果您例行运行make clean; make all只是为了好玩,您将获得一个新的构建编号,但没有任何改变。

Mitch Frazier 是 Emerson Electric Co. 的嵌入式系统程序员。自 2000 年代初以来,Mitch 一直是Linux Journal的贡献者和朋友。

加载 Disqus 评论