Makefile笔记
前言
对于源代码包,我们只有编译才能在系统上运行。而Linux下的编译器有gcc、g++,随着源文件的增加,直接用gcc/g++命令的方式显得效率低下,人们开始用Makefile来进行编译。
一、Makefile简介
- makefile关系到了整个工程的编译规则。一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作,因为makefile就像一个Shell脚本一样,其中也可以执行操作系统的命令。
- makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
- make(例如CMake)命令执行时,需要一个 Makefile 文件,以告诉make命令需要怎么样的去编译和链接程序。CMake是开源、跨平台的构建工具,可以让我们通过编写简单的配置文件去生成本地的Makefile,这个配置文件是独立于运行平台和编译器的,这样就不用亲自去编写Makefile了,而且配置文件可以直接拿到其它平台上使用,无需修改,非常方便。
二、关于程序的编译和链接
1.编译
- C 语言代码由固定的词汇按照固定的格式组织起来,简单直观,程序员容易识别和理解,但是对于 CPU,C 语言代码就是天书,根本不认识,CPU 只认识几百个二进制形式的指令。这就需要一个工具,将 C 语言代码转换成 CPU 能够识别的二进制指令,也就是将代码加工成.exe 程序的格式,这个工具是一个特殊的软件,叫做编译器(Compiler);编译器能够识别代码中的词汇、句子以及各种特定的格式,并将它们转换成计算机能够识别的二进制形式,这个过程称为编译(Compile)。
- C 语言的编译器有很多种,不同的平台下有不同的编译器,例如:
- Windows 下常用的是微软开发的Visual C++, 它被集成在 Visual Studio 中,一般不单独使用;
- Linux 下常用的是GUN 组织开发的 GCC,很多 Linux 发行版都自带 GCC;
- Mac 下常用的是LLVM/Clang,它被集成在 Xcode 中 (Xcode 以前集成的是 GCC,后来由于 GCC 的不配合才改为 LLVM/Clang,LLVM/Clang 的性能比 GCC更加强大) 。
- 编译器能检查你的语法,可以 100% 保证你的代码从语法上讲是正确的,因为哪怕有一点小小的错误,编译也不能通过。
2.链接
- C 语言代码经过编译以后,并没有生成最终的可执行文件(.exe 文件),而是生成也一种做目标文件(Object File)的中间文件(或者说临时文件)。目标文件也是二进制形式的,它和可执行文件的格式是一样的。对于 Visual C++,目标文件的后缀是.obj;对于 GCC,目标文件的后缀是.o。
- 目标文件经过链接(Link)以后才能变成可执行文件。既然目标文件和可执行文件的格式是一样的,为什么还要再链接一次呢,直接作为可执文件不行吗?
不行!因为编译只是将我们写的代码变成了二进制形式,它还要需要和系统组件(比如标准库、动态链接库等)结合起来,这些组件都是程序运行所必须的。 - 链接(Link)其实就是一个 “ 打包” 的过程,它将所有二进制形式的目标文件和系统组件合成一个可执行文件。完成链接的过程也需要一个特殊的软件,叫做链接器(Linker)
- 随着我们学习的深入,我们编写的代码越来越多,最终需要将它们分散到多个源文件中, 编译器每次只能编译一个源文件,生成一个目标文件,这个时候,链接器除了将目标文件和系统组件组合起来,还要将编译器生成的多个目标文件组合起来。
- 编译是针对一个源文件的,有多少个源文件就要编译多少次,就会生成多少个目标文件。
总结:
不管我们编写的代码有多么简单,都必须经过【编译 → 链接】 的过程才能生成可执行文件:
- 编译就是将我们编写的源代码 “翻译” 成计算机可以识别的二进制格式,它们以目标文件的形式存在;
- 链接就是一个 “打包” 的过程,它将所有的目标文件以及系统组件合成一个可执行文件
总结
CMake是用来生成makefile文件的,而makefile文件是用来自动化编译源代码(.c)的脚本