4

There are potential benefits to using multiple precompiled headers. Suppose there exists a project in which there are several headers that change infrequently and are used in many source code files. These headers tend towards two clusters, A and B. When one header changes in A, other headers in A are likely to change as well, but the probability of a header in B changing is unaffected and perhaps vice-versa as well.

Using two precompiled headers in such a case could be beneficial but most compilers that support precompiled headers only support a single precompiled header.

What is the reason for this and why is it so?

NB: This question is not asking if there exists a compiler that supports multiple precompiled headers or how to achieve such.

The question is asking about what makes it technically challenging or impractical to allow for multiple precompiled headers.

The specific compilers I'm interested in are gcc and clang compiling C++ but my expectation is that does not change the answer.

Praxeolitic
  • 22,455
  • 16
  • 75
  • 126
  • The IBM C and C++ compiler for Windows and OS/2 used to precompile every header file you ever used. This quite quickly came to an enormous number of files. So they changed it. – user207421 Oct 15 '14 at 04:45

1 Answers1

2

The real problem, I think, is combinatorics iduced by the number of conditionals in a source/header file.

Most header files are full of conditionals. "Precompiled" implies that the conditionals have been resolved... unfortunately, if you choose to resolved conditionals just to true or false, and you have 20 of them, there are ~~16 million possible configurations. (And we aren't even counting the defines that are scalars but not boolean values, or are parameterized macros).

If the usage is such that one configuration is needed, you can get by with one precompiled header file. Interestingly, for an individual developer this seems to be pretty common, which is one explanation for "only one". But if the configurations change rapidly, either one needs a huge number of precompiled headers, which has its own cost (imagine "precompiling" 16 million preconfigured headers), or one must generate them on demand (oops, this is the situation we were hoping to avoid).

One might duck this two ways.

Much of the cost of "precompiling" is simply processing the text. If compilers broke header files into the consitutent tokens, and stored the tokens, then that text processing time could be largely avoided, even if the conditionals were still evaluated every time. I've never seen (but haven't looked very hard) for a C or C++ compiler that did this.

Another possibility is to precompile and store every combination a user actually uses, and store them indexed by the configuration. Then lookup would be easy to find the "right" precompiled header. I suspect this would top out for a single user at a modest number; who has time to experiment with hundreds of configurations?

A sort of far out idea is to symbolically evaluate the conditions. While many are independent, some of the conditionals control the configuration of others, so there is a complex set of constraints across the conditions... One could precompute these combinations, and then precompute the possible configurations. There might be a lot fewer useful combinations in practice.

More practical might be to isolate groups of interrelated conditionals. In essence, you get a lot of smaller header files each with fewer conditionals. If they get small enough, you might actually be able to precompute the space of choices for the smaller files, and then simply choose the right one. You'd have to attach a preprocessor configuration description to each one.

Usually the best solutions are ones that are hybrids. I'd expect that storing the tokens rather than the text, splitting up conditionals as above, but leaving some file with some unevaluated conditions, to actually be "processed" would produce a pretty useful result.

Alas, I shall have to leave these ideas to the enthusiasm of others to implement :-}

Ira Baxter
  • 93,541
  • 22
  • 172
  • 341
  • The precompiled headers I'm familiar with are already bound to the compiler options used to generate them. Macros are not just defined/undefined but can also expand so trying to preempt all possible configurations is impossible, even for a single precompiled header. That stuff is the user's problem. – Praxeolitic Oct 15 '14 at 02:33
  • 1
    Yes, they have to be; the compiler can't use the precompiled header unless it can verify that the precompiled header was processed with the same set of defines (including parameterized macros). Otherwise the content might not be correct. Any precompiled header that is saved, needs to have its associated configuration stored with it for such a check. – Ira Baxter Oct 15 '14 at 02:49