美文网首页TBOOX开源工程互联网科技我用 Linux
不同编译器对预编译头文件的处理

不同编译器对预编译头文件的处理

作者: waruqi | 来源:发表于2017-08-01 13:41 被阅读78次

最近为了给xmake实现预编译头文件的支持,研究了下各大主流编译器处理预编译头的机制以及之间的一些差异。

现在的大部分c/c++编译器都是支持预编译头的,例如:gcc,clang,msvc等,用于优化c++代码的编译速度,毕竟c++的头文件如果包含了模板定义的话,编译速度是很慢的,
如果能够吧大部分通用的头文件放置在一个header.h中,在其他源码编译之前预先对其进行编译,之后的代码都能重用这部分预编译头,就可以极大程度上减少频繁的头文件冗余编译。

但是不同编译器对它的支持力度和处理方式,还是有很大差异的,并不是非常通用,在xmake中封装成统一的接口和使用方式,还是费了很大的功夫才搞定。

msvc的预编译头处理

预编译头在msvc的项目中很常见,经常会看到类似stdafx.cpp, stdafx.h的文件,就是用于此目的,而msvc编译器是通过编译stdafx.cpp来生成预编译头文件stdafx.pch的。

创建预编译头的命令行如下:

$ cl.exe -c -Yc -Fpstdafx.pch -Fostdafx.obj stdafx.cpp

其中,-Yc就是创建预编译头stdafx.pch的意思,通过-Fp来指定*.pch的输出文件路径,用-Fo指定编译stdafx.cpp生成对象文件。

其他源码是如何使用这个stdafx.pch的呢,通过将stdafx.h传入-Yu来告诉编译器,编译当前代码,忽略#include "stdafx.h",直接使用已经编译好的stdafx.pch文件。

$ cl.exe -c -Yustdafx.h -Fpstdafx.pch -Fotest.obj test.cpp

最后链接的时候,需要把:stdafx.obj, test.obj都连接上才行,这个也是和gcc, clang编译器不同的地方。

$ link.exe -out:test test.obj stdafx.obj

注:一定要吧stdafx.obj也链接上哦,虽然stdafx.cpp仅用于生成stdafx.pch,但是对象文件也是需要。

还有个跟gcc, clang有区别的地方是,msvc的-Yu指定stdafx.h必须是#include "stdafx.h"中的头文件名字,不是文件路径哦。

clang的预编译头文件处理

个人感觉clang的预编译头文件支持方式最为友好,也最为简单。

相比于msvc,不需要stdafx.cpp,只需要一个头文件stdafx.h就可以生成pch文件。
相比于gcc,可以灵活控制pch文件的路径,更加灵活。

编译头文件生成pch文件:

$ clang -c -o stdafx.pch stdafx.h

使用预编译头文件:

$ clang -c -include stdafx.h -include-pch stdafx.pch -o test.o test.cpp

其中-include stdafx.h用于忽略编译test.cpp中的#include "stdafx.h",通过-include-pch使用预先编译好的stdafx.pch

并且这里指定的stdafx.hstdafx.pch不仅可以是在includedir搜索路径下的文件,也可以指定全路径文件名,非常灵活,例如:

$ clang -c -include inc/stdafx.h -include-pch out/stdafx.pch -o test.o test.cpp

gcc的预编译头文件处理

gcc的预编译头处理方式基本上跟clang的类似,唯一的区别就是:它不支持-include-pch参数,因此不能所以指定使用的stdafx.pch文件路径。

它有自己的搜索规则:

  1. stdafx.h所在目录中,查找stdafx.h.pch文件是否存在
  2. -I的头文件搜索路径找查找stdafx.h.pch

编译头文件生成pch文件:

$ gcc -c -o stdafx.pch stdafx.h

使用预编译头文件:

$ gcc -c -include stdafx.h -o test.o test.cpp

为了让上述代码正常编译,stdafx.h.pch必须放置在stdafx.h的相同目录下,这样编译才能找到,目前我还没有找到可以所以指定输出目录的方法。

其他注意点

gcc、clang对于*.h的头文件编译,默认是作为c预编译头来使用的,这跟c++的pch是不一样的,无法给c++的代码使用,如果要生成c++可用的pch文件,必须要告诉编译器,如何去编译stdafx.h

这个可以通过-x c++-header参数来解决:

$ gcc -c -x c++-header -o stdafx.pch stdafx.h

当然也可以通过修改后缀名来解决:

$ gcc -c -o stdafx.pch stdafx.hpp

xmake对预编译头文件的支持

xmake支持通过预编译头文件去加速c/c++程序编译,目前支持的编译器有:gcc, clang和msvc。

使用方式如下:

target("test")
    set_precompiled_header("header.h")

通常情况下,设置c头文件的预编译,这需要加上这个配置即可,如果是对c++头文件的预编译,改成:

target("test")
    set_precompiled_header("header.hpp")

其中的参数指定的是需要预编译的头文件路径,相对于当前xmake.lua所在的目录。

如果只是调用xmake命令行进行直接编译,那么上面的设置足够了,并且已经对各个编译器进行支持,但是有些情况下,上面的设置还不能满足需求:

  1. 如果要使用xmake project工程插件生成vs工程文件,那么还缺少一个类似stdafx.cpp的文件(上面的设置在msvc编译的时候会自动生成一个临时的,但是对IDE工程不友好)。
  2. 如果gcc/clang下,header.h想作为c++的预编译头文件就不支持了,除非改成header.hpp(默认会当做c头文件进行预编译)。

因此为了更加地通用跨平台,可以在工程里面创建一个类似vc中stdafx.cpp的源文件:header.cpp

target("test")
    set_precompiled_header("header.h", "header.cpp")

header.cpp的内容如下:

#include "header.h"

上面的设置,就可以很好地处理各种情况下的预编译处理,追加的header.cpp也告诉了xmake:header.h是作为c++来预编译的。

相对于经典的vc工程中的stdafx.cppstdafx.h,也能完美支持:

target("test")
    set_precompiled_header("stdafx.h", "stdafx.cpp")

更多使用说明见:target.set_precompiled_header

参考资料

Speed up C++ compilation, part 1: precompiled headers

原文出处:http://tboox.org/cn/2017/07/31/precompiled-header/

相关文章

  • 不同编译器对预编译头文件的处理

    最近为了给xmake实现预编译头文件的支持,研究了下各大主流编译器处理预编译头的机制以及之间的一些差异。 现在的大...

  • C语言学习笔记

    1. C的预处理器 .h头文件 #include是C语言的预处理指令,C语言编译器在编译前会对源码进行预处理工作。...

  • 【OC梳理】预处理指令

    预处理指令,就是我们常说的宏定义。在编译器对 C或者 objective-c 进行编译前,编译器会对这些预处理命令...

  • JAVA内存模型--指令重排序

    指令重排序 在执行程序时,为了提高性能,编译器和处理器会对指令做重排序。但是,JMM确保在不同的编译器和不同的处理...

  • 19_编译过程简介

    关键词:初识编译器、预处理、编译、汇编 1. 初识编译器 广义上的编译器由:预处理器、编译器、汇编器、链接器组成。...

  • C++重复包含头文件坏处

    为什么要避免头文件重复包含呢? 1.我们知道在编译c或c++程序时候,编译器首先要对程序进行预处理,预处理其...

  • 关于预处理器LESS的使用

    要了解预处理器LESS的使用,首先得知道什么是预处理器,说到预处理就会讲到后处理器 一、预编译器和后编译 1.预处...

  • makefile-- 自动生成依赖关系 示例

    自动生成依赖关系 1、编译行为带来的缺陷 预处理器将头文件中的代码直接插入源文件 编译器只通过预处理后的源文件产生...

  • IOS #define和预编译指令

    预处理过程扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。可见预处理过程先于编译器对源代码进行处理。 ...

  • .h和.c的恩怨

    简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几...

网友评论

    本文标题:不同编译器对预编译头文件的处理

    本文链接:https://www.haomeiwen.com/subject/zysjlxtx.html