Partially preprocess a C or C++ source file?

2019-04-26 15:30发布

Is there a way to partially pre-process a C or C++ source file? By "partially preprocess" I mean expanding some but not all of the #include directives. For example, I would like to expand #includes pointing to my project headers, but not #includes pointing to other libraries' headers.

I tried to do this by running gcc -E with only the -I flags for my project headers and not the -I flags for the libraries, but that doesn't work because gcc gives an error when it encounters an #include it cannot expand.

EDIT: I do not really care about the preprocessor's behaviour with respect to macro expansion.

5条回答
聊天终结者
2楼-- · 2019-04-26 15:34

In the general case, a partial header expansion is meaningless. Consider the following example:

#include <limits.h>

#if UINT_MAX > 0xffffffff
# include "fasthash_64.h"
#elif UINT_MAX == 0xffffffff
# include "hash.h"
#else
# error "int too small for hash implementation."
#endif
查看更多
Fickle 薄情
3楼-- · 2019-04-26 15:37

The #include which you don't want to expand, you can replace with something like $$$include (in short, which cannot be understood by pre-processor). Preferably first you copy original files into the temporary files and then run gcc -E <filename>;. Once you are done, again replace to the original source files.

The only concern here is that you have to go and edit your source files at least once. But that may not be a big deal as you can use the facility provided by your text editor.

查看更多
beautiful°
4楼-- · 2019-04-26 15:44

The C preprocessor isn't smart enough to do this on its own. If you're only interested in #include, you should just roll your own tool (in, say, Perl) to process the source files, expanding #include lines that interest you and ignoring the rest.

This script prefixes uninteresting header lines with // Ignored:

#!/usr/bin/perl

use warnings;
use strict;

my @uninteresting = qw(iostream vector map);
my $uninteresting = join '|', @uninteresting;

while (<>) {
    s%(#include <(?:$uninteresting)>)%// Ignored $1%;
    print;
}

Now you can do:

cat sourcefile.cpp | perl ignore-meh.pl | g++ -E

And if you want to get really fancy:

#!/usr/bin/perl

use warnings;
use strict;

while (<>) {
    s%// Ignored (#include <[^>]+>)%$1%;
    print;
}

Now you can do:

cat sourcefile.cpp | perl ignore-meh.pl | g++ -E | perl restore-meh.pl
查看更多
手持菜刀,她持情操
5楼-- · 2019-04-26 15:46

Use -nostdinc for gcc (or cpp).

gcc ... -nostdinc ...
查看更多
forever°为你锁心
6楼-- · 2019-04-26 16:00

How about this?:

#include <always_include.h>
#include <another_always_include.h>

#ifdef PART_2_INCLUDES
 #include <part2.h>
 #include <part2a.h>
#endif

#ifdef PART_3_INCLUDES
 #include <part3.h>
 #include <part3a.h>
#endif

...

Then, to compile everything, gcc -DPART_2_INCLUDES -DPART_2_INCLUDES ... Or, since it seems like usually everything should be included by default and not including some items is the special case, reverse the sense of the tests:

#include <always_include.h>
#include <another_always_include.h>

#ifndef PART_2_INCLUDES_OMITTED
 #include <part2.h>
 #include <part2a.h>
#endif
...
查看更多
登录 后发表回答