I have a perl script I'd like to filter my cpp/h files through before gcc processes them normally -- basically as an extra preprocessing step. Is there an easy way to do this? I realize I can feed the cpp files to the script and have gcc read the output from stdin, but this doesn't help with the header files.
The C and C++ preprocessor does not have any support for this kind of thing. The only way to handle this is to have your makefile (or whatever) process all the files through the perl script before calling the compiler. This is obviously very difficult, and is one very good reason for not designing architectures that need such a step. What are you doing that makes you think you need such a facility? There is probably a better solution that you are not aware of.
How about a wrapper around gcc that runs your Perl script and then calls gcc? Call it something like plgcc and set CC=plgcc
in your makefile. Your script will have to be smart enough to process the include directives -- unless your script calls just the pre-processor to bring in the includes, does its thing, and then calls gcc.
The classic way to handle such a process is to treat the source code (input to the Perl filter) as a new language, with a new file suffix. You then tell make
that the way to compile a C++ source file from this new file type is with the Perl script.
For example:
- New suffix:
.ccp
New rule (assuming
.cc
suffix):.ccp.cc: ${FILTERSCRIPT} $<
Add the new suffix to the suffix list - with priority over the normal C++ rules.
The last point is the trickiest. If you just add the .ccp
suffix to the list, then make
won't really pay attention to changes in the .ccp
file when the .cc
file exists. You either have to remove the intermediate .cc
file or ensure that .ccp
appears before .cc
in the suffixes list. (Note: if you write a '.ccp.o
' rule without a '.ccp.cc
' rule and don't ensure that that the '.cc
' intermediate is cleaned up, then a rebuild after a compilation failure may mean that make
only compiles the '.cc
' file, which can be frustrating and confusing.)
If changing the suffix is not an option, then write a compilation script that does the filtering and invokes the C++ compiler directly.
GCC allows you to use your own preprocessor. You could set your script as the preprocessor then run the output through cpp (the normal gcc pre-processor). Look at the gcc manual for -B and -no-integrated-cpp command line options.
Warning - I have never tried it myself so don't know how messy it might be (bear in mind though that for many years lots of languages, including C++, were implemented as preprocessors to a c compiler so support shouldn't be too bad).
I've handled cases like this in the past by doing something like the following. This approach assumes that the unprocessed source code can be distinguished through a naming scheme of some sort, in this case suffixing the basename with _pp
.
# These are your source files to be preprocessed
SRC_RAW = mysrc_pp.cpp
# These are the source files after preprocessing
SRC_PP = $(patsubst %_pp.cpp, %.cpp, $(SRC_RAW))
ALL_SRC = $(SRC) main.cpp other.cpp
OBJ = $(patsubst %.cpp, %.o, $(ALL_SRC))
$(SRC): %.cpp: %_pp.cpp
$(PERL) $< > $@
$(OBJ): %.o: %.cpp
$(CXX) ...
This does not, however, handle the case where you have header files which need preprocessing. In that case you would need similar rules for creating them.