Conditional compilation with preprocessors like cpp is a simple but
effective means to implement variability. By annotating code fragments
with #ifdef and #endif directives, different program variants with or
without these fragments can be created, which can be used (among others)
to implement software product lines. Although, preprocessors are
frequently used in practice, they are often criticized for their
negative effect on code quality and maintainability. In contrast to
modularized implementations, for example using components or aspects,
preprocessors neglect separation of concerns, are prone to introduce
subtle errors, can entirely obfuscate the source code, and limit reuse.
Our aim is to rehabilitate the preprocessor by showing how simple tool
support can address these problems and emulate some benefits of
modularized implementations. At the same time we emphasize unique
benefits of annotations, including simplicity, expressiveness, and being
language independent. Our goal is to rehabilitate preprocessors and show
that they are not a lost cause as many researchers think. On the
contrary, we argue that - with the presented improvements -
annotation-based approaches are a serious alternative for product-line
implementation.