详解自动化编译命令make及Makefile文件
编译Android或Linux源码时,我们会发现串口输入命令make后就会开始自动编译。make命令通过一个称为makefile的文件来完成并自动维护编译工作。输入make指令后将自动寻找当前目录下的makefile(或Makefile)文件并解析它完成编译工作,故我们需要重点理解makefile文件的语法。
参考视频:Linux 的make自动化编译和通用makefile_哔哩哔哩_bilibili
编译Android或Linux源码时,我们会发现串口输入命令make后就会开始自动编译。
make命令通过一个称为makefile的文件来完成并自动维护编译工作。输入make指令后将自动寻找当前目录下的makefile(或Makefile)文件并解析它完成编译工作,故我们需要重点理解makefile文件的语法。
目录
一、C文件单编命令
命令:gcc [options] [filenames]
其中options就是编译器所需要的参数,filenames给出相关的文件名称。
-c,只编译,不链接成为可执行文件,编译器只是由输入的.c等源代码文件生成.o为后缀的目标文件,通常用于编译不包含主程序的子程序文件。
-o output_filename,确定输出文件的名称为output_filename,同时这个名称不能和源文件同名。如果不给出这个选项,gcc就给出预设的可执行文件a.out。
-g,产生符号调试工具(GNU的gdb)所必要的符号资讯,要想对源代码进行调试,我们就必须加入这个选项。
-O,对程序进行优化编译、链接,采用这个选项,整个源代码会在编译、链接过程中进行优化处理,这样产生的可执行文件的执行效率可以提高,但是,编译、链接的速度就相应地要慢一些。
-O2,比-O更好的优化编译、链接,当然整个编译、链接过程会更慢。
-Idirname,将dirname所指出的目录加入到程序头文件目录列表中,是在预编译过程中使用的参数。C程序中的头文件包含两种情况∶
A)#include <myinc.h>
B)#include “myinc.h”
其中,A类使用尖括号(< >),B类使用双引号(“ ”)。对于A类,预处理程序cpp在系统预设包含文件目录(如/usr/include)中搜寻相应的文件,而B类,预处理程序在目标文件的文件夹内搜索相应文件。
-v gcc执行时执行的详细过程,gcc及其相关程序的版本号
举例:
gcc -c main.c -o main.o //编译main.c生成可执行文件main.o
gcc main.o add.o subtract.o -o main //将多个文件生成一个目标可执行文件main
二、makefile基本语法


举例:

三、make是如何工作的
1、make会在当前目录下找名字叫“Makefile"或“makefile”
2、如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“main”这个文件,并把这个文件作为最终的目标文件。
3、如果main文件不存在,或是main所依赖的后面的.o文件的文件修改时间要比main这个文件新,那么,他就会执行后面所定义的命令来生成main这个文件。
4、如果main所依赖的.o文件也存在,那么make会在当前文件中找目标为.o文件的依赖性,如果找到则再根据那一个规则生成.o文件。
5、当然,你的C文件和H文件是存在的啦,于是make会生成.o文件,然后再用.o文件make的终极任务,也就是执行文件main了。
注:如果DEPENDENCIES中有一个或多个文件更新的话COMMAND就要执行,这就是Makefile最核心的内容。
四、编写一个简单的makefile文件

释义:
1、最终生成的可执行目标文件:main
2、生成main所需要的其他文件:main.o stu.o
3、编译main.o所需要的文件:main.c stu.h
4、编译stu.o所需要的文件:stu.c stu.h
五、makefile使用伪目标
- make命令不带参数时从第一目标文件开始执行,将依次执行生成第一目标文件所需要的目标文件。
- make命令可以带参数,参数为makefile的任意目标文件,可单独执行生成该目标文件所需的指令。
- make命令的参数可以是伪目标文件,伪目标文件指执行该目标文件的指令不生成该目标文件,仅用于执行单个指令使用。
举例:

释义:
- .PHONY作用是声明clean是伪目标。
- 输入make clean将执行命令:rm -f main.o stu.o main
- 不声明clean为伪目标(即没有.PHONY:clean这行)是可以的,但是当目录下有clean文件时可能会出现问题,make会报如下错误:

- 其他常用伪目标:

六、make自动化变量

使用变量及自动化变量可优化makefile文件为:

七、make自动推导
- GNU的make很强大,它可以自动推导文件以及文件依赖关系后面的命令,于是我们就没必要去在每一个[.0]文件后都写上类似的命令,因为,我们的make会自动识别,并自己推导命令。
- 只要make看到一个[.0]文件,它就会自动的把[.c]文件加在依赖关系中,如果make找到一个whatever.o,那么whatever.c,就会是whatever.o的依赖文件。并gcc -c whatever.c也会被推导出来。
使用make自动推导可优化makefile文件为:

使用变量object继续优化为:

八、makefile中常见函数

使用函数查找所有[.c]文件并替换为[.o]文件可进一步优化makefile文件:
或
当查找的文件在多级子目录下呢?可以使用find命令查找到:

九、使用变量修改自动推导的gcc编译命令
以上优化后想要去掉编译指令:gcc $^ -0 $@ -llist
可以重定义CC变量,修改后为:

十、通用makefile的其他写法

释义:
shell ls -d */ 可以列出所有二级目录
SUBDIR记录二级目录名;ROOTOBJ记录所有一级目录下的[.o]文件;SUBOBJ记录所有二级目录下的[.o]文件
.c.o: 表示将所有[.c]编译成[.o],其指令直接看执行结果理解:
@D:目标目录;@F:目标文件;<F:第一依赖文件名

更多推荐




所有评论(0)