Linux项目自动化构建工具-make/Makefile

🪐🪐🪐欢迎来到程序员餐厅💫💫💫
主厨:邪王真眼
主厨的主页: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

这说明你没有写入的权限,可能是你自己之前不小心修改了文件的权限,有或许这是别人提供给你的只读文件

解决方法:

  1. 通过su切换为root,或通过sudo把自己提权为root
  2. 使用chmod修改文件的权限

对于权限知识不清楚的可以看看这篇博客回忆一下

Linux的权限概念及修改


  • 使用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通常是的是一个伪造的文件, 而不是真实存在的文件,我们称呼他为伪目标

  1. 伪目标意思是这个目标本身不代表一个文件,执行这个目标不是为了得到某个文件或东西,而是单纯为了执行这个目标下面的命令。
  2. 伪目标一般都没有依赖,因为执行伪目标就是为了执行目标下面的命令。既然一定要执行命令了那就不必加依赖,因为不加依赖意思就是无条件执行。
  3. 伪目标可以直接写,不影响使用;但是有时候为了明确声明这个目标是伪目标会在伪目标的前面用.PHONY来明确声明它是伪目标
  • 优点:
  1. 可以防止在Makefile中定义的只执行命令的目标和工作目录下的实际文件出现名字冲突,
  2. 提高执行makefile时的效率。

比如伪目标clean,如果当前目录下刚好有一个叫做clean的文件,那么clean作为一个目标文件,由于已经出现了目标文件,那么依赖方法就不会执行,就像上面的创建可执行文件一样被禁止执行。可是我们用PHONY声明clean作为一个伪目标,clean的依赖方法就会被强制执行了。

clean:
    rm -rf *.o

make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。


今天学习了make、makefile的作用,PHONY的使用以及原理,make报错的修复,记得好好复习总结,下一期我们来学习gbd工具


🥰创作不易,你的支持对我最大的鼓励🥰
🪐**~ 点赞收藏+关注 ~**
相关推荐
热爱嵌入式的小许11 分钟前
Linux基础项目开发1:量产工具——显示系统
linux·运维·服务器·韦东山量产工具
韩楚风4 小时前
【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
linux·服务器·性能优化·架构·gnu
陈苏同学4 小时前
4. 将pycharm本地项目同步到(Linux)服务器上——深度学习·科研实践·从0到1
linux·服务器·ide·人工智能·python·深度学习·pycharm
Ambition_LAO4 小时前
解决:进入 WSL(Windows Subsystem for Linux)以及将 PyCharm 2024 连接到 WSL
linux·pycharm
Pythonliu74 小时前
茴香豆 + Qwen-7B-Chat-Int8
linux·运维·服务器
你疯了抱抱我4 小时前
【RockyLinux 9.4】安装 NVIDIA 驱动,改变分辨率,避坑版本。(CentOS 系列也能用)
linux·运维·centos
追风赶月、4 小时前
【Linux】进程地址空间(初步了解)
linux
栎栎学编程4 小时前
Linux中环境变量
linux
我是哈哈hh5 小时前
专题十_穷举vs暴搜vs深搜vs回溯vs剪枝_二叉树的深度优先搜索_算法专题详细总结
服务器·数据结构·c++·算法·机器学习·深度优先·剪枝
郭二哈5 小时前
C++——模板进阶、继承
java·服务器·c++