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 |
|
BOOST_WAVE_SUPPORT_WARNING_DIRECTIVE |
Support the #warning directive |
BOOST_WAVE_SUPPORT_MS_EXTENSIONS |
Support several MS specific language extensions (i.e. __int8 et.al.) |
BOOST_WAVE_PREPROCESS_ERROR_MESSAGE_BODY |
Enable the preprocessing of the message bodies of #error and #warning directives. |
BOOST_WAVE_EMIT_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. |
BOOST_WAVE_PREPROCESS_PRAGMA_BODY |
Enable the preprocessing of the bodies of all
#pragma directives. |
BOOST_WAVE_ENABLE_COMMANDLINE_MACROS |
Enable the functionality required to define macros with the command line syntax (-DMACRO(x)=definition) |
BOOST_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. |
BOOST_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. |
BOOST_WAVE_SUPPORT_CPP0X |
If defined, then the preprocessor library supports
C++0x keywords and C++0x specific features, such as variadics, placemarkers, extended character and string literals. This implies the definitions of the |
BOOST_WAVE_SUPPORT_CPP1Z |
If defined, then the preprocessor library supports
C++17 keywords - currently just |
BOOST_WAVE_SUPPORT_CPP2A |
If defined, then the preprocessor library supports
C++20 keywords, specifically |
BOOST_WAVE_MAX_INCLUDE_LEVEL_DEPTH |
If defined, it will determine the initial maximal possible include file nesting depth supported. It defaults to 1024. |
BOOST_WAVE_SUPPORT_PRAGMA_ONCE |
If defined, then the |
BOOST_WAVE_SUPPORT_PRAGMA_MESSAGE |
If defined, then the |
BOOST_WAVE_SUPPORT_INCLUDE_NEXT |
If defined, then the |
BOOST_WAVE_USE_STRICT_LEXER |
If this is defined to something != 0, then the C/C++ lexers recognize the strict C99/C++ basic source character set. If it is not defined or defined to zero, the lexers recognize the '$' character as part of identifiers. |
BOOST_WAVE_PRAGMA_KEYWORD |
If this is defined to a string literal it will be used as the pragma keyword recogniyed by the library as specific Wave pragmas. This constant defaults to "wave", i.e. the library recognizes all #pragma wave option [(argument)] directives and dispatches the handling to the interpret_pragma() preprocessing hook function (see: Preprocessing Hooks). The arguments part of the pragma is optional. |
BOOST_WAVE_SUPPORT_LONGLONG_INTEGER_LITERALS |
The C++ standard requires the preprocessor to use one of the following
types for integer literals: This preprocessor constant is effective only, if your target platform supports
long long integers ( |
BOOST_WAVE_SUPPORT_THREADING |
This preprocessor constant allows to configer whether the Wave library will be built with threading support enabled or not. This value (if defined) should be set to zero ('0') if threading needs to be disabled and to a numerical value not equal to zero, if threading should be enabled explicitly.
If this constant is not defined, the Wave library will be built using the threading
as picked up from the Boost build environment (see |
Using a different token type or lexer type in conjunction with Wave
It is possible to use the Wave library while using your own token and/or lexer types. This may be achieved by providing your lexer type as the second template parameter while instantiating the boost::wave::context<> object. The token type used by the library is derived from the token_type typedef to be provided by the lexer type. If you want to provide your own token type only, you may use the boost::wave::lex_iterator<> type contained with the library. This type needs to be parameterized with the token type to use.
The Wave library contains several samples illustrating these possibilities. The cpp_tokens sample shows the usage of a custom lexer and a custom token types. The lexer type used is functionally fully compatible to the re2c [3] based lexer used by default. It is implemented based on the SLex [5] lexer example written by Dan Nuffer. The token type used therein is functionally equivalent to the default token type except for an additional operator<< used for dumping the information carried by the token.
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 explicitly 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 |
|
C++ lexer |
|
Spirit grammars |
|
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 and the LexIteratorT
placeholder type has to be replaced with your lex iterator type you've used while instantiation of the boost::wave::context<> object. 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 boost::wave::context<> object.
Summary of required explicit template
instantiations required when using the separation compilation model |
|
Separate |
|
C++ lexer |
template
cpplexer::re2clex::new_lexer_gen<IteratorT>; |
Spirit grammars |
|
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 explicitly instantiated inside. By using the separation model the compilation times required to build the Wave example are dropped by up to 90%.
Beginning with version 1.77, Wave will require building with C++11 features, and will no longer support the use of older compilers. However, Wave will continue to emulate the features of older preprocessors indefinitely.
Copyright © 2003-2011 Hartmut Kaiser
Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
Last updated: Sunday, January 9, 2011 16:16