通过gcc或msvc,clang等编译器编译出来的C++源文件是.o文件。在windows上也就是PE文件,linux为ELF文件,在这一步中,调用其它代码文件中的函数的函数地址是未知的(00000),等到链接之后才会替换掉函数地址的

linux,windows 可执行文件(ELF、PE)

C++是如何编译的

C/C++编译过程主要分为4个过程

  1. 编译预处理
  2. 编译、优化阶段
  3. 汇编过程
  4. 链接程序

编译游戏引擎的耗时

内网使用IB(incrediBuild)编译引擎时总耗时2分23秒,编译2分钟,link耗时15秒

在vs中提高c++的编译速度

达到修改一行代码,10s内编译完,link会花点时间,因为所的工程都是lib,而不是dll,如果改成dll,则会更快。

调试信息的格式

把所有的工程的属性这项: C/C++ - General - Debug Information Format ,改成:C7 compatible (/Z7)

实际上是在vcxproj文件中增加了这样一项:<DebugInformationFormat>OldStyle</DebugInformationFormat>

Debug Information Format是一个编译器选项,用于控制生成的调试信息的格式。

调试信息是一种用于调试程序的数据,包括变量名、函数名、行号等信息。在程序出现错误时,调试信息可以帮助开发人员快速定位问题。

Debug Information Format选项有以下几种可选值:

  1. None:不生成调试信息。

  2. Program Database (/Zi):生成一个独立的PDB文件,包含所有的调试信息。

  3. Program Database for Edit and Continue (/ZI):生成一个独立的PDB文件,包含所有的调试信息,并且支持编辑和继续调试。

  4. Old Style (/Z7):将调试信息嵌入到可执行文件中。

需要注意的是,生成调试信息会增加可执行文件的大小,因此在发布版本时应该关闭调试信息生成。

另外,需要注意的是,如果使用了/DEBUG选项,那么编译器会自动将Debug Information Format选项设置为Program Database (/Zi)。

预编译头

选中工程,右键 - 属性 - C/C++ - Precompiled Headers - Precompiled Header 改成 Not

就是把一些固定的东西先编译好,其他cpp文件直接引用就不copy了,这东西在分布式下没用, 单机是有效果的

什么是预编译头?

includeN多的头文件会导致编译变慢,提取整个项目公共头文件放到一起,只编译一次,减少编译时间。

增量编译

在入口工程启用增量编译 : Linker - General - Enable Incremental Linking,勾选:Yes (/INCREMENTAL)

Linker - Optimization

右键 - 属性,Linker - Optimization - 把这2项改成No

  • References :No (/OPT:NOREF)
  • Enable COMDAT Folding :No (/OPT:NOICE)

OptimizeReferences 用于控制是否优化未使用的函数和数据的代码生成,当OptimizeReferences选项设置为/OPT:REF时,编译器将在链接时删除未使用的函数和数据,以减小可执行文件的大小。这可以减少可执行文件的大小,提高程序的运行效率。

EnableCOMDATFolding 用于控制是否启用COMDAT折叠优化,当Enable COMDAT Folding选项设置为Yes/OPT:ICF时,编译器将启用COMDAT折叠优化。这可以减少可执行文件的大小,提高程序的运行效率。

Linker - Debugging

右键 - 属性, Linker - Debugging , Generate Debug Info 改成Faster,可以link的更快

cgthreads(Code generation threads)

cl 默认使用的线程数是 4 ,最大可设置成 8 ,如果拥有更多核心时设置为8将可以缩短构建时间,在开启GL时效果更佳

在项目 配置属性 > C/C++ > 命令行 增加 /cgthreads8

MP(Build with multiple processes)

当您编译许多文件时,编译器选项可以显着减少构建时间。为了缩短构建时间,编译器会创建最多processMax自身的副本,然后同时使用这些副本来编译源文件

其他模式建议开启, published 模式 , 测试后构建时间并无明显差异, 因为MP对链接时编译并不能起到提速作用

同样也是在项目 配置属性 > C/C++ > 命令行 增加 /mp

Incredibuild(集群编译)

使用ib编译完之后,再从vs按F5即可启动调试,已经生成了pdb文件。

非published模式(非WPO模式) 建议以下设置:

打开IB,切到Visual Studio Builds - Advanced

  1. 关闭 Limit Concurrent PDB file Instances to []
  2. 开启 Force 64-bit tooset

使用集群或者限制本机cpu的核数,这俩动态控制好,但是本机使用一半的核还是会卡,因为其它进程不一定会分配到空闲的CPU

打开IB,切到Initiator - General

  1. Avoid task execution on local machine when possible(尽可能避免在本地计算机上执行任务)

  2. CPU Allocation : Limit maximum number of cores utilized in build to (限制构建过程中可使用的最大核心数为)

WPO

全程序优化(Whole program optimization) 功能,是为了增加文件之间的可见性,将编译延迟到了链接时

WPO 可以提高程序的执行性能,一般在发布模式下都会开启此功能,代价只是增加了部分构建时长

如果开启WPO模式后, 不建议使用 IB 构建, 也许可能会有未知问题

makefile

摘自UE引擎的某个makefile示例

CXXFLAGS += -std=c++11 -Wall -Wextra -pedantic -Wcast-align -Wcast-qual -Wno-ctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch -Wundef -Wno-unused -Wnon-virtual-dtor -Wreorder -Wdeprecated -Wno-float-equal
CPPFLAGS += -I ../single_include -I . -I thirdparty/doctest -I thirdparty/fifo_map -DDOCTEST_CONFIG_SUPER_FAST_ASSERTS SOURCES = src/unit.cpp \
src/unit-algorithms.cpp \
OBJECTS = $(SOURCES:.cpp=.o) TESTCASES = $(patsubst src/unit-%.cpp,test-%,$(wildcard src/unit-*.cpp))

CMake

cmake.txt示例

cmake_minimum_required(VERSION 3.17)
project(mycpp) set(CMAKE_CXX_STANDARD 11)
#添加需要编译的文件
add_executable(strTest strTest.cpp)

C/C++为什么要写头文件?

来源:为什么C/C++要分为头文件和源文件? - 知乎 (zhihu.com)

C时代的时候编译器比较简单,是固定的编译和链接两个过程,编译一次只处理一个文件,进行预处理之后,头文件会插入到这一个文件里,不同源代码文件的处理时独立的,这样如果头文件里面定义了一个函数的实现,编译的时候所有引用这个头文件的源码文件,生成的obj里都会有这个符号。而链接是通用的链接程序,从汇编时代就用的工具,没有什么高级功能,同一个符号链接时出现两次是会报错的。

但是,我们又说了,每个文件的编译是独立的,所以如果实现不在当前源文件里面,调用的时候编译器就不知道这个函数的类型和签名,没法生成调用代码,所以必须在调用之前先声明一遍。如果不把声明写在头文件里面,就必须在每个用到这个函数的源文件里都声明一遍,很不方便,所以综合之后的解决方案就是实现写源码文件里面,声明写头文件里面。

C++的编译链接与在vs中build提速的更多相关文章

  1. 【原创】Linux下编译链接中常见问题总结

    前言 一直以来对Linux下编译链接产生的问题没有好好重视起来,出现问题就度娘一下,很多时候的确是在搜索帮助下解决了BUG,但由于对原因不求甚解,没有细细研究,结果总是在遇到在BUG时弄得手忙脚乱得. ...

  2. c++中编译链接总结

    1 编译链接过程分为 预处理--->编译---->汇编---->链接.如下图所示 2 预处理都做了什么 (1)将所有的#define删除并展开所有的宏 (2)处理所有的条件预编译指令 ...

  3. 加快XCode的编译链接速度(200%+)—XCode编译速度慢的解决方案

    最近在开发一个大项目的时候遇到一个很头疼的问题,由于项目代码较多,每次都要编译链接1分钟左右,调试的时候很浪费时间,于是研究了一下如何提高编译链接的速度,在这里分享给大家. 提升编译链接的速度主要有以 ...

  4. C++开始前篇,深入编译链接(3)

    一,COMMON块 什么是COMMON块,这是一种机制,早期的Fortran没有动态分配空间的机制,程序员必须事先声明它所需要的临时使用空间的大小.Fortran把这种空间叫做COMMON块,当不同的 ...

  5. C++开始前篇,深入编译链接

    C++开始,为什么要写这个东西,因为按照课堂进度的话,现在的C++已经学到模板以及重载了,有时却仍然因为一些小问题无法解答,原因是忘记了开始时学到的知识,深知不能像猴子掰棒子一样,掰一个扔一个,因此, ...

  6. 编译链接 C++

    预处理之后的源文件被称为一个编译单位,也即编译器的工作对象.为了使编译能够进行,程序员必须提供各种程序其他部分的声明来孤立分析一个编译单位.所有名字空间,类,函数都应该在他们所在的编译单位中有声明,所 ...

  7. VS编译链接时错误(Error Link2005)的解决方法

    近期参与的项目中使用了公司另外一个同事提供的一个静态库文件.该静态库文件集成了CUDA, OpenCL两个库,用于做图形加速计算,提高视频解码拼接速度.但是在编译链接项目时,VS爆出如下错误: 1&g ...

  8. 模板函数(template function)出现编译链接错误(link error)之解析

    总的结论:    将template function 或者 template class的完整定义直接放在.h文件中,然后加到要使用这些template function的.cpp文件中. 1. 现 ...

  9. OC-01 编译链接的作用

    编译:检测代码的语法合法性,随后生成.o文件. 链接:把项目中所有的.out合并,生成一个可执行文件. OC编译连接过程 .m---->.o---->.out  . 检测源文件的语法合法性 ...

  10. GCC编译器编译链接

    在gcc编译器环境下,常见的文件扩展名的含义如下: .c:C源程序,经过预编译后的源程序也为.c文件,它可以通过-E参数输出. .h:头文件 .s:经过编译得到的汇编程序代码,它可以通过-S参数输出. ...

随机推荐

  1. 使用 React Three Fiber 和 GSAP 实现 WebGL 轮播动画

    参考:Building a WebGL Carousel with React Three Fiber and GSAP 在线 demo github 源码 效果来源于由 Eum Ray 创建的网站 ...

  2. 运行和编译时期资源加载的不同【vue】

    开发语言都有编译和运行两个阶段,很多时候这个也会带来许多bug 如:一个项目在开发阶段测试没有问题,然上线发布后就会有这样那样的问题,譬如说图片的加载,静态数据(js,css,json)读取错误 一 ...

  3. 在DevExpress的GridView的列中,使用RepositoryItemSearchLookUpEdit控件实现产品列表信息的展示和选择

    有时候,我们为了方便,我们往往使用扩展函数的代码方式创建很多GridView的操作功能,如在随笔<在DevExpress中使用BandedGridView表格实现多行表头的处理>中介绍过多 ...

  4. Winform或WebForm使用ReportViewer报表设计,工具栏按钮英文显示的解决办法

    在项目开发中,我们总是会用到rdlc报表设计器,大多数情况下在本地开发环境中工具栏按钮显示的是中文,但是部署到客户环境后发现显示的是英文. 解决这个问题也是走了很多弯路,给大家简单说一下: 1.最初以 ...

  5. Devexpress如何获取RadioGroup选中项的值和显示值

    分享一个小技巧,如题目所示,DEV控件如何获取RadioGroup选中项的值和显示值.也是在网上找了很久,看了大家都是通过SelectIndex的值定位选中的按钮,并没有说取选中项的值,所以自己研究了 ...

  6. 混合模式开发之原生App webview与H5交互

    快速实现 混合模式开发之原生App webview与H5交互, 详情请访问uni-app插件市场地址:https://ext.dcloud.net.cn/plugin?id=12550 效果图如下: ...

  7. 根据模板动态生成word(三)使用poi-tl生成word

    @ 目录 一.前言 1.什么是poi-tl 2.官方信息 2.1 源码仓库 2.2 中文文档 2.3 开源协议 3.poi-tl的优势 3.1 poi-tl和其他模板引擎的对比 3.2 poi-tl ...

  8. 【后端面经-Java】JVM垃圾回收机制

    目录 1. Where:回收哪里的东西?--JVM内存分配 2. Which:内存对象中谁会被回收?--GC分代思想 2.1 年轻代/老年代/永久代 2.2 内存细分 3. When:什么时候回收垃圾 ...

  9. SEO相关配置 HTML meta标签总结与属性使用介绍

    HTML meta标签总结与属性使用介绍 <!-- 声明文档使用的字符编码 --> <meta charset='utf-8'> <!-- 优先使用 IE 最新版本和 C ...

  10. 学习 YAML 语法

    符号 意义 备注 - 表示数组 数组也叫序列 # 表示注释 只支持单行注释 空格缩进 表示层级关系 相同层级左侧必须对齐 --- 表示一份内容的开始 ... 表示一份内容的结束 可省略 : 表示键值对 ...