C/C++代码变成可执行程序的过程:
1、把程序员所编写的C代码变成预处理文件,编译.i结尾的预处理文件 预处理
gcc -E hello.c -o hello.i
2、把预处理文件翻译成.s结尾的汇编文件 编译
gcc- s hello.i --> hello.s
3、把.s结尾的汇编文件编译成.o结尾的目标文件 汇编
gcc -c hello.s --> hello.o
4、把若干个.o结尾的目标文件合并成可执行文件 链接
gcc a.o b.o c.o …. -o hello
什么是Makefile脚本:
Makefile脚本集合了程序的编译指令的文件,make是一个命令工具,当执行make命令时,它会自动读取Makefile中的编译指令并执行,会自动完成整个项目的自动化编译工作。
为什么需要Makefile脚本:
项目中如果有很多.c文件,它们的编译指令会有很多,需要编译的时间比较长,依赖关系非常复杂。
当项目中的.h、.c文件被修改时,我们无法人为的分辨出哪些文件需要重新编译,只能全部重新编译一下,但这项操作非常耗时
所以使用Makefile脚本编译项目:
1、节约时间
2、记录文件之间的依赖关系
3、自动化执行编译过程
Makefile脚本的原理:
Makefile脚本的原理就是基于文件的最后修改时间,被依赖文件的最后修改时间晚于目标文件,该文件就需要重新编译。
hello.c > hello.c
gcc -c hello.c
hello.h > hello.c
gcc -c hello.c
Makefile脚本的格式:
有若干个编译目标组成,它类似C语言中的函数,就是若干个编译指令组成的编译模块,默认只执行排在第一个的编译目标,也叫入口目标。
target … : prerequisites …
command
….
….
target:编译目标,它如果不存在,或者早于它的依赖文件,那么就执行下面的编译指令
prerequisites:被依赖的编译目标,相当于C语言中的函数调用
commamd:编译指令
在Makefile脚本中可以使用变量:
变量名=value 定义变量并给变量赋值初值
$(变量名) 使用变量名,获取出变量的值。
常用的变量名:
CC=编译器
STD=语法标准
FLAG=检查标准,-Wall,-Werror
TARGE=最终可执行文件的名字
OBJECT=所有的目标文件名
负责清理的编译目标文件:
该编译目标一般负责删除目标文件、头文件的编译结果、可执行文件。
一般它不会被依赖,也就是不会被执行,而是当需要时,在命令行通过make 目标名,手动执行。
什么时候需要它执行:
1、刚修改的内容,并没有发生变化,有可能是依赖有问题,代码并没有重新编译,执行它就可以删除所有目标文件、可执行文件,重新编译。
2、更换了执行平台后,那么之前编译出的目标文件就全部不能再继续使用。
3、项目最终上线时,会把所有的编译结果删除,重新编译。
clean:
rm -rf $(OBJECT)$(ARGE)
rm -rf .h .gch
通用的Makefie脚本:
CC=gcc
STD=-std=gnu89
FLAG=-Wall -Werror
TARGE=最终可执行文件的名字
OBJECT=所有的目标文件名
all:$(OBJECT)
$(CC) $(OBJECT) -o $(TARGE)
%.o:%.c
$(CC) $(STD) $(FLAG) $<
缺点:依赖规则无法描述完整
建议:
FLAG=-Wall -Werror
TARGE=manager
OBJECT=main.o tools.o manager_user.o
$(TARGE):$(OBJECT)
$(CC) $(OBJECT) -o $(TARGE)
main.o:%.o:%.c manager_user.h
$(CC) $(STD) $(FLAG) -c $<
tools.o:%.o:%.c tools.c tools.h
$(CC) $(STD) $(FLAG) -c $<
manager_user.o:%.o:%.c manager_user.c manager_user.h tools.h
$(CC) $(STD) $(FLAG) -c $<
clean:
rm -rf $(OBJECT) $(TARGE)
rm -rf .h.gch
常见的面试问题:
为什么使用Makefile?
Makefile脚本中有哪些内容?
简单介绍下Makefile?
1、使用Makefile的好处
节约编译时间
记录文件的依赖关系
自动执行编译过程
2、Maekfile的原理
在命令执行make命令(make是安装在操作系统上的读取、解析、执行Makefile的和、工具)。
make命令会读取当前目录下的makefile、Makefile文件中的内容,解析里面的编译目标。
根据依赖关系和编译目标的最后修改时间判断是否需要执行编译命令,以达到节约编译时间的目的。
3、Makefile脚本中有哪些内容
变量
入口目标
被依赖的目标
伪目标
注释
系统命令
4、要注意的问题
必须使用Tab键进行缩进,不能使用空格
5、能手写一份通用的模板