【Linux】Make/Makefile



这个3/4行的语法和1/2行是一样的。也是依赖关系和依赖方法。

make命令扫描makefile文件时,从上向下扫描,默认形成一个目标文件。
指定make clean的时候才回去执行对应的清除。
为什么要给我们的clean.PHONY:clean声明它是伪目标呢?
PHONY类似一种建议性的关键字。
伪目标,表示对应的依赖方法和依赖关系总是被执行。
什么叫不被执行?
我们上面的这组可执行程序没有被修饰,所以我们如果make完又make,是不会执行的。但如果用为目标修饰了,就会发现也可以执行。

所以我们一般可执行程序不用伪目标修饰,因为如果代码没有更新,没有必要再次编译。
默认老代码不作重新编译。
make怎么知道bin和.c的新旧?

Linux下每一个文件有三个相关时间,分别是Access/Modify/Change
文件=内容+属性
cat打印内容,ls打印属性
如果我们只改文件内容,那么Modify时间被修改。
如果我们只改文件属性,那么Change时间被修改。
如果不修改,单纯查看,Access时间被更新。

可以看到,这样我们的Modfiy时间就被改了。
而且文件属性页同步变化了,所以时间也改了:

大小和时间本就是文件的属性,所以基本都会同时修改。

更改这个权限,我们就是只改属性。
如果过于高频因为查看就更新时间,会有很多隐性的成本。所以linux现在查看上若干次才会更新一次Access时间,具体多少次看具体系统。
我们知道,myproc.c的Modify时间应当是要比myroc早的。所以make可以以此为依据判断myproc.c是否被修改过了。
我们曾经说过,touch可以用来改文件时间:

比如带上-a,就可以只改Access时间。
如果什么选项都不带,就会把ACM三个时间全部更新。
所以通过touch更改时间,也能使我们重复使用make。

所以PHONY的作用就是修饰后总是被执行,如果我们用其修饰第一组的代码,我们就可以重复使用make。
在makefile中注释代码我们使用#来注释。


makefile会在自己内部维护一个类似栈结构的东西。
makefile推导规则

从上往下扫描,从下往上执行。
当我们从上往下扫描,一条找不到时就入栈。所以就保证了我们最后找到myproc.c时,从下往上的执行顺序。
当然我们一般不会这么去写整个过程,自己增加难度。
makefile也允许我们去定义变量。所以我们写makefile一般喜欢这样写:


如果改写成这样:

就不会回显命令。


这样,BIN是我们的目标文件,CC是编译器,SRC是源文件,FLAGS是方法。我们将这组变量打印。

$(BIN)就是取它的内容。
所以我们全以变量的形式呈现了。这就是一个基于变量版本的makefile了。
有点像宏。

所以我们也能猜出,这样做的好处也就是替换具体的文件时不用改后面的代码了,只要在变量处稍作修改。

其实,还可以写得更加优雅:

$@代表的是目标文件,$^代表的是依赖的众多文件列表。
我们的依赖方法来源不止一行。
我们可以把默认的显示信息用@关闭,然后写自己的信息:


但我们发现还是将echo回显了,于是我们继续优化:

多文件呢?
而且,我们并不喜欢直接从.c到可执行文件,而是喜欢先从.c到.o,原因以前说过,为了方便去链接C语言库等,所以我们要改写。

LFLAGS的L代表link。OBJ代表.o文件。
.o文件从哪来的?所以我们要再写一组依赖关系和方法。但是一般我们的.c文件和以此生成的.o文件不止一个,为了简写,我们使用%.o:%.c这样来写我们的依赖关系。%就像makefile模式下的通配符;在依赖关系中我们也简写为:$(CC) $(FLAGES) $<,也是gcc -c $<,这里<用来简写所有的.c文件。

我们知道,gcc -c myproc.c -o myproc.o可以帮我们从.c文件编译到.o文件。
然后,gcc -c myproc.c则可以帮我们直接编译出同名.o文件。
这也就是为什么上面我们写成$(CC) $(FLAGS) $<

优化:

这个地方,我们可以SRC=$(shell ls *.c)执行ls *.c的命令,然后把对应所有的源文件放在SRC中。就不用我们一个一个手写要的源文件了。
第二种做法:
makefile天生自带类似函数的东西,可以支持我们这样写:SRC=$(wildcard *.c)
也是类似通配符。

所以我们的OBJ同样也需要这样能够使用类似通配符的效果,来避免一个一个手写。
OBJ=$(SRC:.c=.o)
这就是最终的makefile。
我们这样来创建100个文件:

不用改刚才的makefile文件了,可以直接这样使用make和make clean:


Makefile还有其他语法,日后可以再学。
相关文章:
【Linux】Make/Makefile
这个3/4行的语法和1/2行是一样的。也是依赖关系和依赖方法。 make命令扫描makefile文件时,从上向下扫描,默认形成一个目标文件。 指定make clean的时候才回去执行对应的清除。 为什么要给我们的clean.PHONY:clean声明它是伪目标呢? PHONY类…...
C++练级计划->《多态》虚函数表,菱形继承多态
目录 什么是多态? 多态的条件 虚函数: 虚函数的重写: 协变 析构函数的重写 C11 final 和 override final: override: 总结: 三重对比:重载重写重定义对比 抽象类 多态的原理 虚函数…...
OkHttp3 - 2. OkHttp的核心组件与架构
1 OkHttp的工作原理 OkHttp3 的核心设计遵循以下原则: 请求与响应的分离:通过 Request 和 Response 对象解耦请求构建与结果处理。异步与同步支持:使用 Call 对象管理请求,可以同步或异步执行。高效连接复用:通过连接…...
异或操作解决一些问题
前提: 异或操作符合交换律,结合律(因为其根本上来抽象理解,就是查看所有项二进制数相同位是否有奇数个1,对运算结果二进制数而言,没有该位为0,有该位为1,与顺序无关)。 …...
操作系统之输入输出
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…...
Centos 安装 Node.js 和 npm
方法2:使用 NVM(Node Version Manager)安装 安装 NVM curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash 重新加载配置 source ~/.bashrc 安装最新的 LTS 版本的 Node.js nvm install --lts 验证安装…...
C语言——指针初阶(一)
目录 一.什么是指针??? 指针是什么? 指针变量: 总结: 总结: 二.指针和指针类型 指针-整数: 总结: 指针的解引用 总结: 三.野指针 如何规避野指针 往期…...
React Native 原生开发指南
写在前面 React Native (RN) 是一个用于构建跨平台移动应用的框架。它允许开发者使用 JavaScript 和 React 来编写应用程序,并将其转换为原生代码。虽然 RN 提供了许多内置的组件和 API,但有时候你可能需要访问原生平台的特定功能或性能优化。为此&…...
【前端】JavaScript中的柯里化(Currying)详解及实现
博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 前端 文章目录 💯前言💯什么是柯里化?💯柯里化的特点💯柯里化的简单示例💯通用的柯里化实现💯柯里化让代码更易读的原因💯…...
解决 docker 部署 vsftpd 速度慢问题
解决 docker 部署 vsftpd 速度慢问题 Docker 部署 ftp version: 3.8services:ftps:image: fauria/vsftpdcontainer_name: my-ftpsenvironment:- FTP_USERyourusername- FTP_PASSyourpassword- PASV_ADDRESS192.168.0.123 # 使用环境变量或直接指定IP地址- PASV_MIN_PORT4900…...
Java基础夯实——2.9 多线程如何共享数据
在 Java 多线程编程中,共享数据通过以下几种方式实现: 1. 使用共享对象 多个线程可以通过引用同一个对象来实现数据共享。例如: class SharedData {private int count;public synchronized void increment() {count;}public synchronized …...
【Leetcode Top 100】234. 回文链表
问题背景 给你一个单链表的头节点 h e a d head head,请你判断该链表是否为 回文链表(回文 序列是向前和向后读都相同的序列)。如果是,返回 t r u e true true;否则,返回 f a l s e false false。 数据…...
GitLab指定用户分配合并权限
进入项目 -》 Project Settings Repository -》展开 Protected branches -》 添加要保护的分支,设置角色 管理用户角色权限 查看到不同用户的角色,一般设置Developer只有Merger Request权限,Maintainer还有Merge审批权限 GitLab 中的权限…...
五,[GXYCTF2019]Ping Ping Ping1
进入靶场,有提示 我们在url试着输入本地IP,返回了ping命令 既然要在url处传参,那就用postman,再输入ip127.0.0.1 & ls,试着列出目录内容 ok,好像是个脏话,它过滤了空格 试着穿越又看到了脏话࿰…...
基于STM32的智能无人机自主飞行与目标识别系统设计
目录 引言系统需求分析 2.1 功能需求 2.2 硬件需求 2.3 软件需求系统设计 3.1 总体架构 3.2 各模块设计系统实现 4.1 硬件实现 4.2 软件实现系统调试与优化总结与展望 1. 引言 随着无人机技术的快速发展,无人机在军事侦察、环境监测、物流配送等领域的应用逐渐增多…...
C 语言数组与函数:核心要点深度剖析与高效编程秘籍
我的个人主页 我的专栏:C语言,希望能帮助到大家!!!点赞❤ 收藏❤ 目录 引言数组基础 2.1 数组的定义与初始化 2.2 一维数组的基本操作 2.3 二维数组及其应用 2.4 数组与指针的关系函数基础 3.1 函数的定义与调用 3.2…...
汽车轮毂结构分析有哪些?国产3D仿真分析实现静力学+模态分析
本文为CAD芯智库原创,未经允许请勿复制、转载! 之前分享了如何通过国产三维CAD软件如何实现「汽车/汽配行业产品设计」,兼容NX(UG)、Creo(Proe),轻松降低企业上下游图纸交互成本等。…...
解决jupyter notebook 新建或打开.ipynb 报500 : Internal Server Error(涉及jinja2兼容性问题)
报错: [E 10:09:52.362 NotebookApp] 500 GET /notebooks/Untitled16.ipynb?kernel_namepyt hon3 (::1) 93.000000ms refererhttp://localhost:8888/tree ...... 重点是: from .exporters import * File "C:\ProgramData\Anaconda3\lib\site-p…...
【若依ruoyi Vue前端线上个人服务器部署】以及常见报错问题解决
提示:【若依ruoyi Vue前端线上个人服务器部署】以及常见报错问题解决 文章目录 前言一、若依ruoyi Vue前端部署常见两种错误1、404问题2、找不到….模块 二、使用步骤(正式开始)1.修改vue.config.js中的publicPath属性。2.修改router/index.j…...
Python学习第十天--处理CSV文件和JSON数据
CSV:简化的电子表格,被保存为纯文本文件 JSON:是一种数据交换格式,易于人阅读和编写,同时也易于机器解析和生成,以JavaScript源代码的形式将信息保存在纯文本文件中 一、csv模块 CSV文件中的每行代表电…...
wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明
LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造,完美适配AGV和无人叉车。同时,集成以太网与语音合成技术,为各类高级系统(如MES、调度系统、库位管理、立库等)提供高效便捷的语音交互体验。 L…...
RocketMQ延迟消息机制
两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后…...
基于FPGA的PID算法学习———实现PID比例控制算法
基于FPGA的PID算法学习 前言一、PID算法分析二、PID仿真分析1. PID代码2.PI代码3.P代码4.顶层5.测试文件6.仿真波形 总结 前言 学习内容:参考网站: PID算法控制 PID即:Proportional(比例)、Integral(积分&…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
反射获取方法和属性
Java反射获取方法 在Java中,反射(Reflection)是一种强大的机制,允许程序在运行时访问和操作类的内部属性和方法。通过反射,可以动态地创建对象、调用方法、改变属性值,这在很多Java框架中如Spring和Hiberna…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)
骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术,它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton):由层级结构的骨头组成,类似于人体骨骼蒙皮 (Mesh Skinning):将模型网格顶点绑定到骨骼上,使骨骼移动…...
