[ccache] ccache and precompiled headers

Joel Rosdahl joel at rosdahl.net
Sun Jun 27 06:15:15 MDT 2010


On 2010-06-21 13:09, Tor Arne Vestbø wrote:
> I ran into a problem where ccache would log "Preprocessor gave exit
> status 1" and fail to cache builds. Closer inspection revealed that
> this was due to the use of precompiled headers though an -include
> argument to gcc. When ccache then tried to run the preprocessor on the
> source file gcc reported "file not found" for the precompiled header.
> Aparenly gcc appends ".gch" and some other magic to the filename
> during build but not during preprocessing.
> The solution seems to be to add the -fpch-preprocess flag, which will
> add a custom #pragma include to the preprocessed output, see:
>   http://gcc.gnu.org/onlinedocs/gcc-4.5.0/gcc/Preprocessor-Options.html#index-fpch_002dpreprocess-877

I came to mostly the same conclusion some months ago but decided to
postpone thinking about support for preprocessed headers until after the
3.0 release. So, now's a good time to continue. :-)

> The question is, is it safe to use ccache with precompiled headers at all?
> If so, would a patch like this work, basically adding the flag if a
> pch include is detected, and making sure it's included and hashed in
> the direct mode manifest's list of includes?

See comments below.

> [...]
> @@ -1557,6 +1562,12 @@ static void process_args(int argc, char **argv, ARGS **preprocessor_args,
>                                         }
>                                         args_add(stripped_args, argv[i]);
> +                                       if (strcmp(argv[i], "-include")
> +                                                       && strstr(argv[i+1], "pch")) {
> +                                               found_pch = 1;
> +                                               cc_log("Found precompiled header: %s",
> +                                                      argv[i+1]);
> +                                       }

But this means that you have to include "pch" in name of the precompiled
header file, which is quite limiting. There's also the case when using
'#include "preprocessed.h"' in the source code to include the
precompiled header instead of using the -include compiler option. Also,
if the name contains "pch" when it's not a precompiled header,
-fpch-preprocess will be added anyway, and that will make the
preprocessor fail if the compiler isn't GCC 4.0 or higher.

I don't see how ccache in a good way could figure out if the
-fpch-preprocess option should be added or not, so the easy option is
this: Just document that if you want ccache caching to work with
precompiled headers, you have make sure to add the -fpch-preprocess
option to the compilation command. That may be done by altering the
build system (adding -fpch-preprocess to CPPFLAGS or similar), but it
could also be done by adding -fpch-preprocess to CCACHE_CPPFLAGS if we
introduce such a variable. We also need the first part of your patch, of

Another way would be to ask the compiler if it supports the
-fpch-preprocess option and, if so, always add it. This could be done by
checking the status code of running something like "compiler
-fpch-preprocess -x c -c /dev/null -o /dev/null". The result of this
command could be cached somewhere in CCACHE_DIR (keyed with the
compiler's mtime) so that there's no need to run it more than once.
(Storing other types of information about the compiler may be useful for
other things as well, like doing compiler-specific handling of flags or
maybe enabling direct mode only for compilers known to work with it.)

There's also at least one more subtle thing that needs to be addressed:
the __TIME__ macro in direct mode. As can be read in the Performance
section in the manual
(http://ccache.samba.org/manual.html#_performance), the direct mode is
turned off when "__TIME__" is present in the source code. But when
precompiled headers are being used, ccache can't easily read the code
that was included, so it can't tell whether __TIME__ is potentially
being used and thus has to turn off direct mode as a safety measure
(unless CCACHE_SLOPPY=time_macros). This also needs to be implemented.

What do you think?

-- Joel

More information about the ccache mailing list