Compile Time Configuration

Library compile time configuration

The C++ preprocessor iterator library may be configured at compile time by specifying different preprocessor constants to include different additional features. The possible preprocessor constants are described in the following table.

Summary of possible preprocessor constants for
library configuration
WAVE_SUPPORT_WARNING_DIRECTIVE

Support the #warning directive

WAVE_SUPPORT_MS_EXTENSIONS

Support several MS specific language extensions (i.e. __int8 et.al.)

WAVE_PREPROCESS_ERROR_MESSAGE_BODY

Enable the preprocessing of the message bodies of #error and #warning directives.

WAVE_RETURN_PRAGMA_DIRECTIVES

If defined, then the #pragma directives are returned as a token sequence to the caller, if not defined, the whole #pragma directive is skipped.

WAVE_PREPROCESS_PRAGMA_BODY

Enable the preprocessing of the bodies of #pragma directives.
Note though, that the body of an operator _Pragma() is preprocessed always, as required by the C99 Standard [2].

WAVE_ENABLE_COMMANDLINE_MACROS

Enable the functionality required to define macros with the command line syntax (-DMACRO(x)=definition)

WAVE_STRINGTYPE

The tokens generated by the Wave library contain the token data and the file position, where this token was found in the input stream.
This constant may be used to redefine the data type, which is used to hold the token data and the corresponding file name. If this isn't defined it defaults to std::string. (The here defined data type should be compatible to the std::string type)

WAVE_SUPPORT_VARIADICS_PLACEMARKERS

If defined, then the preprocessor library supports variadics and placemarkers. Note, to support C99 mode, this constant must be defined too.

WAVE_MAX_INCLUDE_LEVEL_DEPTH

If defined, it will determine the initial maximal possible include file nesting depth supported. It defaults to 1024.

WAVE_ENABLE_CPP0X_EXTENSIONS

If defined, the the preprocessor library supports a couple of experimental C++0x extensions, as macro scopes, variadics and placemarkers in C++ mode, well defined token pasting of unrelated tokens. For more details please refer to The Preliminary C++0x support.

Separation and inclusion compilation models

The Wave C++ preprocessor iterator library is build almost completely as a header only library (except for the re2c based lexer). If you're trying to include all required files at once you will mention, that the resulting compilation times are very large (up to an hour - depending on your system configuration). This straightforward method we'll call the inclusion compilation model. If you do not pay attention to compilation times, that's the way to go, no special handling is needed.

If you're interested in decreasing compilation times, the following method is to be used. This we will call it the separation compilation model. The trick is to separate the different objects such, that they are compilable separately. The function, which instantiates the templated object in question is factored out such, that its definition is visible to only one translation unit. To simplify this further this creation function is packaged into a small generator template structure.

There are two levels of separation implemented: the separation of the compilation of the C++ lexer and the separation of the compilation of the different Spirit grammars used. To use these separations you will have to define two preprocessor constants while compiling the whole application and you will have to explicitely instantiate some helper templates. The following tables shows these constants in detail.

Summary of possible compilation constants required
to enable the separation compilation model
Separate

Preprocessor constant

C++ lexer

CPP_SEPARATE_LEXER_INSTANTIATION

Spirit grammars

CPP_SEPARATE_GRAMMAR_INSTANTIATION

The following table shows the explicit template instantiations required, if you want to use the separation compilation model. The TokenT placeholder type has to be replaced with your token type to use. You will achieve the best results, if you place these into separate compilation units each. The IteratorT placeholder should be replaced by the iterator type, which was used to instantiate the wave::context<> object.

Summary of required explicit template instantiations
required when using the separation compilation model
Separate

Templates to explicitly instantiate

C++ lexers template cpplexer::re2clex::new_lexer_gen<IteratorT>; or
template cpplexer::slex::new_lexer_gen<IteratorT>;
Spirit grammars

template wave::grammars::cpp_grammar_gen<TokenT>;
template wave::grammars::expression_grammar_gen<TokenT>;
template wave::grammars::intlit_grammar_gen<TokenT>;
template wave::grammars::chlit_grammar_gen<TokenT>;
template wave::grammars::floatlit_grammar_gen<TokenT>;
template wave::grammars::predefined_macros_grammar_gen<TokenT>;
template wave::grammars::defined_grammar_gen<TokenT>;

To see an example of this you can look at the Wave driver program included as an acompanion sample to the C++ preprocessor iterator library. The corresponding files are named obviously "instantiate_...something.cpp", where the '...somthing' is a hint, which grammars are explicitely instantiated inside. By using the separation model the compilation times required to build the Wave example are dropped by up to 90%.


Last updated: Saturday, May 10, 2003 21:05