前言
本文将会向您介绍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定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于更复杂的功能操作
makefile带来的好处好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率
make是如何工作的,在默认的方式下,也就是我们只输入make命令。
首先你应该有一个.c的源文件
然后我们再touch一个名为Makefile的文件
在文件中写入以下代码
最后我们进入底行模式wq保存退出
我们先操作一番看一下结果
输入make
查看生成的可执行程序
这时就会多出来一个我们命名的可执行程序
然后再./mybin运行
最后输入make clean
这时我们的可执行程序就被清理掉了
解析:
mybin:code.c
依赖关系: 上面的文件mybin,它依赖code.c
tips:依赖关系是指一个程序或模块需要使用另一个程序或模块的功能或资源。依赖关系可以是源代码级别的依赖,也可以是编译时或运行时的依赖。
gcc code.c - o mybin
使用gcc将名为code.c的c源文件编译成为一个名为mybin的可执行文件
如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“mybin”这个文件,并把这个文件作为最终的目标文件。
.PHONY:clean
声明一个名为"clean"的伪目标。通过声明为伪目标,可以告诉Make工具,"clean"目标不对应任何实际的文件,而是用于执行清理操作
clean目标用于删除生成的可执行文件。当运行"make clean"命令时,Make工具将会执行clean目标下的命令,即rm -f mybin,来删除"mybin"文件 tips:在Makefile中,.PHONY是一个特殊的目标,用于声明一个伪目标,伪目标是一种特殊的目标,它并不对应任何实际的文件,而是用于定义一些特殊的操作或命令。
当在Makefile中使用@符号时,后面的命令将不会被打印到标准输出中。这样可以隐藏命令的执行过程,使输出更加简洁。
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识别到目前的文件是没有作修改的,因此不用重复编译
而
文件的ACM时间
我们不能重复make的原因是
Access该文件的最近访问时间
Modified对内容进行修改的时间
change对文件的属性修改的时间
我们可以用stat命令获取文件的ACM时间
可以观察到每次make后,可执行程序mybin的ACM时间就被更新了,且晚于源文件的时间
因此再次make的时候,操作系统会提醒我们mybin是最新的
当我们重复的make clean的时候,这件事却被允许了,why?
.PHONY是一个特殊的目标。它用于定义一个伪目标(即不存在对应的文件),并且告诉make工具这个目标不需要检查依赖关系,总是需要执行
小结
本文的分享就到这里啦,如果本文存在疏漏或错误的地方还请您能够指出!