Creating several precompiled header files using GN

2019-04-22 22:07发布

I use gcc (running as g++) and GNU make. I use gcc to precompile a header file precompiled.h, creating precompiled.h.gch; the following line in a Makefile does it:

# MYCCFLAGS is a list of command-line parameters, e.g. -g -O2 -DNDEBUG
precompiled.h.gch: precompiled.h
    g++ $(MYCCFLAGS) -c $< -o $@

All was well until i had to run g++ with different command-line parameters. In this case, even though precompiled.h.gch exists, it cannot be used, and the compilation will be much slower. In the gcc documentation i have read that to handle this situation, i have to make a directory called precompiled.h.gch and put the precompiled header files there, one file for each set of g++ command-line parameters.

So now i wonder how i should change my Makefile to tell g++ to create the gch-files this way. Maybe i can run g++ just to test whether it can use any existing file in the precompiled.h.gch directory, and if not, generate a new precompiled header with a unique file name.

Does gcc have support for doing such a test?

Maybe i can implement what i want in another way?

2条回答
啃猪蹄的小仙女
2楼-- · 2019-04-22 22:54

It seems weird to answer my own question; anyway, here goes.

To detect whether a suitable precompiled header file exists, i add a deliberate error to my header file:

// precompiled.h
#include <iostream>
#include <vector>
...
#error Precompiled header file not found

This works because if gcc finds a precompiled header, it will not read the .h file, and will not encounter the error.

To "compile" such a file, i remove the error first, placing the result in a temporary file:

grep -v '#error' precompiled.h > precompiled.h.h
g++ -c -x c++ $(MYCCFLAGS) precompiled.h.h -o MORE_HACKERY

Here MORE_HACKERY is not just a plain file name, but contains some code to make a file with unique name (mktemp). It was omitted for clarity.

查看更多
闹够了就滚
3楼-- · 2019-04-22 22:58

There is a simpler way than introducing an #error in precompiled.h: never create this file at all. Neither G++ nor Visual C++ (at least up to 2005) expect the "real" file to be there, if a precompiled version is around (and if they get the necessary compilation flags).

Let's say the list of #includes that we want to precompile is called "to_be_precompiled.cpp". The filename extension doesn't matter much, but I don't like to call this a .h file, since it has to be used in a way different from genuine header files, and it's easier in Visual C++ if this is a .cpp. Then pick a different name to refer to it throughout the code, let's say "precompiled_stuff". Again, I I don't like to call this a .h file, because it's not a file at all, it's a name to refer to precompiled data.

Then in all other source files, the statement #include "precompiled_stuff" is not a genuine include, but simply loads precompiled data. It's up to you to prepare the precompiled data.

  • For g++, you need a build rule to create "precompiled_stuff.gch" from a source file whose name doesn't matter to the compiler (but would be "to_be_precompiled.cpp" here).
  • In Visual C++, the string "precompiled_stuff" equals the value of the /Yu flag and the precompiled data loaded comes from a .pch file with an unrelated name, that you also created from an unrelated source file (again "to_be_precompiled.cpp" here).
  • Only when building with a compiler without precompiled header support, a build rule needs to generate an actual file called "precompiled_stuff", preferably in the build directory away from the real source files. "precompiled_stuff" is either a copy of "to_be_precompiled.cpp", a hard or symbolic link, or a small file containing #include "to_be_precompiled.cpp".

In other words, you take the viewpoint that every compiler supports precompilation, but it's just a dumb copy for some compilers.

查看更多
登录 后发表回答