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工具


🥰创作不易,你的支持对我最大的鼓励🥰
🪐~ 点赞收藏+关注 ~

e3ff0dedf2ee4b4c89ba24e961db3cf4.gif

相关推荐

最近更新

  1. TCP协议是安全的吗?

    2024-05-25 19:42:35       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-05-25 19:42:35       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-05-25 19:42:35       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-05-25 19:42:35       18 阅读

热门阅读

  1. 机柜里面的设备有哪些

    2024-05-25 19:42:35       10 阅读
  2. Go语言标准库之log和三方库zap

    2024-05-25 19:42:35       10 阅读
  3. zookeeper选主之LeaderLatch

    2024-05-25 19:42:35       8 阅读
  4. [前端|vue] v-if 和v-show的区别,为什么功能会类似

    2024-05-25 19:42:35       9 阅读
  5. 学校上课,是耽误我学习了。。

    2024-05-25 19:42:35       11 阅读
  6. Python解析网页

    2024-05-25 19:42:35       10 阅读
  7. 【Kubernetes】Pod无法访问Service域名问题排查

    2024-05-25 19:42:35       11 阅读
  8. Vue3判断变量和对象不为null和undefined

    2024-05-25 19:42:35       9 阅读
  9. android 在 Activity 的 onCreate 中获取View 的宽高

    2024-05-25 19:42:35       8 阅读
  10. 【数组】Leetcode 228. 汇总区间【简单】

    2024-05-25 19:42:35       10 阅读
  11. CentOS防火墙管理及配置

    2024-05-25 19:42:35       9 阅读