Reputation: 9884
In our source files we usually have a version string like that:
static const char srcvers[] = "VERSION/foo.c/1.01/09.04.15";
When that string isn't optimized away, it's quite useful in certain cases, as one can determine the version of each source file linked to an executable by simply calling strings a.out | grep VERSION
.
Unfortunately it is optimized away by gcc (using '-O'). So my question is, is there a simple way (a compiler switch would be great) to make gcc keep that variable (its name is always the same) without switching off any other optimizations.
Edit
What, in my opinion, makes the question different from that one, is that I'm was hoping to find a solution for which I wouldn't have to touch thousands of source files.
Upvotes: 31
Views: 38310
Reputation: 1
You are concerned about gcc
removing an unused static char[]
variable. AFAIK, the compiler is right to do so.
Other answers provided suggestion to improve that. But you don't want to change the source code of thousands of files.
Then, you might perhaps change your build (e.g. some Makefile
) so that every such source file using your trick (which is slightly wrong, as discussed here...) would not need to be changed. So you might invoke GCC specifically. You want
static const char _ver[] __attribute__((used));
(this is a declaration, not a definition) to be compiled before anything else. Put the line above in some _declare_ver.h
file, and compile with gcc -include _declare_ver.h
command (instead of gcc
). If using make
add
CFLAGS += -include _declare_ver.h
in your Makefile
.
BTW, that is a dirty trick. You should consider doing something better (following other answers).
Upvotes: 1
Reputation: 41793
As it seems that all the solutions require some kind of decoration of the version string in the source, it may help to define a macro containing all the necessary syntax and then use this macro in the source or header files whenever need:
#define SRCVERSION(file, version, data) static const char _ver[] __attribute__((used)) = "VERSION/" file "/" version "/" date;
Then in your source just put
SRCVERSION("foo.c", "1.01", "09.04.15")
The macro may be in a central project header file or on the compiler's command line.
That way, at least you do not have to touch all the source files again if you want to change something about the definition.
Note how the macro definition uses string concatenation to build the final version string. Also it contains the final semicolon so you can remove everything by defining an empty macro if needed.
Upvotes: 1
Reputation: 14743
As I understand your question, you need to add version string to every object file without touching sources. It can be done using next way.
Create header file, for example include/version.h
:
#ifndef VERSION_H
#define VERSION_H
static const char _ver[] __attribute__((used)) = "VERSION/foo.c/1.01/09.04.15";
#endif /* VERSION_H */
Then in your Makefile
(or whatever your build system is) add next gcc
flag:
CPPFLAGS += -include include/version.h
Of course it should be passed to gcc
, e.g. like this:
%.o: %.c
$(CC) $(CFLAGS) $(CPPFLAGS) -o $(*).o -c $(*).c
Now you can observe your _ver
string compiled to every object file:
$ objdump -DS src/main.o | grep _ver
Which will show you something like that:
Disassembly of section .rodata._ver:
00000000 <_ver>:
Upvotes: 5
Reputation:
Declaring the variable as volatile
can also help. That's why it is used in the first place, preventing any optimizations by the compiler regarding that variable.
Upvotes: 1
Reputation: 222040
You can use __attribute__((used))
gcc (also works in clang) specific (I see that the question is tagged gcc
) attributes for this:
This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for example, when the function is referenced only in inline assembly.
From https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html
Demo:
$ cat a.c
static const char srcvers[] __attribute__((used)) = "VERSION/foo.c/1.01/09.04.15";
$ gcc -O3 -c a.c
$ strings a.o
VERSION/foo.c/1.01/09.04.15
You can use some #if
s and #define
s to make this terser and also compile on compilers which don't support this extension.
Upvotes: 42