背景

啊 最近因为做视频和渲染相关的工程,因为图像视频相关的应用对性能要求比较高,所以大部分都会用C++来实现,过程中接触了很多C++的工程,也需要写一些C++工程,开始就卡在了复杂的环境搭建上,大部分开发者也都被都被它复杂的环境劝退了,所以这里简单总结一下C++编译相关的基础知识。

C++编译过程

首先,C++是一个高性能跨平台高级语言,当然也有定义C++是中级语言的说法,可能是因为C++里面有很多和内存或者类型相关的复杂操作,和现在比较流行的不同于C/C++对机器更友好,对人类更友好如Java、Python、Javascript之类的语言相比,上手还是要困难一点。随着计算机硬件性能越来越好,语言的趋势肯定也是会往对人类更友好的方向发展,比如安卓平台最新的Kotlin语言,苹果平台最近的Swift语言,追求C/C++性能的Go和Rust语言以及随随便便github库就星星?上万的Javascript语言。但是理解或者学习C++语言还是可以帮助自己理解计算机一些基础的原理,这些原理经久不衰,而且很多C++的开源库源码都很优雅都是很适合学习的材料。除了高性能这个特性外,跨平台也是C++被广泛应用的一个原因。今年上半年因为做浏览器端H.265视频播放的开发研究了很久WebAssembly的跨平台原理,和Wasm、JVM利用虚拟机的跨平台方案不同,C++的跨平台原理很传统,可能也是因为它更接近底层。

众所周知,计算机底层只是一个操作电路计算布尔值0/1的机器,所以所有的程序都需要转换成机器执行需要的机器码。C++的编译过程主要分为3步,可以参考这个回答。这3步分别是:

  1. 预处理:把C++源文件进行一个预处理,把里面的#include头文件、#define宏定义等进行一个分析合并,输出还是一个C++文件
  2. 编译:编译器输入预处理后的C++文件输出目标文件,通过把各个C++文件经过一些编译优化编译成汇编文件.s,汇编文件再编译成机器码文件.o
  3. 链接:链接器输入目标文件,输出一个library库或者一个可执行文件,链接这步会把各个.o/.a文件(静态库)连接起来,然后产出一个真正可执行的文件


而C++的跨平台就是在不同的操作系统下使用不同的编译器将C++源码编译成各个平台使用的可执行文件(机器码)。

C++编译器

作者接触到的MacOS下常见的C++编译器主要是2个:gccclang,当然还有比如MSVC、Intel C++之类其他平台的C++编译器,因为作者不是特别熟悉在这里就不展开了,原理基本是一样的。从上面的图描述的我们可以看到,编译器就是把cpp源文件变成可执行程序的工具,这里面编译器主要做的就是:源代码 (source code) → 预处理器 (preprocessor) → 编译器 (compiler) → 目标代码 (object code) → 链接器 (Linker) → 可执行程序 (executables)的过程。除了把源码转成机器码,这里面还涉及一些编译优化,也就是把你的代码转换成性能更高更好的机器码的一个过程,也是不同编译器的差别所在。

几种编译器的差别可以具体参考这个文章。其中编译器还有一些不同的选项,在编译速度编译文件大小编译文件性能上针对不同的情况也有差别。比如gcc有-O0、-O1、-O2、-O3四个选项,默认选项-O0不会做任何编译优化,但是里面也有一个子选项比如-floop-optimize可以对循环进行编译优化。-O1就会优化会消耗少多的编译时间,它主要对代码的分支,常量以及表达式等进行优化。 具体可以参考这个文章的介绍。

C++编译工具

因为之前研究音视频,看过一些像chromium、webrtc的C++工程,安装了很多google家的编译工具,开始的时候装的很头大,gn、ninja不知道对应是干啥的。所以把C++工程编译的流程大致了解了一下。上面我们知道了像gcc这样的编译器,在mac下也可以直接调用gcc命令来编译C++文件,比如:gcc -c hello.cpp ,就可以生成对应平台的可执行文件。

但是当工程大了之后,你每次可能都需要执行很多的命令,且文件之间存在一些依赖,每次编译就变得很麻烦,这个时候就需要用到make工具来批量进行处理,有点像js中的npm,而makefile就有点像package.json,里面包含了编译的命令集合,比如gcc命令等。makefile在一些简单的工程完全可以人工手写,但是当工程非常大的时候,手写makefile也是非常麻烦的,如果换了个平台makefile又要重新修改。这时候就出现了Cmake这个工具,cmake就可以更加简单的生成makefile文件给上面那个make用。当然cmake还有其他功能,就是可以跨平台生成对应平台能用的makefile,你不用再自己去修改了。cmake生成的就是平时在C++工程中经常看到的Makefile文件。
image.png

那么回到google家的两个编译工具gn和ninja又是什么呢?如果类比一下的话,其实gn就相当于是cmake,ninja就相当于是make,因为google家的C++产品太多了,webrtc最开始也是使用的 cmake /scons 作为编译工具的,但后来发现产生工程文件和编译速度太慢,所以就自己写了一套工具(gyp/ninja)。具体可以参考这个文章的介绍。


九瑶
139 声望26 粉丝

前阿里前端,在淘宝直播、鹿班短视频、iTAG智能AI标注平台打过杂。