I have seen that is done through #ifdef and #ifndef and directives.
It can be done through #ifdef
and #ifndef
directives or #if
directives.
The key part of this is you need some way to define preprocessor macros based on what project is being built. A common way this is done is:
- Each project has its own build settings.
- Those build settings include options to pass to the compiler.
- The compiler has options to define preprocessor symbols.
For example, with GCC and Clang, you can use -Dsymbol
to cause symbol
to be defined (with no replacement tokens; it is defined, but the definition is empty) or -Dsymbol=replacement
to cause it to be defined with the indicated replacement
.
Once you have this, there are choices about how to use it. One choice is for a symbol to be defined if a feature should be included and undefined if not. Then you would have directives such as:
#if defined FeatureX
#include "HeaderForFeatureX.h"
#endif
Another choice is for a symbol to be defined to be 1 if the feature should be included and 0 if not. Then you would have:
#if FeatureX
#include "HeaderForFeatureX.h"
#endif
Historically, some people used the first choice and some people used the second. Because of this, it is common to write your settings and code to cover both of them. When defining a symbol with a compiler option, we will both define it (satisfying the first method) and define it to be 1 (satisfying the second method), as with -DFeatureX=1
. When testing it, we will test with with #if defined FeatureX
because that is true if either choice is used, whereas #if FeatureX
is true only if FeatureX
is defined to be 1, not just defined with empty replacement tokens.
(In a #if
directive, if a token that could be a preprocessor macro name is not a defined preprocessor macro name, it is replaced with 0
. So, if FeatureX
is not defined, #if FeatureX
becomes #if 0
.)
A third choice is to define a symbol to have different values according to the features chosen. For example, we could define ProductLevel
to be 10, 20, or 30, and then use directives such as:
#if 10 <= ProductLevel
#include "Level10Features.h"
#if 20 <= ProductLevel
#include "Level20Features.h"
#if 30 <= ProductLevel
#include "Level30Features.h"
#endif
#endif
#endif