Nitro
Nitro

Reputation: 1093

Get the value of a defined variable

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

Answers (2)

Florian Weimer
Florian Weimer

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

Beta
Beta

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

Related Questions