带有GCC的预编译头文件


91

任何人都可以使用GCC预编译头文件取得成功吗?我的尝试没有运气,我也没有看到很多关于如何设置它的好例子。我已经尝试过cygwin gcc 3.4.4,并在Ubuntu上使用4.0。


我尝试了一下,并为预编译的标头提供了最佳的用例,因为我的c源代码是编译器生成的,而不是用户编写的。Sun Studio特别是Visual Studio大大缩短了构建时间。在gcc上,如果没有预编译的头文件,情况甚至更糟。这是3.4版本,没有4.x版本,但是速度和gcc是互斥的。
洛萨尔

@Lothar的代码是什么?我发现在某些高度模板化的代码上,g ++比最近的Visual Studio编译器快10倍。
猪2014年

我的C ++代码中没有使用模板。它只是C +异常处理+不错的C ++扩展。即使在提出这个问题之后的6年,VS2010的速度也要快得多。但是与此同时,我有16个核心,因此我可以忍受它。
Lothar

Answers:


58

我绝对有成功。首先,我使用以下代码:


#include <boost/xpressive/xpressive.hpp>
#include <iostream>

using namespace std;
using namespace boost::xpressive;

//A simple regex test
int main()
{
    std::string hello( "hello world!" );

    sregex rex = sregex::compile( "(\\w+) (\\w+)!" );
    smatch what;

    if( regex_match( hello, what, rex ) )
    {
        std::cout << what[0] << '\n'; // whole match
        std::cout << what[1] << '\n'; // first capture
        std::cout << what[2] << '\n'; // second capture
    }
    return 0;
}

这只是Boost Xpressive的一个问候世界(请参阅下面的链接)。首先,我使用-Hgcc中的选项进行了编译。它显示了它使用的大量头文件列表。然后,我查看了我的IDE(code :: blocks)正在生成的编译标志,并看到了类似的内容:

g++ -Wall -fexceptions -g -c main.cpp -o obj/Debug/main.o

所以我写了一个命令,用完全相同的标志编译Xpressive.hpp文件:

sudo g++ -Wall -fexceptions -g /usr/local/include/boost/xpressive/xpressive.hpp

我再次使用编译了原始代码,-H并得到以下输出:

g ++-墙-fexceptions -H -g -c main.cpp -o obj / Debug / main.o
!/usr/local/include/boost/xpressive/xpressive.hpp.gch
main.cpp
。/usr/include/c++/4.4/iostream
.. /usr/include/c++/4.4/x86_64-linux-gnu/bits/c++config.h
.. /usr/include/c++/4.4/ostream
.. /usr/include/c++/4.4/istream
main.cpp

!意味着编译器能够使用预编译的头文件。x表示它无法使用。使用适当的编译器标志至关重要。我摘下-H并进行了一些速度测试。预编译的头文件从14秒提高到11秒。不错,但不是很好。

注意:以下是示例的链接:http : //www.boost.org/doc/libs/1_43_0/doc/html/xpressive/user_s_guide.html#boost_xpressive.user_s_guide.examples我无法使其在发布。

顺便说一句:我正在使用以下g ++

g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3


20
添加-Winvalid-pch将帮助您调试PCH的使用是否出错以及为什么出错。
lefticus 2012年

当您有许多彼此重新链接的头时,“不错,但不是很好”的预编译头很有用,因此它们将减少使用大型库或许多库的大型项目的编译时间。
jokoon

4
“还不错,但不是很好”:使用gcc 4.4.7、136个.cpp文件总大小为35.5 Mb,148个.h文件总大小为5.5 Mb,.gch文件为48 Mb,调试版本需要2'20“(vs 2 '14“非pch),-O2优化的构建需要4'30”(vs 5'33“非pch)在调试构建附近会产生预期的效果,但这只是从预编译中获利的优化构建...。不知道为什么。在Windows上,预编译的方式更加生动!
Andreas Vergison 2014年

1
(续)相应的pch / non-pch输出文件的字节大小完全相同,这很好。重复构建时,上述时间安排似乎有所不同,例如-O2 non-pch在3'45“和5'33”之间变化,因此这不是精确的科学方法,可能是由于在VMware中运行所致。无论如何,在我看来,gcc pch似乎根本没有任何好处。将其与Windows VS2012(x64,单线程编译)上的相同代码库进行比较:调试46“ pch,2'50”非pch,发布2'13“ pch,5'02”非pch。而且,当启用多处理器时,速度甚至更快...
Andreas Vergison 2014年

@AndreasVergison-您是否尝试过使用-Winvalid-pch以确保正确使用了预编译的标头?我们注意到将pch用于我们的调试版本有了很大的改进,所以我想知道您的设置是否存在问题。
Josh Kelley 2014年

52

首先,请参阅此处的文档

您可以像其他任何文件一样编译标头,但是将输出放在后缀为的文件中.gch

因此,例如,如果您预编译stdafx.h,则您将拥有一个预编译的头文件,该头文件将在stdafx.h.gch您包括stdafx.h

例:

stdafx.h:

#include <string>
#include <stdio.h>

a.cpp:

#include "stdafx.h"
int main(int argc, char**argv)
{
  std::string s = "Hi";
  return 0;
}

然后编译为:

> g++ -c stdafx.h -o stdafx.h.gch
> g++ a.cpp
> ./a.out

即使在步骤1之后删除了stdafx.h,您的编译也将起作用。


8

-xC ++预编译标头的说明符-x c++-header不是-x c++。以下是PCH的示例用法。

pch.h

// Put your common include files here: Boost, STL as well as your project's headers.

main.cpp

#include "pch.h"
// Use the PCH here.

像这样生成PCH:

$ g++ -x c++-header -o pch.h.gch -c pch.h

pch.h.gch必须在为同一个目录中pch.h,以惯了,所以请确保您从所在目录执行上面的命令pch.h是。


3
这应该是-c pch.h-c pch.cpp
MM

7

过去,我已经设法使预编译的头文件在gcc下工作了一次,我还记得当时也有问题。要记住的是,如果不满足某些条件,gcc将忽略该文件(header.h.gch或类似文件),可以在gcc预编译的头文件说明页上找到该文件的列表

通常,让构建系统首先编译.gch文件是最安全的,并使用与其他源代码相同的命令行选项和可执行文件。这样可以确保文件是最新的,并且没有细微的差异。

首先将其与人为设计的示例一起使用可能也是一个好主意,只是消除了您的问题特定于项目中的源代码的可能性。


7

调用gcc的方式与调用源文件相同,但带有头文件。

例如

g++ $(CPPFLAGS) test.h

这将生成一个名为test.h.gch的文件

每次gcc搜索test.h时,它都会首先查找test.h.gch,如果找到它,它将自动使用它。

可以在GCC预编译标题下找到更多信息


我正在使用gcc 3.4,并且g ++ stdafx.h行将无法编译,您会收到错误消息“ g ++:请求头文件的编译”,但这将进行编译,但不确定这是否是我想要的:“ g ++ -c -x c ++ stdafx.h -o stdafx.h.pch”
stefanB

0

确保 -include your_header.h

这就是我预编译和使用bits/stdc++.h集合的方式。

#include <bits/stdc++.h>

然后我通过使用-H编译文件并查看输出来定位该库

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

我看到的地方

. /usr/include/x86_64-linux-gnu/c++/7/bits/stdc++.h

因此,我bits在当前目录中创建了一个新目录并stdc++.h从那里复制。

然后我跑了

g++ bits/stdc++.h -O3 -std=c++14  -pthread

产生了 bits/stdc++.gch

通常我通过编译我的代码

g++ sol.cpp -O3 -pthread -lm -std=c++14 -o executable

,但我不得不将其修改为

g++ sol.cpp -include bits/stdc++.h -O3 -pthread -lm -std=c++14 -o executable

因为它只决定.gch归档而不是归档.h-include bits/stdc++.h 这对我来说很关键。要记住的另一件事是,您必须使用与编译*.h.NET文件几乎相同的参数来编译头文件*.cpp。当我不包括它-O3-pthread它忽略了*.gch预编译的头文件时。

要检查一切是否正确,您可以通过比较以下结果来测量时差

time g++ sol.cpp ...

或跑步

g++ sol.cpp -H -O3 -pthread -lm -std=c++14 -o executable

再次查找标头路径!,例如,现在是否在库路径之前

! ./bits/stdc++.h.gch
....
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.