[Linux开发工具]项目自动化构建工具-make/Makefile


📙 作者简介 :RO-BERRY
📗 学习方向:致力于C、C++、数据结构、TCP/IP、数据库等等一系列知识
📒 日后方向 : 偏向于CPP开发以及大数据方向,欢迎各位关注,谢谢各位的支持


请添加图片描述


目录

  • 1.背景
  • 2.依赖关系和依赖方法
  • 3.简单使用
  • 4.项目清理
  • 5.三个时间
  • 6.修改访问时间:
  • 7.PHONY修饰目标文件
  • 8.make实现原理


1.背景

  • 会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力
  • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作
  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编
    译,极大的提高了软件开发的效率。
  • make是一个命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,makefile都成为了一种在工程方面的编译方法。
  • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

2.依赖关系和依赖方法

make是一个命令,makefile是一个文件,makefile里面存储的是依赖关系和依赖方法

  • 在makefile里写入如下这种信息:
    在makefile里写入如下这种信息

mybin就是目标文件,mytest.c就是依赖文件
通过依赖方法将依赖文件生成目标文件
依赖关系:确定为什么要帮你。
依赖方法:确定怎么帮你。


3.简单使用

  • Makefile文件编辑好后再输入make
    在这里插入图片描述
  • 即可自动完成文件的编译
    在这里插入图片描述
  • 形成的可执行程序叫做mybin

4.项目清理

我们在实现了make之后再次实现make会出现如下提示
在这里插入图片描述
💧提示说明该可执行程序是最新的,不能再编译了。只要可执行程序的最近修改时间比源文件的最近修改时间要来的新,那么该可执行程序就是最新的,此时make就会出现以上状况。

这个时候我们有两种办法解除提示
1.修改源文件内容
2.清理项目:

在Makefile文件添加如下指令
在这里插入图片描述
输入make clean
在这里插入图片描述
将项目及时清理,以便我们后续的编译

以上就是项目的自动化构建以及项目的自动化清理


这里我们引申一个概念:

1.Makefile和make形成目标文件的时候,默认是从上到下扫描makefile文件的,默认形成的是第一个目标文件
2.默认只形成一个

  • 正常情况下:

输入make执行编译,输入make clean才会执行clean
在这里插入图片描述
在这里插入图片描述

  • 将clean写在make前:

输入make执行清理,输入make mybin才会执行编译
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里,make后再次make的时候会出现已更新到最新,那么make和makefile怎么知道可执行程序是最新的呢?
这个是通过对比时间比出来的,只要可执行程序的最近修改时间比所有源文件的最近修改时间新,说明他就是最新的


5.三个时间

我们来认识一下时间
使用指令

stat 文件

在这里插入图片描述
这里有三个时间

Access是访问时间,即查看该文件的内容的时间;
Modify是文件内容的修改时间;
Change是文件属性的改变时间。
文件=内容+属性

接下来我们来测试一下时间各自的对应操作:

  • 1.我们修改文件的权限属性
    change时间发生了改变其他的事件没有改动
    在这里插入图片描述

  • 2.修改文件内容
    三个时间属性均改变
    在这里插入图片描述

  • 3.查看文件内容
    三个时间均没有改变
    在这里插入图片描述

我们可以看到当多次访问同一个文件的时候,不是每次访问(access)时间都会实时更新,而是过了一段时间后再次访问后才会进行更新。这是因为,时间也是文件的属性,我们要对文件属性进行修改就要到文件所在的磁盘底下对数据进行修改,而访问文件时修改文件,改动属性这三者当中占比最多的一个。如果我们每次访问文件都对文件的访问时间(access)进行实时更新的话,那也就是说在系统当中相当一大部分时间都只在对文件的属性进行更新,而且还是实时更新的,那个假设有多个文件同时访问呢?这务必会对系统的一些效率会产生一定的影响,所以设计者就规定,只有在访问后的一段时间,或者访问到一定的次数之后我们的访问时间才会进行更新。


6.修改访问时间:

我们原来想实现make功能只能更新源文件内容以及实现clean
我们如果每次都要这样是不是会很麻烦?
我们也可直接从修改时间下手,直接通过命令直接修改——修改时间(modify)就要用到我们之前学到的一个命令——touchtouch除了可以创建一个文件外,还可以对一个已成创建的文件进行刷新修改时间(modify)
在这里插入图片描述


7.PHONY修饰目标文件

  • 被".PHONY"修饰后的目标文件成为一个伪目标,修饰后的结果——总是可以被执行。
    在这里插入图片描述
    在这里插入图片描述

这个时候无论执行多少次make都可以了,因为这个时候目标文件被.PHONY修饰后成为伪目标,总是可以被执行。
但是我们一般并不希望把目标文件设置为伪目标,一把比较希望把clear设置为总是被执行的。
这里为什么没有被.PHONY修饰还是可以被执行呢,是因为由-f选项,强制删除。
至于为什么不希望把目标文件设置为伪目标呢?是因为当我们在一个项目里面,有很多个.c文件,当这些文件都生成.o文件之后,需要进行链接,而链接也是有效率的,而对于项目多多少少都可能会出现一些问题在给别的.c文件里面,这个时候需要对部分的.c文件进行debug,也就是对部分.c我文件进行修改,那么一旦我们的目标文件被.PHONY修饰为伪目标之后,在debug之后,所有的.o文件都将重新进行链接,个别两个效率可能还看不出来,如果时成百上千个呢?这个时候效率显现出来的,而如果没有被修饰成伪目标,make之后对修改了的我进行再次编译,链接的时候只需要把修改后的文件重新进行链接就行了,这样链接的整体效率就得到了提高。


8.make实现原理

在上面的依赖关系和依赖方法我们都是一步到位的,但是其实中间是有四个过程的

预处理,编译,汇编,和链接构成的,所有它们的依赖关系和依赖方法应该也是有四个的。

在这里插入图片描述
在这里插入图片描述

上面的文件
mytext依赖 mytext.o
mytext.o依赖 mytext.s
mytext.s依赖 mytext.i
mytext.i依赖 mytext.c

make是如何工作的,在默认的方式下,也就是我们只输入make命令。那么,

  1. make会在当前目录下找名字叫“Makefile”或“makefile”的文件。
  2. 如果找到,它会找文件中的第一个目标文件(target),在上面的例子中,他会找到“mytest”这个文件,并把这个文件作为最终的目标文件。
  3. 如果mytest文件不存在,或是hello所依赖的后面的mytest.o文件的文件修改时间要比mytest这个文件新(可以用 touch 测试),那么,他就会执行后面所定义的命令来生成mytest这个文件。
  4. 如果hello所依赖的mytest.o文件不存在,那么make会在当前文件中找目标为hello.o文件的依赖性,如果找到则再根据那一个规则生成mytest.o文件。(这有点像一个堆栈的过程)
  5. 当然,你的C文件和H文件是存在的啦,于是make会生成 mytest.o 文件,然后再用 mytest.o 文件声明make的终极任务,也就是执行文件mytest了。
  6. 这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
  7. 在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到,那么make就会直接退出,并报错,而对于所定义的命令的错误,或是编译不成功,make根本不理。
  8. make只管文件的依赖性,即,如果在我找了依赖关系之后,冒号后面的文件还是不在,那么对不起,我就不工作啦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/682500.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用LORA微调RoBERTa

模型微调是指在一个已经训练好的模型的基础上,针对特定任务或者特定数据集进行再次训练以提高性能的过程。微调可以在使其适应特定任务时产生显着的结果。 RoBERTa(Robustly optimized BERT approach)是由Facebook AI提出的一种基于Transfor…

python算法之 Dijkstra 算法

文章目录 基本思想:步骤:复杂度:注意事项:代码实现K 站中转内最便宜的航班 Dijkstra 算法是一种用于解决单源最短路径问题的经典算法。该问题的目标是找到从图中的一个固定顶点(称为源点)到图中所有其他顶点…

四、OpenAI之文本生成模型(Text Generation)

文本生成模型 OpenAI的文本生成模型(也叫做生成预训练的转换器(Generative pre-trained transformers)或大语言模型)已经被训练成可以理解自然语言、代码和图片的模型。模型提供文本的输出作为输入的响应。对这些模型的输入内容也被称作“提示词”。设计提示词的本质是你如何对…

ELAdmin 配置定时任务

定义方法 在自己的 Module 中写个要执行的方法。 比如获取微信公众号的 accessToken,每两个小时更新一次。这种的其实使用 Spring 的 Scheduled 更方便些,此处仅为演示。 package me.zhengjie.mp.task;import com.alibaba.fastjson.JSON; import lombo…

java的面向对象编程(oop)——认识泛型

前言&#xff1a; 打好基础&#xff0c;daydayup! 泛型 1&#xff0c;认识泛型&#xff1a; 定义类&#xff0c;接口&#xff0c;方法时&#xff0c;同时声明了一个或多个类型变量&#xff08;例&#xff1a;<E>&#xff09;,称为泛型&#xff0c;泛型接口&#xff0c;泛…

springboot743二手交易平台

springboot743二手交易平台 获取源码——》公主号&#xff1a;计算机专业毕设大全

电子元器件基础2---电容

两个相互靠近的导体&#xff0c;中间夹一层不导电的绝缘介质&#xff0c;这就构成了电容器。当电容器的两个极板之间加上电压时&#xff0c;电容器就会储存电荷。电容器的电容量在数值上等于一个导电极板上的电荷量与两个极板之间的电压之比。电容器的电容量的基本单位是法拉(F…

C语言学习day12:for循环

前面学了dowhile循环&#xff0c;今天我们来学习经常用到的for循环&#xff1a; for循环&#xff1a; 例子&#xff1a; int main() {//int i;for (int i 0; i < 10;i) {printf("%d\n",i);};system("pause");return EXIT_SUCCESS; } 解释&#xff…

SNMP 简单网络管理协议、网络管理

目录 1 网络管理 1.1 网络管理的五大功能 1.2 网络管理的一般模型 1.3 网络管理模型中的主要构件 1.4 被管对象 (Managed Object) 1.5 代理 (agent) 1.6 网络管理协议 1.6.1 简单网络管理协议 SNMP 1.6.2 SNMP 的指导思想 1.6.3 SNMP 的管理站和委托代理 1.6.4 SNMP…

AcWing 122 糖果传递(贪心)

[题目概述] 有 n 个小朋友坐成一圈&#xff0c;每人有 a[i] 个糖果。 每人只能给左右两人传递糖果。 每人每次传递一个糖果代价为 1。 求使所有人获得均等糖果的最小代价。 输入格式 第一行输入一个正整数 n&#xff0c;表示小朋友的个数。 接下来 n 行&#xff0c;每行一个…

2.第一个Electron程序

目录 一、前言二、基本运行结构三、代码详解四、打包 一、前言 原文以及系列文章后续请参考&#xff1a;第一个Electron程序 上一章我们完成了Electron的环境搭建&#xff0c;本章就开始详解如何使用Electron开发一个完整的Electron桌面端程序。 注意开发环境&#xff0c;个…

【王道数据结构】【chapter5树与二叉树】【P158t6】

二叉树按二叉链表形式存储&#xff0c;试编写一个判别二叉树是否是完全二叉树的算法 #include <iostream> #include <queue> typedef struct treenode{char data;struct treenode *left;struct treenode *right; }treenode,*ptreenode;ptreenode buytreenode(char …

2024.2.14

二维数组实现杨辉三角形 #include<stdio.h> #include<string.h> int main(int argc, const char *argv[]) {int n;scanf("%d",&n);int a[n][n];for(int i0;i<n;i){for(int j0;j<i;j){if(j0||ij){ a[i][j]1;}else{a[i][j]a[i-1][j]a[i-1][j-…

docker 2:安装

docker 2&#xff1a;安装 ‍ ubuntu 安装 docker sudo apt install docker.io‍ 把当前用户放进 docker 用户组&#xff0c;避免每次运行 docker 命都要使用 sudo​ 或者 root​ 权限。 sudo usermod -aG docker $USER​id $USER ​看到用户已加入 docker 组 ​​ ‍ …

CSS介绍

本章目标&#xff1a; CSS概述 三种样式表 简单选择器 复合选择器 盒子模型 常用背景样式 浮动 常用文本样式 伪类样式 列表样式 表格样式 定位 一、CSS概述: CSS&#xff1a;cascading style sheets-层叠样式表 专门负责对网页的美化 二、有三种使用方式&…

SpringBoot与虚拟线程,接口吞吐量成倍增加,太爽了!

我们看一下如何在spring-boot中利用loom虚拟线程。 我们将做一些负载测试&#xff0c;看看虚拟线程和普通线程的响应时间如何。 让我们快速设置我们的 Spring Boot 项目。 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http:/…

【开源图床】使用Typora+PicGo+Gitee搭建个人博客图床

准备工作&#xff1a; 首先电脑得提前完成安装如下&#xff1a; 1. nodejs环境(node ,npm):【安装指南】nodejs下载、安装与配置详细教程 2. Picgo:【安装指南】图床神器之Picgo下载、安装与配置详细教程 3. Typora:【安装指南】markdown神器之Typora下载、安装与无限使用详细教…

JavaScript中如何判断数据类型

在JavaScript中&#xff0c;判断数据类型是我们在日常开发中经常会遇到的问题。正确地判断数据类型不仅有助于我们编写出更加健壮的代码&#xff0c;还可以提高程序的可读性和可维护性。本文将为大家介绍几种判断数据类型的方法 使用typeof运算符&#xff1a; typeof运算符可以…

[NSSRound#17 Basic]WEB

1.真签到 看robots.txt 密码先base32再base64得到md5加密的密文&#xff0c;在线解得到密码为Nss hint用16进制转字符串&#xff0c;提示新生赛遇到过 是一个敲击码加密 账号是ctfer,登录之后源码提示在F111n4l.php 要求nss参数若比较等于732339662&#xff0c;但是不能是数…

关于idea无法检测出lombok,导致代码爆红的处理

为啥需要本地安装lombok插件&#xff1f; 编译错误提示&#xff1a;Lombok 使用注解来自动生成代码&#xff0c;这些代码在编译时会由 Lombok 插件进行处理。如果没有安装 Lombok 插件&#xff0c;IDEA 在编译过程中可能会报告错误&#xff0c;因为它无法识别并处理 Lombok 注解…