9

我使用 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 是否支持进行此类测试?

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

4

2 回答 2

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) 的文件。为了清楚起见,它被省略了。

于 2010-12-26T20:00:59.897 回答
2

有一种比在 precompiled.h 中引入#error 更简单的方法:永远不要创建这个文件。G++ 和 Visual C++(至少到 2005 年)都不希望“真实”文件存在,如果存在预编译版本(并且如果它们获得必要的编译标志)。

假设我们要预编译的#include 列表称为“to_be_precompiled.cpp”。文件扩展名无关紧要,但我不喜欢称它为 .h 文件,因为它必须以不同于真正的头文件的方式使用,如果这是 .cpp 在 Visual C++ 中更容易. 然后在整个代码中选择一个不同的名称来引用它,比如说“precompiled_stuff”。同样,我不喜欢称它为 .h 文件,因为它根本不是一个文件,它是一个引用预编译数据的名称。

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

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

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

于 2015-02-20T16:45:54.027 回答