Add an Auto-Incrementing Build-Number to Your Build Process
July 8th, 2008 by Mitch Frazier in
When building software it's often useful to give each iteration of your build process a unique number. Many IDEs and RAD tools do this for you automatically. If yours doesn't and you're using a make file to build your code you can add an auto-incrementing build number to your project with a few simple changes to your make file.
The mechanism presented here does not need to modify your source code at all, it uses linker symbols to add the build number to your program. Note however that you will probably want to modify your source code to display the build number, but that's not strictly necessary.
Let's start with the following simple make file for building a program:
# Makefile
OBJECTS=bnum.o
a.out: $(OBJECTS)
$(CC) $(LDFLAGS) -o $@ $(OBJECTS)
To add the build number to the make file we set the variable BUILD_NUMBER_FILE to the name of a file that will contain our build number value. Then we add BUILD_NUMBER_FILE to the dependencies for a.out, add BUILD_NUMBER_LDFLAGS to the flags used when linking the program, and finally include the file buildnumber.mak at the end of the make file. The converted make file looks like:
# 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
The included file buildnumber.mak looks like:
# 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)
The linker flags cause the linker to create two symbols: __BUILD_NUMBER and __BUILD_DATE which will be equal to the build number and the build-date respectively. The build-date is set using the standard date command. The build number is simply the value contained in the build number file, which is extracted using the standard cat command.
The make rule for the build number file depends on all the project object files and if any of them changes the build number is incremented by executing the following commands:
if ! test -f build-number.txt; then echo 0 > build-number.txt; fi
echo $(($(cat build-number.txt) + 1)) > build-number.txt
The test program bnum.c merely writes out the build number and build-date:
#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);
}
A sample of iterative builds is shown below:
$ 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
One caveat to an auto-incrementing build number is that just because you have two versions of a program with different build numbers it does not mean they are functionally different. If you routinely run make clean; make all just for fun, you'll get a new build number but nothing will have changed.
__________________________Mitch Frazier is the System Administrator at Linux Journal.
Special Magazine Offer -- 2 Free Trial Issues!
Receive 2 free trial issues of Linux Journal as well as instant online access to current and past issues. There's NO RISK and NO OBLIGATION to buy. CLICK HERE for offer
Linux Journal: delivering readers the advice and inspiration they need to get the most out of their Linux systems since 1994.
Sorry, offer available in the US only. International orders, click here.
Subscribe now!
The Latest
Featured Videos
Linux Journal Live - Oct 9, 2008
October 9th, 2008 by Shawn Powers
The October 9, 2008 edition of Linux Journal Live! Associate Editor, Shawn Powers, and Kyle Rankin, "Hack and /" columnist and author of Knoppix Hacks, Linux Multimedia Hacks, Knoppix Pocket Reference and others, discuss Linux distributions.
Linux Journal Live - Oct 2, 2008
October 3rd, 2008 by Shawn Powers
The October 2, 2008 edition of Linux Journal Live! Associate Editor, Shawn Powers, and Steven Evatt, Online Development manager for The Houston Chronicle discuss surviving disaster with Linux.
Recently Popular
From the Magazine
November 2008, #175
There aren't many numbers that put the US national debt to shame, but here's one: 1,100,000,000,000,000. What's that? That's how many floating-point operations per second the Roadrunner supercomputer at Las Alamos can perform. That's about 100 FLOPS per dollar of US debt (unfortunately, the debt is winning the second derivative race). Read the article about Roadrunner in this month's High Performance Computing issue of LJ.
Along with that, find out how to program the Cell processor and how to use CUDA with your NVIDIA GPU. Also in this issue: Mr HandS (aka Kyle Rankin) gives us a few tips on using Compiz, Chef Marcel shows you how to get blogging off your plate quicker, Mick Bauer talks about Samba security, Dan Sawyer interviews Cory Doctrow and Doc talks about how information technology can affect democracy and fix the national debt (just kidding about that last part). That and more for your reading pleasure in this month's Linux Journal.
Delicious
Digg
Reddit
Newsvine
Technorati








I personally don't like this
On August 4th, 2008 smoser says:
I've done a fair amount of work in trying to verify what source object code came from, and guaranteeing that a build of that same source at another point in time will produce identical output. This is largely of interest to a distribution that wants to make sure their source packages recompile as expected.
This sort of "feature" is quite annoying in doing that. lots of packages do similar things to this. There is even a gnu cpp compiler macro that you can use (if forget what it is).
The problem is that identical source input starts to produce binary output that differs every time a second ticks off the clock.
just my 2 cents.
Avoid a circular reference
On July 9th, 2008 V-12 Bill (not verified) says:
This is a nice tip.
However, make will complain about a circular reference.
Instead of:
OBJECTS=bnum.o
You may want to do this:
SOURCES=bnum.c
OBJECTS=$(SOURCES:.c=.o)
Then - (note dependency change)
$(BUILD_NUMBER_FILE): $(SOURCES)
@if ! test -f $(BUILD_NUMBER_FILE); then echo 0 > $(BUILD_NUMBER_FILE); fi
@echo $$(($$(cat $(BUILD_NUMBER_FILE)) + 1)) > $(BUILD_NUMBER_FILE)
This will avoid a circular reference. However, you only get a build number increment for source file changes.
Doesn't seem to complain here
On July 9th, 2008 Mitch Frazier says:
I don't get any complaints from make. Did you actually test this and get a complaint from make?
Seems like BUILD_NUMBER_FILE should depend on the same thing that linking depends on, so that every time you re-link you get a new version number. Not relevant for this example, but in more complex cases, depending on the sources would miss changes in header files.
__________________________Mitch Frazier is the System Administrator at Linux Journal.
Post new comment