2

GCC can output a fully preprocessed C++ source file if I pass the -E or -save-temps command line argument.

My question is, can I somehow get a partially preprocessed C++ source file in which

a) code fragments not meeting #if, #ifdef and #ifndef conditions are eliminated,

b) #include directives are resolved (header files are included), etc

BUT

c) ordinary #define directives are NOT resolved?

(This would be necessary and really helpful because I would like to have the most compact and readable output possible. Resolving the #if directives shortens the source code, but resolving #define directives makes the source less readable and more redundant.)

I have tried to create an example as compact as possible in order to demonstrate what I would like to achieve:

Sample input files:

// header1.h
#ifndef header1_h
#define header1_h
int function1(int val) {
  return val + MYCONST;
}
#endif

// header2.h
#ifndef header2_h
#define header2_h
int function1(int val) {
  return val + val + MYCONST;
}
#endif

// main.c
#define MYCONST 1234
#define SETTING1
#ifdef SETTING1
  #include "header1.h"
#endif
#ifdef SETTING2
  #include "header2.h"
#endif
int main(void) {
  int retVal = function1(99);
}

Expected output:

// main.i (GCC preprocessing output)
#define MYCONST 1234 // I would like to see the definition of MYCONST here
#define SETTING1
#define header1_h
int function1(int val) {
  return val + MYCONST; // I would like to see MYCONST here instead of the resolved value
}
int main(void) {
  int retVal = function1(99);
}
yellowtail
  • 435
  • 3
  • 12
  • 2
    "Resolving" `#include` directives will add a *lot* to your files. And for system header files you will mostly not use or want to read most of it. – Some programmer dude Nov 11 '19 at 18:19
  • You can try to use Boost.Wave or a simliar stand alone PP implementation as a starting point for your solution. – erenon Nov 11 '19 at 18:21
  • 3
    But (c) and (a) could be dependent on each other. – Richard Critten Nov 11 '19 at 18:28
  • @RichardCritten Actually (b) too, as macros can be used for includes. – Some programmer dude Nov 11 '19 at 18:45
  • Does this answer your question? [Can I export the used code from a c program with many compiler flags?](https://stackoverflow.com/questions/9271984/can-i-export-the-used-code-from-a-c-program-with-many-compiler-flags) – rici Nov 11 '19 at 23:05
  • Piggybacking on @erenon's comment, check out simplecpp::Macro::expand here: https://github.com/danmar/simplecpp/blob/master/simplecpp.cpp – parktomatomi Nov 12 '19 at 01:16
  • Thanks for the suggestions. I have been playing around with unifdef, coan and simplecpp - with no luck so far. (The usage of these tools can sometimes be pretty difficult to understand.) I would like to note that GCC does remove superfuous code based on the evaluation of #if-s, so that's not what I am looking for. I have now added a code sample which hopefully can clarify a little bit more what I want to achieve. – yellowtail Nov 12 '19 at 07:15

1 Answers1

2

gcc has an option -fdirectives only which does something close to what you want:

-fdirectives-only

When preprocessing, handle directives, but do not expand macros.

The option’s behavior depends on the -E and -fpreprocessed options.

With -E, preprocessing is limited to the handling of directives such as #define, #ifdef, and #error. Other preprocessor operations, such as macro expansion and trigraph conversion are not performed. In addition, the -dD option is implicitly enabled.

With -fpreprocessed, predefinition of command line and most builtin macros is disabled. Macros such as __LINE__, which are contextually dependent, are handled normally. This enables compilation of files previously preprocessed with -E -fdirectives-only.

With both -E and -fpreprocessed, the rules for -fpreprocessed take precedence. This enables full preprocessing of files previously preprocessed with -E -fdirectives-only.

In your case, it should be called

 % gcc -fdirectives-only -E -o main.i main.c

but you get more defines (those internally defined), blank lines and #line lines than what you ask for.

Community
  • 1
  • 1
AProgrammer
  • 51,233
  • 8
  • 91
  • 143
  • Thanks. It works like a charm. I was not hoping for such a simple solution after so many hours spent with debugging the source of simplecpp and playing around with coan. Obviously blank lines, #line lines and comments can be easily removed, and the picture would not be whole without the listing of internally defined defines (so that's very beneficial actually) – yellowtail Nov 12 '19 at 19:25