Precompiled headers with GCC

Viewed 75065

How can I get precompiled headers working with GCC?

I have had no luck in my attempts and I haven't seen many good examples for how to set it up. I've tried on Cygwin GCC 3.4.4 and using 4.0 on Ubuntu.

7 Answers

Firstly, see the documentation here.

You compile headers just like any other file but you put the output inside a file with a suffix of .gch.

So for example if you precompile stdafx.h you will have a precompiled header that will be automatically searched for called stdafx.h.gch anytime you include stdafx.h

Example:

stdafx.h:

#include <string>
#include <stdio.h>

a.cpp:

#include "stdafx.h"
int main(int argc, char**argv)
{
  std::string s = "Hi";
  return 0;
}

Then compile as:

> g++ -c stdafx.h -o stdafx.h.gch
> g++ a.cpp
> ./a.out

Your compilation will work even if you remove stdafx.h after step 1.

Call GCC the same way as if you call it for your source file, but with a header file.

E.g.,

g++ $(CPPFLAGS) test.h

This generates a file called test.h.gch.

Every time GCC searches for test.h, it looks first for test.h.gch and if it finds it it uses it automatically.

More information can be found under GCC Precompiled Headers.

I have managed to get precompiled headers working under gcc once in the past, and I recall having problems then as well. The thing to remember is that gcc will ignore the file (header.h.gch or similar) if certain conditions are not met, a list of which can be found on the gcc precompiled header documentation page.

Generally it's safest to have your build system compile the .gch file as a first step, with the same command line options and executable as the rest of your source. This ensures the file is up to date and that there are no subtle differences.

It's probably also a good idea to get it working with a contrived example first, just to remove the possibility that your problems are specific to source code in your project.

Make sure to -include your_header.h

This is how I precompiled and used bits/stdc++.h collection.

Code

#include <bits/stdc++.h>

Then I located the lib by compiling my file with -H and looking at output

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

where I saw

. /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h

So I made a new directory bits inside of current one and copied stdc++.h from there.

Then I ran

g++ bits/stdc++.h -O3 -std=c++14  -pthread

which generated bits/stdc++.gch

Normally I compiled my code via

g++ sol.cpp -O3 -pthread -lm -std=c++14 -o executable

, but I had to modify that to

g++ sol.cpp -include bits/stdc++.h -O3 -pthread -lm -std=c++14 -o executable

as it only resolved to .gch file instead of .h with -include bits/stdc++.h That was key for me. Other thing to keep in mind is that you have to compile *.h header file with almost the same parameters as you compile your *.cpp. When I didn't include -O3 or -pthread it ignored the *.gch precompiled header.

To check if everything's correct you can measure time difference via comparing result of

time g++ sol.cpp ...

or run

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

again and look for header paths and if you now get ! before library path, for example

! ./bits/stdc++.h.gch
....

A subtle tip about the file extension that tripped me up, because I wasn't paying close enough attention: the .gch extension is added to the precompiled file's full name; it doesn't replace .h. If you get it wrong, the compiler won't find it and silently does not work.

precomp.h => precomp.h.gch

Not:

precomp.h => precomp.gch

Use GCC's -H to check if it's finding/using it.

Related