简体   繁体   English

使用GNU make创建几个预编译的头文件

[英]Creating several precompiled header files using GNU make

I use gcc (running as g++ ) and GNU make. 我使用gcc(作为g++运行)和GNU make。 I use gcc to precompile a header file precompiled.h , creating precompiled.h.gch ; 我使用gcc预编译头文件precompiled.h ,创建precompiled.h.gch the following line in a Makefile does it: Makefile中的以下行可以做到这一点:

# 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. 一切都很好,直到我不得不使用不同的命令行参数运行g++为止。 In this case, even though precompiled.h.gch exists, it cannot be used, and the compilation will be much slower. 在这种情况下,即使存在precompiled.h.gch ,也无法使用它,并且编译速度会慢得多。 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. 在gcc文档中,我读到了要处理这种情况的信息,我必须创建一个名为precompiled.h.gch的目录,并将预编译的头文件放在此处,每个g++命令行参数集都有一个文件。

So now i wonder how i should change my Makefile to tell g++ to create the gch-files this way. 所以现在我想知道如何更改我的Makefile来告诉g++以这种方式创建gch文件。 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. 也许我可以运行g++只是为了测试它是否可以使用precompiled.h.gch目录中的任何现有文件,如果不能,则生成具有唯一文件名的新的预编译头文件。

Does gcc have support for doing such a test? gcc是否支持进行此类测试?

Maybe i can implement what i want in another way? 也许我可以用另一种方式实现我想要的?

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. 之所以可行,是因为如果gcc找到了预编译的标头,它将不会读取.h文件,也不会遇到该错误。

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 ). 在这里,MORE_HACKERY不仅是纯文件名,还包含一些代码来创建具有唯一名称( mktemp )的文件。 It was omitted for clarity. 为了清楚起见,将其省略。

There is a simpler way than introducing an #error in precompiled.h: never create this file at all. 有一种比在precompiled.h中引入#error更为简单的方法:根本不要创建此文件。 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). 如果预编译的版本已经存在(并且获得了必要的编译标志),那么G ++和Visual C ++(至少在2005年之前)都不会期望“真实”文件存在。

Let's say the list of #includes that we want to precompile is called "to_be_precompiled.cpp". 假设我们要预编译的#include列表称为“ 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. 文件扩展名没什么大不了,但是我不喜欢将此文件称为.h文件,因为它的使用方式必须不同于真正的头文件,而且如果它是.cpp,则在Visual C ++中更容易使用。 。 Then pick a different name to refer to it throughout the code, let's say "precompiled_stuff". 然后在整个代码中选择一个不同的名称来引用它,比如说“ precompiled_stuff”。 Again, II 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. 同样,II不喜欢将此文件称为.h文件,因为它根本不是文件,它是指预编译数据的名称。

Then in all other source files, the statement #include "precompiled_stuff" is not a genuine include, but simply loads precompiled data. 然后,在所有其他源文件中,语句#include "precompiled_stuff"不是真正的包含,而是仅加载预编译的数据。 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). 对于g ++,您需要一个构建规则来从名称与编译器无关的源文件中创建“ precompiled_stuff.gch”(此处为“ to_be_precompiled.cpp”)。
  • 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). 在Visual C ++中,字符串“ precompiled_stuff”等于/ Yu标志的值,并且加载的预编译数据来自具有不相关名称的.pch文件,该文件也是从不相关的源文件中创建的(同样,此处为“ to_be_precompiled.cpp”) )。
  • 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”的实际文件,最好在远离实际源文件的构建目录中生成。 "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" . “ precompiled_stuff”是“ to_be_precompiled.cpp”的副本,硬链接或符号链接,或者是包含#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. 换句话说,您认为每个编译器都支持预编译,但是对于某些编译器而言,它只是一个哑本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM