【问题标题】:Creating several precompiled header files using GNU make使用 GNU make 创建几个预编译的头文件
【发布时间】:2011-05-27 19:59:42
【问题描述】:

我使用 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 是否支持做这样的测试?

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

【问题讨论】:

  • -Winvalid-pch 会给你一个警告。与 -Werror 一起使用,如果 gcc 看到无效的 .gch,它将停止编译。
  • @bobbogo 谢谢,这正是我需要的!它会为我省去一些麻烦。

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


【解决方案1】:

有一种比在 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"的小文件。

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

【讨论】:

【解决方案2】:

回答我自己的问题似乎很奇怪;不管怎样,就这样吧。

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-16
    • 1970-01-01
    • 2012-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多