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

时间:2010-12-19 11:38:55

标签: c++ gcc precompiled-headers gnu-make

我使用gcc(运行为g++)和GNU make。 我使用gcc预编译头文件precompiled.h,创建precompiled.h.gch; Makefile中的以下行执行:

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

一切顺利,直到我必须使用不同的命令行参数运行g++。 在这种情况下,即使precompiled.h.gch存在,也无法使用,编译速度会慢得多。 在gcc文档中,我已经阅读了处理这种情况, 我必须创建一个名为precompiled.h.gch的目录并放入 那里预编译的头文件, 每组g++命令行参数的一个文件。

所以现在我想知道我应该如何改变我的Makefile来告诉g++创建 这样的gch文件。 也许我可以运行g++来测试它是否可以使用任何现有文件 在precompiled.h.gch目录中, 如果没有,则生成一个具有唯一文件名的新预编译头。

gcc是否支持进行此类测试?

也许我可以用另一种方式实现我想要的东西?

2 个答案:

答案 0 :(得分:5)

回答我自己的问题似乎很奇怪;无论如何,这里去了。

要检测是否存在合适的预编译头文件,我会在我的头文件中添加一个故意错误:

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

这是有效的,因为如果gcc找到预编译的头文件,它将不会读取.h文件,也不会遇到错误。

要“编译”这样的文件,我首先删除错误,将结果放在一个临时文件中:

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

此处MORE_HACKERY不仅仅是普通文件名,还包含一些代码,用于创建具有唯一名称(mktemp)的文件。为清楚起见,省略了它。

答案 1 :(得分:0)

有一种比在precompiled.h中引入#error更简单的方法:永远不要创建这个文件。无论是G ++还是Visual C ++(至少到2005年)都不期待&#34;真正的&#34;文件存在,如果预编译版本(如果他们得到必要的编译标志)。

让我们说我们想要预编译的#includes列表被称为&#34; to_be_precompiled.cpp&#34;。文件扩展名并不重要,但我不想将其称为.h文件,因为它必须以与真正的头文件不同的方式使用,并且它更容易使用Visual C ++,如果这是一个.cpp。然后在整个代码中选择一个不同的名称来引用它,让我们说&#34; precompiled_stuff&#34;。同样,我不想把它称为.h文件,因为它根本不是文件,它是引用预编译数据的名称。

然后在所有其他源文件中,语句#include "precompiled_stuff"不是真正的包含,而只是加载预编译数据。您可以自行准备预编译数据。

  • 对于g ++,您需要一个构建规则来创建&#34; precompiled_stuff.gch&#34;来自源文件,其名称与编译器无关(但是&#34; to_be_precompiled.cpp&#34;此处)。
  • 在Visual C ++中,字符串&#34; precompiled_stuff&#34;等于/ Yu标志的值,加载的预编译数据来自具有不相关名称的.pch文件,您也是从不相关的源文件创建的(再次&#34; to_be_precompiled.cpp&#34;此处)。
  • 只有在没有预编译头支持的编译器构建时,构建规则才需要生成一个名为&#34; precompiled_stuff&#34;的实际文件,最好是在远离真实源文件的构建目录中。 &#34; precompiled_stuff&#34;是&#34; to_be_precompiled.cpp&#34;的副本,硬链接或符号链接,或包含#include "to_be_precompiled.cpp"的小文件。

换句话说,你认为每个编译器都支持预编译,但对于某些编译器来说,它只是一个愚蠢的副本。

相关问题