本文将会向您介绍make/makefile的原理与操作
首先先向您介绍linux的编译器gcc的编译过程:
预处理
预处理功能主要包括宏定义,文件包含,条件编译,去注释等。
预处理指令是以#号开头的代码行。
实例: gcc –E hello.c –o hello.i
选项“-E”,该选项的作用是让 gcc 在预处理结束后停止编译过程。
选项“-o”是指目标文件,“.i”文件为已经过预处理的C原始程序
编译(生成机器可识别代码)
在这个阶段中,gcc 首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,gcc 把代码翻译成汇编语言。
用户可以使用“-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码
gcc –S hello.i –o hello.s
汇编
汇编阶段是把编译阶段生成的“.s”文件转成目标文件
读者在此可使用选项“-c”就可看到汇编代码已转化为“.o”的二进制目标代码了
实例: gcc –c hello.s –o hello.o
链接
在成功编译之后,就进入了链接阶段。
实例: gcc hello.o –o hello
一个工程里的源文件不计数,其按类型,功能,模块,分别放在若干目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于更复杂的功能操作
makefile带来的好处好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
make是如何工作的,在默认的方式下,也就是我们只输入make命令。
首先你应该有一个.c的源文件
然后我们再touch一个名为Makefile的文件
在文件中写入以下代码
最后我们进入底行模式wq保存退出
我们先操作一番看一下结果
输入make
查看生成的可执行程序
这时就会多出来一个我们命名的可执行程序
然后再./mybin运行
最后输入make clean
这时我们的可执行程序就被清理掉了
解析:
mybin:code.c
依赖关系: 上面的文件mybin,它依赖code.c
gcc code.c - o mybin
使用gcc将名为code.c的c源文件编译成为一个名为mybin的可执行文件
.PHONY:clean
声明一个名为"clean"的伪目标。通过声明为伪目标,可以告诉Make工具,"clean"目标不对应任何实际的文件,而是用于执行清理操作
mybin:code.c
@gcc code.c -o mybin
@echo "编译成功..."
.PHONY:clean
clean:
@rm -f mybin
@echo "清理成功..."
make会在当前目录下找名字叫“Makefile”或“makefile”的文件
然后用vim打开Makefile文件
//变量话处理
cc=gcc
src=code.c
target=mybin
target:$(src)
@$(cc) $(src) -o $(target)
@echo "编译成功..."
PHONY:clean
clean:
@rm -f $(target)
@echo "清理成功..."
我们也可以用$ ^代替冒号右侧的源文件,用$@冒号左侧的目标文件
mybin:code.o
gcc code.o -o mybin
code.o:code.s
gcc -c code.s -o code.o
code.s:code.i
gcc -S code.i -o code.s
code.i:code.c
gcc -E code.c -o code.i
.PHONY:clean
clean:
rm -f mybin code.o code.s code.i
这里就对应本文刚开始的引入gcc的选项
如果hello所依赖的hello.o文件不存在,那么make会在当前文件中找目标为hello.o文件的依赖性,如果找到则再根据那一个规则生成hello.o文件。(这有点像一个堆栈的过程)
当我们make的时候,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文
件。在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错。
当我们重复make的时候,makefile识别到目前的文件是没有作修改的,因此不用重复编译
而
我们不能重复make的原因是
Access该文件的最近访问时间
Modified对内容进行修改的时间
change对文件的属性修改的时间
我们可以用stat命令获取文件的ACM时间
可以观察到每次make后,可执行程序mybin的ACM时间就被更新了,且晚于源文件的时间
因此再次make的时候,操作系统会提醒我们mybin是最新的
当我们重复的make clean的时候,这件事却被允许了,why?
.PHONY是一个特殊的目标。它用于定义一个伪目标(即不存在对应的文件),并且告诉make工具这个目标不需要检查依赖关系,总是需要执行
本文的分享就到这里啦,如果本文存在疏漏或错误的地方还请您能够指出!