Modules affect preprocessing because of header units and include translation. Some uses of the preprocessor as a separate step either do not produce a correct output, or require CMIs to be available.
Header units import macros. These macros can affect later conditional inclusion, which therefore can cascade to differing import sets. When preprocessing, it is necessary to load the CMI. If a header unit is unavailable, the preprocessor issues a warning and continue (when not just preprocessing, an error is emitted). Detecting such imports requires preprocessor tokenization of the input stream to phase 4 (macro expansion).
Include translation converts
#import directives to internal
Whether a particular directive is translated is controlled by the
module mapper. Header unit names are canonicalized during
Dependency information can be emitted for macro import, extending the functionality of -MD and -MMD options. Detection of import declarations also requires phase 4 preprocessing, and thus requires full preprocessing (or compilation).
The -M, -MM and -E -fdirectives-only options halt preprocessing before phase 4.
The -save-temps option uses -fdirectives-only for preprocessing, and preserve the macro definitions in the preprocessed output. Usually you also want to use this option when explicitly preprocessing a header-unit, or consuming such preprocessed output:
g++ -fmodules-ts -E -fdirectives-only my-header.hh -o my-header.ii g++ -x c++-header -fmodules-ts -fpreprocessed -fdirectives-only my-header.ii