Reputation: 1093
I am trying to write a makefile to automate the work of compiling, pushing the code to a server, and running the code all in one.
The problem is that I don't have a list of servers defined, and there are going to be other people using this makefile.
What I am trying to do is the following.
Let's say there is a code c code
#include<stdio.h>
#define SERVER_NAME "Some Server"
int main(int argc, char** argv)
{
//Some random code
}
Is there any tool which I can use in the makefile, to which I will pass the C file along with all it's dependencies, and the tool will tell me what the (For lack of a better word) variable "SERVER_NAME" is defined to?
I need something of this sort
<Some tool> <c file initially created> <all include files> <any c specific switch>
and the output is something like
SERVER_NAME="Some Server"
I know I can always do a grep on the file and pull the variable, but I want to also take care of conditions like the following.
#include<stdio.h>
#define SERVER1 //This might change to server2
#ifdef SERVER1
#define SERVER_NAME "Some Server 1"
#endif
#ifdef SERVER2
#define SERVER_NAME "Some Server 2"
#endif
int main(int argc, char** argv)
{
//Some random code
}
I know that the C preprocessor is powerful enough to do this work, I just can't figure out what arguments or switches to pass to it.
Upvotes: 0
Views: 70
Reputation: 33747
Assuming that your header files do not declare any other constants (which may be a bit of a stretch for C++ code), you can compile a file like this:
// Comes from a header file
#define SERVER_NAME "server name"
const char compile_time_server_name[] = SERVER_NAME;
The resulting object file will have the string in its constant data section. For example, if your target is ELF, you can use objcopy
from binutils to extract this data:
objcopy -O binary -j .rodata server_name.o server_name.contents
The command xxd server_name.contents
shows this:
00000000: 7365 7276 6572 206e 616d 6500 server name.
Note the trailing NUL; you may have to remove that by further scripting. It is probably a good idea to check that the boject file contains only one symbol in the .rodata
section, perhaps using nm
.
Upvotes: 0
Reputation: 99174
The gcc preprocessor option -imacros
lets you scan the macros in a source file and ignore the rest of it.
Suppose your source file is named foo.cc
:
#define SERVER1 //This might change to server2
#ifdef SERVER1
#define SERVER_NAME "Some Server 1"
#endif
#ifdef SERVER2
#define SERVER_NAME "Some Server 2"
#endif
int main(int argc, char** argv)
{
//Some random code
}
Write another source called serverReporter.cc
:
#include <iostream>
using std::cout;
using std::endl;
int main()
{
cout << "SERVER_NAME=" << SERVER_NAME << endl;
return 0;
}
Now build (with or without Make):
g++ -imacros foo.cc serverReporter.cc -o serverReporter
and run it.
(There may be a way to get the macro value without running the code, by means of an option like -dD
, but I haven't yet gotten that to work.)
Upvotes: 1