Want to use __ DATE __ and __ TIME __ as integer for giving automated version to my code in compile time.
#define STRINGIZER(arg) #arg
#define STR_VALUE(arg) STRINGIZER(arg)
#define DATE_as_int_str useD(__DATE__) // What can be done ?
#define TIME_as_int_str useT(__TIME__) // What can be done ?
#define VERSION 1.4
#define COMPLETE_VERSION STR_VALUE(VERSION) "." DATE_as_int_str "." TIME_as_int_str
and get COMPLETE_VERSION
as string in a const unsigned char []
.
const unsigned char completeVersion[] = ?? COMPLETE_VERSION;
Should output 1.4.1432.2234 something.
One of the possible solution could be but did not work: convert-date-to-unsigned-int
In context of compile time convertint-date-and-time-string-to-just-integers-in-c One can refer expanssion-and-stringification-how-to-get-the-marco-name-not-its-value
Short answer (asked version): (format 3.33.20150710.182906)
Please, simple use a
makefile
with:and if you don't want a
makefile
, shorter yet, just compile with:Short answer (suggested version): (format 150710.182906)
Use a
double
for version number:MakeFile:
Or a simple bash command:
Tip: Still don't like
makefile
or is it just for a not-so-small test program? Add this line:to your
~/.profile
, and remember compile withgcc $CPPFLAGS ...
Long answer:
I know this question is older, but I have a small contribution to make. Best practice is always automatize what otherwise can became a source of error (or oblivion).
I was used to a function that created the version number for me. But I prefer this function to return a
float
. My version number can be printed by:printf("%13.6f\n", version());
which issues something like:150710.150411
(being Year (2 digits) month day DOT hour minute seconds).But, well, the question is yours. If you prefer "major.minor.date.time", it will have to be a string. (Trust me, double is better. If you insist in a major, you can still use double if you set the major and let the decimals to be date+time, like:
major.datetime = 1.150710150411
Lets get to business. The example bellow will work if you compile as usual, forgetting to set it, or use
-DVERSION
to set the version directly from shell, but better of all, I recommend the third option: use amakefile
.Three forms of compiling and the results:
Using make:
Running:
Using -DVERSION:
Running:
Using the build-in function:
Running:
Source code
Please note that the string is limited by
MAJOR<=9999
andMINOR<=9999
. Of course, I set this high value that will hopefully never overflow. But usingdouble
is still better (plus, it's completely automatic, no need to setMAJOR
andMINOR
by hand).Now, the program above is a bit too much. Better is to remove the function completely, and guarantee that the macro
VERSION
is defined, either by-DVERSION
directly into GCC command line (or an alias that automatically add it so you can't forget), or the recommended solution, to include this process into amakefile
.Here it is the
makefile
I use:MakeFile source:
A better version with DOUBLE
Now that I presented you "your" preferred solution, here it is my solution:
Compile with (a) makefile or (b) gcc directly:
(a) MakeFile:
(b) Or a simple bash command:
Source code (double version):
Note: this double function is there only in case you forget to define macro VERSION. If you use a
makefile
or set analias gcc gcc -DVERSION=$(date +"%g%m%d.%H%M%S")
, you can safely delete this function completely.Well, that's it. A very neat and easy way to setup your version control and never worry about it again!
it is very simple....
[in make file]
==== 1 ===================
OBJS = ....\
==== 2 ===================
DATE = $(shell date +'char szVersionStr[20] = "%Y-%m-%d %H:%M:%S";') <<== add
all:version $(ProgramID) <<== version add at first
version: <<== add
[in program]
=====3 =============
extern char szVersionStr[20];
[ using ]
=== 4 ====
You could always write a simple program in Python or something to create an include file that has simple
#define
statements with a build number, time, and date. You would then need to run this program before doing a build.If you like I'll write one and post source here.
If you are lucky, your build tool (IDE or whatever) might have the ability to run an external command, and then you could have the external tool rewrite the include file automatically with each build.
EDIT: Here's a Python program. This writes a file called
build_num.h
and has an integer build number that starts at 1 and increments each time this program is run; it also writes#define
values for the year, month, date, hours, minutes and seconds of the time this program is run. It also has a#define
for major and minor parts of the version number, plus the fullVERSION
andCOMPLETE_VERSION
that you wanted. (I wasn't sure what you wanted for the date and time numbers, so I went for just concatenated digits from the date and time. You can change this easily.)Each time you run it, it reads in the
build_num.h
file, and parses it for the build number; if thebuild_num.h
file does not exist, it starts the build number at 1. Likewise it parses out major and minor version numbers, and if the file does not exist defaults those to version 0.1.I made all the defines just be integers, but since they are simple integers you can use the standard stringizing tricks to build a string out of them if you like. Also you can trivially extend it to build additional pre-defined strings.
This program should run fine under Python 2.6 or later, including any Python 3.x version. You could run it under an old Python with a few changes, like not using
.partition()
to parse the string.Here is a working version of the "build defs". This is similar to my previous answer but I figured out the build month. (You just can't compute build month in a
#if
statement, but you can use a ternary expression that will be compiled down to a constant.)Also, according to the documentation, if the compiler cannot get the time of day it will give you question marks for these strings. So I added tests for this case, and made the various macros return an obviously wrong value (99) if this happens.
With the following test code, the above works great:
However, when I try to use those macros with your stringizing macro, it stringizes the literal expression! I don't know of any way to get the compiler to reduce the expression to a literal integer value and then stringize.
Also, if you try to statically initialize an array of values using these macros, the compiler complains with an
error: initializer element is not constant
message. So you cannot do what you want with these macros.At this point I'm thinking that your best bet is the Python script that just generates a new include file for you. You can pre-compute anything you want in any format you want. If you don't want Python we can write an AWK script or even a C program.
If you can use a C++ compiler to build the object file that you want to contain your version string, then we can do exactly what you want! The only magic here is that C++ allows you to use expressions to statically initialize an array, while C doesn't. The expressions need to be fully computable at compile time, but these expressions are, so it's no problem.
We build up the version string one byte at a time, and get exactly what we want.
This isn't exactly the format you asked for, but I still don't fully understand how you want days and hours mapped to an integer. I think it's pretty clear how to make this produce any desired string.
I have a partial answer for you. This is based on what I get from GCC:
__DATE__
gives something like"Jul 27 2012"
__TIME__
gives something like21:06:19
Put this text in an include file called
build_defs.h
:I tested the above with GCC on Linux. It all works great, except for the problem that I can't figure out how to get a number for the month. If you check the section that is under
#if 0
you will see my attempt to figure out the month. GCC complains with this message:It would be trivial to convert the three-letter month abbreviation into some sort of unique number; just subtract 'A' from the first letter and 'a' from the second and the third, and then convert to a base-26 number or something. But I want to make it evaluate to 1 for January and so on, and I can't figure out how to do that.
EDIT: I just realized that you asked for strings, not expressions that evaluate to integer values.
I tried to use these tricks to build a static string:
GCC complains that "initializer element is not constant" for
__DATE__
.Sorry, I'm not sure how to help you. Maybe you can try this stuff with your compiler? Or maybe it will give you an idea.
Good luck.
P.S. If you don't need things to be numbers, and you just want a unique build string, it's easy:
With GCC, this results in something like: