当前位置: 首页 > news >正文

make和Makefile

make是一个命令工具,用于读取并执行名为Makefile(makefile)的文件中定义的规则。

Makefile是一个文本文件,它告诉make哪些文件依赖于其他文件,以及如何从这些依赖项生成最终的目标文件。

我们先简单看一下使用make的示例:

首先我们先创建一个源文件,然后在里面简单写一下代码。

然后,我们创建Makefile文件,并在文件中写入:

当我们输入make时,就会执行Makefile中的相应命令:

接下来详细讲解Makefile中写入的各个部分。

上面示例中的test是目标文件,冒号后边是依赖文件列表,依赖文件可以有多个,在上面示例中只有test.c一个,也就是说test文件是依赖test.c文件生成的。

第二行gcc -o test test.c命令是使用gcc编译test.c文件,第二行其实就是依赖方法,我们要生成test目标文件,既需要依赖关系,也需要依赖方法,第二行便是依赖方法,需要注意的是,前边要按table键。同样的,也可以有多个依赖方法,在上面示例中只有一个。

接下来的三行又是一组,首先.PHONY是用来声明一个伪目标的,后边的clean便是伪目标的名称。下一行的clean:同样也是依赖关系,只是比较特殊,依赖文件列表为空,rm -f test则是依赖方法。

在上面的示例中我们可以看到,当我们输入make后,就自己显示相应的依赖方法了,make后边是可以跟相应的目标文件的,最后就会执行依赖方法中的指令,当我们要重复多次输入某一指令时,就可以用make来方便自己。当make后边不加目标文件时,默认就是第一个目标文件,如上面示例中make后执行的是gcc指令。

关于.PHONY的具体作用,我们先演示效果,再讲解:

上面示例时:

当加上.PHONY:test并删除.PHONY:clean时:

可以看到,对于test来说,没加上.PHONY时,make是不能被多次执行的,而加上后是可以被多次执行的,.PHONY的作用就是让目标文件对应的方法总是被执行,但是,clean为什么在两次执行过程中都可以多次被执行呢?这个跟时间有关系,没加.PHONY时,多次使用make会提示已经是最新的了,所以它不会再次编译,而rm指令由于与时间无关,所以每次都可以被执行。

我们再来看一个演示:

当前还是不能执行多次make,然后我们再进入到test.c中,并对其内容进行修改,再次执行make时发现可以了。

为什么有时候需要重新编译,但是有时候又不需要呢?

答案是:根据对比文件的Mtime来确定的。

通过stat指令可以查看Mtime:

可以看到有三个时间,即Access、Modify和Change,Access 是文件被访问的时间,Modify是文件内容最近被修改的时间,Change是文件属性最近被修改的时间。在上面例子中,我们在test.c文件中加了一条语句,所以修改了其Mtime,每一次编译生成可执行文件后,也会有一个Mtime,这个时间是比源文件的时间晚的,但是当我们修改文件后,其时间比原来生成的可执行文件的时间晚,所以就又可以重新编译了,即通过比较Mtime来确定是否要重新编译。

我们再来看下一个示例:

在这个示例中,test依赖于test.o,而test.o又依赖于test.s,而test.s依赖于test.i,test.i依赖于test.c,test.c是存在的,所以找到后执行依赖方法,然后逐步递归构建test,也就是说,make解释Makefile时是会自动推导的,一直推导,推导过程不执行依赖方法,直到推导到有依赖文件存在,然后再逆向执行所有的依赖方法。

其他:

在Makefile中,%是通配符,%.o:%.c则是表示任何.c文件都可以生成对应的.o文件,即将当前目录下的所有.c文件都展开在依赖列表中。$<则是表示将依赖文件一个一个交给gcc -c选项,形成同名的.o文件。

下一个示例:

Makefile中也可以定义变量,上面的bin和src便是变量,$(bin)就是test,$(src)就是test.o,$^表示所有的依赖文件列表,这里指的就是test.o,$@代表目标文件,也就是test。

其实Makefile就是指令,执行make后会执行Makefile中写入的相应指令,如果我们不想让这些指令回显,可以在前面加上@:

另外,注释是用#。

http://www.lryc.cn/news/454908.html

相关文章:

  • 【数学分析笔记】第4章第4节 复合函数求导法则及其应用(2)
  • 【预备理论知识——2】深度学习:线性代数概述
  • 【目标检测】yolo的三种数据集格式
  • 数据分析案例-机器学习工程师薪资数据可视化分析
  • Django连接Dify、ChatGPT4o并计算tokens数量方法
  • 面试系列-淘天提前批面试
  • 计算机中科学中有哪些空间换时间的操作??
  • Mac安装Manim并运行
  • leetcode58:最后一个单词的长度
  • 18448 最小生成树
  • 前端工程化 - Vue
  • 使用 NVIDIA H100 上的 Azure 机密计算释放隐私保护 AI 的潜力
  • 目标检测与图像分类:有什么区别?各自的使用场景是什么?
  • Lua 数据类型
  • 复现文章:R语言复现文章画图
  • 东方仙盟——软件终端架构思维———未来之窗行业应用跨平台架构
  • 支持向量机(SVM)基础教程
  • Python小示例——质地不均匀的硬币概率统计
  • 京东web 京东e卡绑定 第二部分分析
  • 【数据结构与算法】Greedy Algorithm
  • Ubuntu22.04之mpv播放器高频快捷键(二百七十)
  • 新闻推荐系统:Spring Boot的可扩展性
  • 目录工具类 - C#小函数类推荐
  • 速盾:如何判断高防服务器的防御是否真实?
  • MySQL连接查询:联合查询
  • Gitea 数据迁移
  • MySQL 绪论
  • 什么是 HTTP Get + Preflight 请求
  • (JAVA)开始熟悉 “二叉树” 的数据结构
  • 【Linux】Linux命令与操作详解(一)文件管理(文件命令)、用户与用户组管理(创建、删除用户/组)