I'm working on a code base that uses quite a bit of conditional compilation via macros passed as arguments to the compiler (i.e. gcc -DMACRO_HERE file.cpp
). I would like to have a way to get a list of all the macros defined this way within the code so that I can write out all the used macros to the console and save files when the application is run, that way we know exactly what build was used.
I also need to do the same thing with the git hash but I think I can do that easily with a macro.
Edit 1: Note that this is not the same question as GCC dump preprocessor defines since I want the list available within the program and I only want the macros that are declared by being passed to the compiler with the -D
argument
Edit 2: I also need it be cross compiler compatible since we use GCC, XL, CCE, CLANG, NVCC, HIP, and the MPI versions of those. Note that we're building with Make
CodePudding user response:
I can think of one way (and only one way). You're not going to like it much, but I don't think you have a choice.
Your code will have to know all the possible #defines
that might be passed in as command line switches (yes, I know, yuk). Then you can simply do:
#ifdef MACRO_1
std::cout << "MACRO_1 is set\n";
#endif
#ifdef MACRO_2
std::cout << "MACRO_2 is set\n";
#endif
and so on.
Well I never claimed it would be pretty.
I can't think of a way to condense those three lines into one right now, but if I do I will post back here.
CodePudding user response:
Here's an outline of a possible solution.
The request is not well-specified because there is no guarantee that all object files will be built with the same conditional macros. So let's say that you want to capture the conditional macros specified for some designated source file.
On that basis, we can play a build trick, easy to do with make
: the build recipe for that designated source file actually invokes a script, by inserting the path to the script at the beginning of the compile line.
The script runs through its arguments, selects the ones which start -D
, and uses them to create a simple C source file which defines an array const char* build_options[]
, populating it with stringified versions of the command line arguments. Unless you're a perfectionist, you don't need to do heroics to correctly escape the strings, because no sane build configuration which use -D
arguments which require heroic escaping.
Once the source file is built, the script saves it and either uses the command-line it was passed as its arguments to compile it, or leaves it to be compiled by some later build step.