🪐🪐🪐欢迎来到程序员餐厅💫💫💫
主厨:邪王真眼
主厨的主页:Chef's blog
所属专栏:青果大战linux
总有光环在陨落,总有新星在闪烁
make基本概念
make是一个在Linux下广泛使用的自动化构建工具,它可以根据一个Makefile文件中的指令来自动执行编译、链接等操作,从而生成一个可执行文件或者库文件。通常情况下,使用make工具可以极大地简化代码的编译和构建过程。
会不会写 makefile ,从一个侧面说明了一个人是否具备完成大型工程的能力 ,一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile 定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作 makefile 带来的好处就是 ------" 自动化编译 " ,一旦写好,只需要一个 make 命令,整个工程完全自动编译,极大的提高了软件开发的效率。
makefile的使用
创建makefile
我们现在要对test.c文件进行编译链接其文件内容如下
#include <stdio.h>
int main()
{
printf("Hello,Makefile");
return 0;
}
接着我们通过vim创建一个文件名是makefile或Mikefile的文件
并在里面输入指令
test2:test2.c
gcc -o test2 test2.c
在这之后,我们直接输入make,就等价于把gcc -o test test.c
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ make
gcc -o test2 test2.c
报错问题解决
这时候,你的那里可能报各种错误,别急,我们现在来分析(如果还不行可以评论区留言)
-
保存文件时出现
E212: Can't open file for writing
Press ENTER or type command to continue
这说明你没有写入的权限,可能是你自己之前不小心修改了文件的权限,有或许这是别人提供给你的只读文件
解决方法:
- 通过su切换为root,或通过sudo把自己提权为root
- 使用chmod修改文件的权限
对于权限知识不清楚的可以看看这篇博客回忆一下
-
使用vim修改文件报错
E37: No write since last change (add ! to override)
解决方法:
使用命令:w!强制存盘即可,在vim底行模式下输入:w!
-
运行make时错误
makefile:2: *** missing separator. Stop.
解决方法:
注意我们的依赖方法开头是一个tab键,不是四个空格,若你有自动缩进那就先把空格删了再按缩进
最后记住依赖关系输入的':'是英文的不是中文的
工作原理
基本概念
我们在makefile中输入了两行代码
第一行:文件名+':'+文件名 他是依赖关系,左边的文件是目标文件,右边的文件叫做依赖关系列表,它可以是多个文件。
第二行是依赖方法:
- 依赖关系
1.是指在编译程序时,一个文件(如源文件或目标文件)需要另一个文件(如头文件或其他源文件)的内容才能正确编译的关系。在编译过程中,如果一个文件发生改变,那么它所依赖的文件也需要重新编译。
2.依赖关系可以形成层序结构,即a依赖b,而b又依赖c,c依赖d,当执行a的指令时,如果发现b不存在,就会通过bc之间的依赖方法生成b,以此类推。
- 依赖方法
1.它是指通过一些手段来确定依赖关系的方法。比如,在Makefile文件中使用伪目标和依赖文件列表来定义编译规则。
2.依赖方法可以包含多条命令,每条命令用回车分隔
- 目标文件
make 命令要生成的文件,通常是可执行程序、中间目标文件、动态链接库或静态链接库等输出文件。
- 依赖文件列表
1.是指一个文件所依赖的其他文件列表。在Makefile文件中,可以使用依赖文件列表来定义编译规则,确保所有依赖文件都已经被编译过,才会编译当前的目标文件。
2.依赖文件列表可以包含多个文件,用空格分隔
再了解了这些基础知识后,我们再学习一个新指令 make clean
vim打开makefile,添加内容
1: makefile+ ⮀ ⮂⮂ buffers
1 test2:test2.c
2 gcc -o test2 test2.c
3 clean:
4 rm -f test2
第三行是clean的依赖关系,可以发现:后面什么都没有,表示clean不依赖任何文件列表
第四行是clean的实现方法
我们再命令行输入make clean,可以看到依赖方法被执行了
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ make clean
rm -f test2
再ll一下当前文件目录,发现之前的test2可执行文件确实不见了
提出问题
,为什么执行第一个生成可执行文件的指令直接使用make就可以,但是执行删除可执行文件需要输入make clean才能执行呢?
当命令行中输入的make后面不接任何内容时,则会在makefile从上往下查找,找到第一个依赖关系进行执行
- 演示:
我们先创建test2
然后修改makefile
1 clean:
2 rm -f test2
3 test2:test2.c
4 gcc -o test2 test2.
执行make
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ make
rm -f test2
makefile的进阶玩法
1.文件名替代
test2:test2.c
gcc -o $@ $^
首先,makefile中,指令内部的目标文件可以用#代替,依赖文件列表可以用^代替:
2,创建变量
在makefile中,是可以定义变量的,只需要用一个等号进行赋值即可
x=test2.c
y=test2
x的值就是test2,y的值就是test,想要使用这个变量,就在对应的地方以(变量名)的形式代替即可,即(变量名)等价于原文件
x=test2.c
y=test2
$(y):$(x)
gcc -o $(y) $(x)
clean:
rm -f $(y)
3.PHONY用法
- 提出问题:
我们可以看到使用gcc多次编译同一个文件是没有任何限制的
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ gcc test2.c -o test
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ gcc test2.c -o test
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ gcc test2.c -o test
但是我们用make呢?
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ make
gcc -o test2 test2.c
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ make
make: `test2' is up to date.
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ make
make: `test2' is up to date.
不难发现,第一次我们make成功,但是之后的make都被拒绝了,这是因为make在执行编译之前会先检查源文件是否被修改,如果没被修改,那么再一次进行编译是没有意义的(因为前后生成的可执行文件一样),那他就会拒绝执行
- 那如果我就想让它执行呢?
PHONY在Makefile中是一个非常有用的特殊目标。当make执行到PHONY目标时,它会无条件执行该目标下定义的命令,而不会检查是否有同名的文件在。
因此我们就可以对mybin使用这个PHONY,让它强制执行命令,不论当前目录下有没有mybin。
修饰语法:
.PHONY:xxx
xxx是一个依赖文件名,此时xxx应的命令就会被强制执行。
.PHONY:mybin
mybin:test.c
gcc -o mybin test.c
此时mybin每次都会强制执行命令,不论之前是否存在mybin文件了。
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ make
gcc -o test2 test2.c
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ make
gcc -o test2 test2.c
[qingguo@iZf8z6fhz4n89uhtqx9ey6Z project3]$ make
gcc -o test2 test2.c
4.PHONY原理
phony :伪造的,假的。
在Makefile中,
.PHONY后面的target通常是的是一个伪造的文件, 而不是真实存在的文件,我们称呼他为伪目标
- 伪目标意思是这个目标本身不代表一个文件,执行这个目标不是为了得到某个文件或东西,而是单纯为了执行这个目标下面的命令。
- 伪目标一般都没有依赖,因为执行伪目标就是为了执行目标下面的命令。既然一定要执行命令了那就不必加依赖,因为不加依赖意思就是无条件执行。
- 伪目标可以直接写,不影响使用;但是有时候为了明确声明这个目标是伪目标会在伪目标的前面用.PHONY来明确声明它是伪目标
- 优点:
- 可以防止在Makefile中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,
- 提高执行makefile时的效率。
比如伪目标clean,如果当前目录下刚好有一个叫做clean的文件,那么clean作为一个目标文件,由于已经出现了目标文件,那么依赖方法就不会执行,就像上面的创建可执行文件一样被禁止执行。可是我们用PHONY声明clean作为一个伪目标,clean的依赖方法就会被强制执行了。
clean:
rm -rf *.o
make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。
今天学习了make、makefile的作用,PHONY的使用以及原理,make报错的修复,记得好好复习总结,下一期我们来学习gbd工具