CMake 和 Makefile 之光速入门

Makefile 由来

在使用编译器进行编译时,例如 g++ main.cpp source1.cpp source2.cpp -o main,将编译三个 cpp 文件,并生成一个 main.exe 的可执行文件。

编译命令非常简单,但这在编译文件非常多时,就会产生问题。该编译命令会将所有文件编译一遍,文件数量非常多时,一次编译就需要很多时间。如果对项目进行修改,一个很小的修改就需要将所有文件编译一遍,包括那些未修改的文件。

为了满足这一需求,我们就需要将编译命令拆开。在上述编译命令中,中间文件是不可见的,一次命令就完成了编译,实际上它整合了许多步骤。

g++ 编译步骤:1、2、3 可以看作是编译阶段,生成一个 .o 文件,4 是一个链接阶段,生成一个可执行文件

  1. 预处理:头文件展开、宏替换等
  2. 编译器:将源文件编译成汇编文件
  3. 汇编器:将汇编文件变成二进制文件
  4. 链接器:对相应的文件进行链接操作

项目修改时,只有一部分文件需要重新编译,另一部分文件并不需要,要重新进行的只有链接的操作,所以只要对修改的文件进行编译,然后进行一次链接即可。

上述的命令可以等价于以下形式:

g++ main.cpp source1.cpp source2.cpp -c
g++ main.o source1.o source2.o -o main

第一条命令生成了一系列已经完成编译的 .o 文件,第二条命令将这些文件进行链接。这时候如果只修改 main.cpp 文件,只需要重新编译 main.cpp 文件即可,不需要再编译其他文件,然后再进行一次链接操作,如下:

g++ main.cpp -c
g++ main.o source1.o source2.o -o main

但是由于上述过程太麻烦,总不能每次编译都要手动去挑选要编译的文件吧,所以就有了 Makefile,将这一过程自动化。

简单的 Makefile 示例

该示例在 Windows 下执行,如果在 Linux 环境下,指令会有所不同

Makefile 文件:

main: main.o source1.o source2.o
	g++ main.o source1.o source2.o -o main
main.o: main.cpp
	g++ main.cpp -c
source1.o: source1.cpp
	g++ source1.cpp -c
source2.o: source2.cpp
	g++ source2.cpp -c

clean:
	del *.o *.exe

大致的意思是 main 文件需要 main.o source1.o source2.o 才可以进行编译,而后续几行又告诉 main.o source1.o source2.o 又需要哪些文件,再执行相应的命令。

clean 命令则是删除指定的文件,例如中间生成的 .o 和最终生成的 .exe 文件。

在执行 make 命令时,程序会自动对比文件更新时间,如果没有更新,则不会重复编译。

# 第一次执行make命令,所有文件都编译了一次
PS C:\makefile> make
g++ main.cpp -c
g++ source1.cpp -c
g++ source2.cpp -c
g++ main.o source1.o source2.o -o main

# 修改main.cpp文件,再次执行make命令
# 此时只对main.cpp进行重新编译
PS C:\makefile> make
g++ main.cpp -c
g++ main.o source1.o source2.o -o main

CMake 由来

虽然 Makefile 已经简化了编译的操作,但还是存在一些问题,从上述的 Makefile 示例文件中可以看到,Makefile 所执行的编译命令是平台相关的,在 Linux 下,就需要再写一份基于 Linux 命令的 Makefile,这对于跨平台的项目来说还是有一些不方便。

所以 CMake 就是为了解决这一问题出现的,CMake 会根据平台,自动生成该平台的 Makefile 文件,于是就解决了 Makefile 跨平台不方便的问题。

CMake 示例

Cmake 入门实战 | HaHack
该博客我觉得已经写的比较详细易懂,内容也比较全,根据自己需求进行阅读即可,本文就不再进行赘述了。

上一篇 下一篇

评论 | 0条评论