How would one compute efficiently the minimal list of macro definitions combinations that will give the same code ? The list of macros is known before-hand.
The objective would be to compile less versions of the program (possibly a shader) and thus skip some compilation time by knowing what macro combinations are equivalent. eg. if a program built with MACRO_A and MACRO_B is the same as a program built only with MACRO_A.
For the sake of simplicity, those macro are either defined or not, and their value doesn't matter (meaning there is no #if SOMEMACRO).
For example with:
#ifdef A
#ifdef B
// some code
#endif
// some code
#elif defined(C)
// some code
#else
// some code
#endif
A trivial way to generate all the programs would be to compile with all the combinations made from A,B and C. It would mean creating 2^3=8 combinations. However, only the following combinations really are useful (!
means the macro is not defined, ~
that the macro doesn't matter and can be either defined or undefined ):
( A, B, ~C)
(same as A, B, C and A, B, !C)( A, !B, ~C)
(!A, ~B, C)
(!A, ~B, !C)
Which means compiling only programs with the following definitions is enough:
- A B
- A
- C
- No defines
With this list, I know that when asked for a program with the (A, !B, C)
combination I can simply use the one built with only A defined.
What tools could be used ?
Notes:
- Most preprocessors will only give the path for a given set of defines
- Perhaps building the control flow graph of the preprocessor would help?
- Some work has been done with clang here by J. Trull to add conditional nodes to the AST, but seems to be aimed at refactoring, not sure if it is the best way to do it