msvc 编译路径_C++加快编译速度(Fast Build)的措施总结

853ec1627a5f96f4ed38bf5ee7d9dca4.png
  1. 前项声明 - 尽可能的使用forward来声明而不是直接包含定义
  2. pimp模式 - 将实现隐藏在指针内,放在一个分离的class中。另外一种范式就是通过定义抽象类,然后子类化他所对应的接口,这样你所依赖的是稳定的接口函数,不会随着他的实现的修改而重新编译。
  3. 并行编译 - 在Visual Studio中你通过打开flag /MP[processorMax]或者在Make中通过追加-jN来实现。如果你用的CMake你可以通过target_compile_options来追加,比如你也可以直接命令行给Make参数
  4. 分布式编译 - 我们可以通过追加nodes来加快我们编译速度, 当你设置好比如distcc之后,你在CMake 3.4可以定义这个选项来帮助你使用distcc, cmake -DCMKAE_CXX_COMPILER_LAUNCHER=/usr/bin/distcc /path/to/cmakedir. 让你的source file在你的本机其他机器上进行预处理(注意:如果你想在预处理阶段交给所有的机器,你需要统一他们的compile versions, libraries等)在本地和其他机器上进行compile接收来自其他机器的objs进行link
  5. Compiler Cache(编译缓存) - 这个机制建立的前提是不再依靠时间戳timestamp来做某个文件是否要重新编译的依据,相反,他建立在根据文件本身的内容和compiler flags来建立计算对应的hash value. 再把每个hash value和obj files做好注册映射放在compiler cache里,这样一旦你需要重新编译某个内容没有更改的cpp,他就会直接从这个cache中帮你拿过来。UNIX比较流行的就是ccahe, Windows的话可以使用clcache. 同样的,你也可以通过cmake -DCMAKE_CXX_COMPILER_LAUNCHER=/usr/bin/ccache /path/to/cmakedir来建立这个CMake关系。 当然了,你甚至可以结合第四部的分布式编译,你需要设置的环境变量是export CCACHE_PREFIX=distcc 然后再利用上面的cmake .. -Dxxx来建议你的compiler launcher即可
  6. 预编译头文件(Precompiled Header Files) - 把一系列需要一直包含的那些重型头文件(比如iostream)单独拎出来放到一个额外的文件中去,并且对他进行编译,然后把这个编译后的文件给所有的编译单元(translation units)进行include在最开始的时候。 在MSVC下,你需要创建两个文件,一个是stdafx.h另外一个是stdafx.cpp 你需要先编译stdafx.cpp通过/Yc"path-to-stdafx.h"默认会为你生成一个.pch的文件当你想使用这个pch文件的时候,你既需要指定Fp"path-to-pch"和/Ycand /Yu来指定你的.pch文件的路径。随后我们需要修改我们的cpp,要么就是在最开始的时候进行#include "path-to-stdafx.h"要么就直接加/FI"path-to-stdafx.h"这个编译选项。在GCC下会有点不同,你需要传递给complier的是prefix header而不是编译好后的文件。 由编译器来帮你自动生成对应的.gch编译文件。 然后你通过-x这个选项,你可以指定是否是c-header还是c++-header, 随后你就可以通过在你的源码中进行#include或者直接gcc的-include来强制包含达到结合这个预处理头文件的目的CMake在3.16引入了target_precompiled_headers,在这个版本之前你可以尝试搜索cotire这个module,他会自动帮你做对应的pch处理
  7. Single Compilation Unit(统一化编译单元) - 运行核心的原理是通过一个cpp去包含别的cpp组装成一个巨大的cpp,比如,如果一个文件包含了所有的translation units,那么这个方法就叫为Unity Build。下面是他的诸多优点: 编译单元的数量急剧减少,因此你的磁盘操作数也会下降。编译器针对模板实例化的操作也下降,这个极大的优化了编译的时间LTO(Link Time Optimization)/WPO(Whole Program Optimization)的linker优化可以进行实施这会对你DevOps的incremental build有一些恶化的效果,因为此时当你修改某个编译单元之后,你的整个single translation unit都要重新编译因为使用了Unity Build,因此你再想使用分布式编译已经不可能了,因为此时的cpp就没几个当然用这种方法之后其实也有有一些缺点: 违反ODR原则(在匿名空间中的macros,local static functions, global static variables会容易起冲突)你可能需要使用namespace来做名字的格力多核系统会因为这个受益颇多: 针对多个Single Compliation Unit并行编译并且使用precompiled header利用compiler cache的分布式编译
  8. 替换你的编译组件 - 比如你可以替换你的ld为gold,如果你的binutils是2.19以后的版本,那默认会随着这个工具,你也可以通过-fuse-ld=gold来让gcc帮你选择gold,下面是一个CMake的实力版本来invoke你的gold,当然如果你有llvm的ldb其实更好,他甚至比你的gold更快
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值