Why doesn't g++ find the precompiled-header that's in the -I include-path?
Asked Answered
W

1

11

I'm trying to build a precompiled header and an executable, like so:

g++ -g -Wall -std=c++17 \
    -c ./src/pch.hpp -o ./build/pch.hpp.gch

g++ -g -Wall -std=c++17 \
        -c ./src/*.cpp  \
        -I./build/ -include pch.hpp

The pch.hpp.gch file is created correctly. But for each of the .cpp files, I'm getting the following error:

1 error generated.
<built-in>:1:10: fatal error: 'pch.hpp' file not found
#include "pch.hpp"

I think my compilation line is correct, based on the gcc Precompiled Headers documentation:

  • -I./build/ tells it to add build directory to the include search-path.
  • -include pch.hpp prepends an #include <pch.hpp> directive to each file.
  • The compiler searches for precompiled headers, with the .gch suffix, for each of its #include directives.

Why is my compilation line not working as expected?


There are some things I've tried which do give me better results, but they don't look correct to me.

If I modify the include to search for a .gch file, then the file is found, in line with what I'd expect. That is, -include pch.hpp.gch, instead of -include pch.hpp .
But then, the PCH is interpreted as a binary file, and compilation fails:

g++ -g -Wall -std=c++17 \
        -c ./src/*.cpp  \
        -I./build/ -include pch.hpp.gch
./build/pch.hpp.gch:2:22: error: source file is not valid UTF-8

I'm not surprised that #include <pch.hpp.gch> doesn't compile. But I'm mentioning this since it seems to show that in my original command, the build folder is searched (as I expected), but the mechanism that knows to use the .gch file instead of a regular header isn't active. Weird.

Alternatively, if I add the src folder to the header search path, it works:

g++ -g -Wall -std=c++17 \
        -c ./src/*.cpp  \
        -I./src/ -I./build/ -include pch.hpp

I do not understand why adding another, irrelevant include-path solves anything. Weird.


My current working solution is to drop the -I include-path directive entirely, and specify a more complete path to build/pch.hpp:

g++ -g -Wall -std=c++17 \
        -c ./src/*.cpp  \
        -include ./build/pch.hpp

This one works as expected. I'm not sure why it's necessary, though, and it's peculiar and inconvenient.

Is this how a PCH is supposed to be used? Why does my original line not work, and what am I meant to be doing instead?

Winegrower answered 30/4, 2019 at 9:56 Comment(0)
K
10

From the documentation:

A precompiled header file is searched for when #include is seen in the compilation. As it searches for the included file (see Search Path in The C Preprocessor) the compiler looks for a precompiled header in each directory just before it looks for the include file in that directory. The name searched for is the name specified in the #include with ‘.gch’ appended. If the precompiled header file cannot be used, it is ignored.

For instance, if you have #include "all.h", and you have all.h.gch in the same directory as all.h, then the precompiled header file is used if possible, and the original header is used otherwise.

It means that the compiler must be able to find BOTH h-file and gch-file while building cpp. So they BOTH should in the same directory or the same include search path.

Keniakenilworth answered 7/5, 2019 at 15:2 Comment(2)
So why when I use -include ./build/pch.hpp without the additional search path the compiler will not find the original header file, and yet it still works?Winegrower
Your second option is skipping precompiled header at all. Compiler includes pch.hpp as a typical header file.Keniakenilworth

© 2022 - 2024 — McMap. All rights reserved.