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

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是否支持执行这样的测试?
也许我可以用另一种方式实现我想要的?

-无效-pch 会给你一个警告。与 -Werror 一起使用,如果 gcc 发现一个无效的 .gch,它将停止编译。 - bobbogo
@bobbogo 谢谢,这正是我需要的!它会帮我省些麻烦。 - anatolyg
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)。为了清晰起见,这部分内容被省略了。


2
有一个比在precompiled.h中引入# error更简单的方法:根本不要创建这个文件。如果有预编译版本存在(并且它们获得必要的编译标志),G ++和Visual C ++(至少到2005年)都不希望“真实”文件存在。
假设我们想要预编译的#includes列表称为“to_be_precompiled.cpp”。文件扩展名并不重要,但我不喜欢将其称为.h文件,因为它必须以与真正的头文件不同的方式使用,并且如果这是一个.cpp,则在Visual C ++中更容易。然后选择一个不同的名称来引用它,在整个代码中称之为“precompiled_stuff”。同样,我不喜欢将其称为.h文件,因为它根本不是文件,而是一个名称,用于引用预编译数据。
然后,在所有其他源文件中,语句#include“precompiled_stuff”不是真正的包含,而只是加载预编译数据。您需要准备预编译数据。
对于g ++,您需要构建规则从源文件(其名称对于编译器并不重要,但在这里将是“to_be_precompiled.cpp”)创建“precompiled_stuff.gch”。
在Visual C ++中,字符串“precompiled_stuff”等于/Yu标志的值,加载的预编译数据来自具有不相关名称的.pch文件,您还可以从不相关的源文件(再次在此处为“to_be_precompiled.cpp”)创建它。
仅在使用不支持预编译头文件的编译器构建时,需要生成一个名为“precompiled_stuff”的实际文件的构建规则,最好将其放在远离真实源文件的构建目录中。“precompiled_stuff”是“to_be_precompiled.cpp”的副本、硬链接或符号链接,或包含#include“to_be_precompiled.cpp”的小文件。
换句话说,您采取的观点是每个编译器都支持预编译,但对于某些编译器来说,这只是一个愚蠢的副本。

请注意,在Visual Studio中,与C++编译器相反,Intellisense确实需要预编译头文件存在(至少在2015年)。 - Stein

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接