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.
Controlling Warning Messages You can then use -Wunused-variable to turn on that warning specifically, without enabling others. To disable that warning, replace the leading -W with -Wno- , and use it in combination with an option to enable the desired warning level.
If either the compiler or the linker can see that there are no references to C functions or C variables, they can (and usually do) remove those unused things.
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.
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>:
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With