2

I've got a C++ project that happens to be stored in a Bazaar repo. This project also uses a #define'd string to display its version number. Someone just asked if we could simply tie this displayed version number to the bzr repo revision number.

So, in pseudo-C, pseudo-bash, something like:

#define VERSION_STRING "revision $(bzr revno)"
//...
cout << "Starting " << VERSION_STRING;

Or so. How might you answer this question? Does the makefile run a script that inserts the output of that command into the appropriate source file? Is there a macro solution for this? Etc?

I'm open to any and all clever solutions, as I'm drawing an educated blank on this one. =D

pdm
  • 1,027
  • 1
  • 9
  • 24
  • 3
    You can define macros with the `-D` compiler flag for g++ and clang++: `g++ -DVERSION_STRING="revision $(bzr revno)" file.cpp -c -o file.o` – BoBTFish Dec 15 '15 at 16:46
  • Ah, perfect. Would that take precedent over a macro defined in source of the same name? The reason I ask is because I figure I should include a `#define VERISON_STRING "000"` in case the inline bash fails when `g++` is invoked. – pdm Dec 15 '15 at 16:51
  • Expanded into a full answer. – BoBTFish Dec 15 '15 at 17:05
  • Did that work for you? – BoBTFish Dec 15 '15 at 21:03
  • It did! ...Turns out, though, that the structure of the project makes this solution not viable. Alas. But you definitely answered, so you definitely get the points. =) – pdm Dec 16 '15 at 20:32

1 Answers1

2

The compiler will have a flag to define a macro value externally. For g++ and clang++ this is -D:

g++ -DVERSION_STRING="revision $(bzr revno)" file.cpp -c -o file.o

To get that in the file as a string, you can either add extra quotes into the definition:

g++ -DVERSION_STRING="\"revision $(bzr revno)"\" file.cpp -c -o file.o

or you need to know how to stringify that value inside the file, which takes a little magic:

#define STRINGIFY_HELPER(X) #X
#define STRINGIFY(X) STRINGIFY_HELPER(X)

Then you could also have a default value. I'd recommend have a different variable set by the compiler to the one you use internally, it helps keep track:

#include <iostream>

#define STRINGIFY_HELPER(X) #X
#define STRINGIFY(X) STRINGIFY_HELPER(X)

#ifdef VERSION
#define VERSION_STRING STRINGIFY(VERSION)
#else
#define VERSION_STRING "0.0.0"
#endif

int main()
{
    std::cout << VERSION_STRING << '\n';
}

results in:

$ g++ -DVERSION="1.0.0" SO.cpp
$ ./a.out 
1.0.0
$ g++ SO.cpp
$ ./a.out 
0.0.0

Note, $(bzr revno) is the syntax to run bzr revno and substitute its output in a shell (bash syntax, probably the same in most others). From within a makefile, as musasabi pointed out, the syntax is slightly different: $(shell bzr revno),

Community
  • 1
  • 1
BoBTFish
  • 19,167
  • 3
  • 49
  • 76
  • 1
    Only change was that I needed to use `$(shell bzr revno)` in the makefile. =) – pdm Dec 16 '15 at 20:33