Chrome源码阅读系列C的各种编译工具

3次阅读

共计 2192 个字符,预计需要花费 6 分钟才能阅读完成。

背景

啊 最近因为做视频和渲染相关的工程,因为图像视频相关的应用对性能要求比较高,所以大部分都会用 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 文件。

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

正文完
 0