Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 966
nihohit Avatar asked Apr 30 '19 09:04

nihohit


1 Answers

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.

like image 142
Andrey Chistyakov Avatar answered Sep 28 '22 21:09

Andrey Chistyakov