编译器、Make和CMake之间的关系

之间在Linux下开发,太过于依赖IDE了,结果导致出现了某些编译依赖问题的时候,解决的效率太低,因此特别写了这一系列的笔记,作为学习的参考,也希望帮助有需要的孩砸。

编译器和编译过程

计算机最终只能识别机器码, 所以编译的最终目的是把C、C++源代码转换到机器码,实现这个过程的最核心的工具是编译器,Linux平台下最主流的编译器无非就是GCC和Clang这两个;当然也有调试过程和调试工具GDB,不过在这里不在叙述了。

编译分为3个过程,分别是:

  1. 编译预处理
  2. 生成目标文件和编译
  3. 执行链接

编译预处理

编译预处理主要是为了处理预处理的指令,比如#include#defineifdefifndef等。

#define的内容,会在与处理过程中进行替换。#include会替换成相应的源文件内容;ifndefifdef是为了处理重复编译引用的问题,这一般在头文件中进行使用。

预处理完成后,所有的源文件内容会进行相应的替换操作。之后,预处理过程会把上述的处理过程,生成一个单独的输出流,这里面也会包括每一行的来源,方便编译器出错时,显示出错位置。

编译和生成目标文件

这一步的任务是把预处理的流转换到机器码。因为有很多不同的头文件和源文件,所以会生成很多的目标文件(比如<filename>.o<filename>.obj等),这些目标文件是二进制类型。

目标文件可以引用未定义的符号,这些是我们声明了但是没有定义的函数或者类等。但是,编译器不会管这些,只要源文件没有语法等错误,就可以产生相应的目标文件。但是,一般编译器在遇到这类错误时,会停止编译的过程。

上述做法非常有用,因为我们如果只改变了一个单独的文件,编译器就不会每次都重新编译整个项目。生成的目标文件会被放在一个称为静态链接库的特殊文档中,这使得编译器可以非常容易的重复使用它们。这些目标文件虽然是二进制文件,但是现在还无法被计算机操作系统直接执行,还需要执行下一步的链接操作才可以。

链接

链接的核心步骤就是把多个分散的目标文件转换成一个可执行文件或者动态链接库之类的,这比如windows下的.exe可执行文件或者Linux下的.so动态链接文件等。连接过程中,会处理上一步中生成的目标文件,比如寻找目标文件中标注的声明等,如果在一个目标 文件中找不到相应的声明,链接器会查找目标文件声明的那些文件,如果都找不到,会报错。如果都找到相应的目标文件,没有任何错误,那么编译器会最终生成一个可执行文件或者链接库等。

编译过程的参考文档

Make和Makefile

在上面,我们描述了一个完整的编译过程,依次是:编译预处理->编译->链接。通过上述的描述,我们知道,预处理仅是处理#后面包含的内容,编译是把每个源代码文件转换成相应的目标文件,而链接是把目标文件进行组合等的处理,最终生成一个可执行文件或者链接库。

在这里,有一个问题,链接的过程中,我们需要引用不同的文件,或者说有些文件依赖于其他的编译完的文件。举个例子b.cc编译出b.oa.cc编译出a.o,而b.cc文件引用了a.cc的文件,在链接的过程中,如果最终需要 生成final可执行文件,需要组合a.ob.o,而且必须使得编译器知道b.o是依赖a.o的,否则会编译出错。

而Make的作用,就是一个自动化的构建工具,它用来告知编译器正确的处理顺序,保证每个依赖都得到了处理,最后生成相应的工程。而Makefile的作用,相当于是一个图纸,它用来告诉make,具体怎样处理编译过程。

不使用Make也可以直接利用编译器处理整个项目,如果只是个小型的工程,比如就几个源代码文件,那么依靠编译器并添加几个指令完全可以处理。但是,如果是个较大的项目,里面有复杂的依赖关系,此时再靠编译器添加几个处理指令的方式,已经不太现实了,此时使用Make和Makefile来进行自动化构建才是正确的选择。

参考文档:

CMake

上文中提到了Make是用来处理编译顺序和依赖关系并构建最终项目的工具,但是问题来了,不同的平台会有不同的构建方式。比如,Linux生成最终的二进制程序和.so动态链接,而windows生成.exe程序和.lib动态链接;同时两者的依赖可能还不同。如果在不同的平台写不同的Makefile,会相当麻烦;而且Makefile文件本身的写法就很复杂,大型工程下,较难阅读和理解。CMake就是为了解决这些问题的。

CMake本身不执行Make过程,而是根据不同平台的特性,生成对应平台的Makefie,这样我们每个工程只要写一个CMake文件即可了,其余的交给不同平台的处理器来产生不同的Makefile文件即可。而且CMake的语法也更加简答,适合阅读。

  • 20
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值