makefile教程(1)

news2024/9/25 5:21:19

makefile教程

makefile是什么:

makefile是用户自行完成的IDE(integrated development environment集成开发环境)程序,与传统的操作系统下的编译不同,makefile可以通过用户自行安排,决定文件的编译顺序,决定哪些文件需要编译,哪些文件需要重复编译等各种复杂的操作

使用makefile的好处:

可自由编译的好处,能够指定文件编译,将繁杂的编译方法集成到一个makefile文件中,然后使用make进行一键编译,极大的提高了开发效率

关于程序的编译和链接:

关于gcc编译成可执行文件的命令,以及对应命令下生成的文件后缀

命令文件
gcc -E 预处理(宏展开)*.i
gcc -S 编译(生成汇编代码)*.s
gcc -c 汇编(生成机器码)*.o(unix下)
gcc -o 链接(把大量的.o文件合成生成可执行文件) (主要链接的是函数和全局变量)对于a.out文件的重命名可执行文件
  • 链接 link

把大量的.o文件合并生成可执行文件

主要链接的就是函数和全局变量,而存放函数和全局变量的地方通常称为库文件 .lib文件

在unix下也叫做.a文件

  • 编译

在编译时,编译器只会管你程序的语法是否正确,函数和变量是否已经声明,函数如果没有声明也没关系,只会报警告,而在链接这一步,链接器会在所有的.o文件中寻找这个函数,如果没有找到,就报链接错误码

makefile内核

所有的makefile的实际都是:编译+链接

只要记住编译+链接就行

  1. 如果这个工程没有被编译过,那么所有的.c文件都要编译并被链接
  2. 如果这个工程已经编译,但是修改了.c文件,我们需要编译修改的.c文件,并连接目标程序
  3. 如果这个工程已经编译,但是修改了.h文件,我们需要编译修改的.h文件,并连接目标程序

makefile的使用规则:

一共有五大原则:显示规则、隐式规则、变量定义、文件指示、注释说明

显示规则

目标…:依赖…

命令

  • 目标:可以是个文件(object文件或者是可执行文件),也可以是个标签label

  • 依赖:要生成target目标的所需要文件或者是目标

  • 命令:就是使用make之后所要执行的命令(shell命令)

当依赖中的文件比目标中的文件要新的话,就必须执行命令中的内容,这就是makefile的核心

请添加图片描述

请添加图片描述

其中“ \ ”表示换行符

clean不是一个文件,而是一个动作名,我们要使用clean,就需要make clean。而且clean后面也不需要出现依赖。

所以我们也可以在makefile中定义不用的编译或者与编译无关的命令,比如程序的打包,程序的备份等

怎么使得make时会判断哪些是不需要makefile的命令呢,例如clean这个动作写入makefile时当我们使用make时不会自动执行,其中的原理在哪

这就谈到make是如何工作的

make是如何工作的

  1. make会首先在当前文件夹中搜寻makefile或者是Makefile文件
  2. 读入被include的其他makefile
  3. 初始化定义的变量
  4. 为所有的目标建立依赖关系链
  5. 顺序执行第一个target,并且把target作为最终的目标文件,也就是一切都是为了第一个target
  6. make会比较依赖和目标的文件时间戳,如果依赖比目标的文件时间新,则会重新生成target文件
  7. 根据最终目标文件的依赖,首先会查找是否存在这些依赖,如果不存在则会按照是否makefile中存在依赖文件的生成方式,有的话就会执行下去,没有的话就直接退出报错
  8. 为什么要单独对clean进行make,是因为:

第一个target并没有直接或间接利用clean

clean之后没有存在依赖

如果我们改变了“command.h”,那么,kdb.o、command.o 和 files.o

都会被重编译,并且,edit 会被重新链接。

makefile中使用变量(变量定义)

  • 变量的定义
  1. 就好比C语言中宏的作用,当我们在添加或者修改依赖时,至少要修改三遍以上,所以干脆用个宏,修改一处就可以,一般宏设置为 “OBJ、OBJECT、OBJS ”
  • 变量的使用
  1. 一般是变量 = 依赖,首先先把变量声明好
  2. 调用变量时使用 $(OBJ)
  • 自动化变量

$< 和 $@称为自动化变量

$@表示目标文件

$<表示依赖文件

makefile自动推导(隐式规则)

一般来说make会自动推导出依赖文件,例如我们的main.o文件就是由main.c得到的,但我们没必要去写:

main.o:main.c defs.h

​ cc -c main.c

直接用 main.o:defs.h

也只是.o对于.c,其余依赖也要补充

请添加图片描述

引用其余的makefile(文件指示)

  • 使用include关键字

include + Makefilename(路径或者通配符)

路径如果没有设置,将会选择是当前文件夹下的makefile

“如果 make 执行时,有“-I”或“–include-dir”参数,那么 make 就会在这个参数所指定”

这个后面再说

  • 环境变量MAKRFILES

如果在当前环境中使用了环境变量MAKEFILES

那么make时会把这个变量MAKEFILES中的值做一个inlcude的动作

但是这个环境变量中的值如果是其他的makefile文件,则会用空格分开

这个变量中的target值在make时也不会起作用,依赖文件发生错误也不会管

通配符的使用

如果要使用一系列的类似的文件,一般使用通配符(* ,?,[…])来概括:

如果文件名中有通配符,我们可以使用 “\ *”来表示真正的“ * ”字符

object = *.o 表示的就是 *.o文件,而没有展开

object = $(wildcard *.o) 就可以得到一个展开后的变量合集

文件搜寻

  • 特殊变量 VPATH

VPATH表示目标或者依赖文件的寻找目录

比如:VPATH = src:…/header

表示目标或者依赖文件寻找的目录为src 或者上一层的header目录

其中:表示目录的分隔

  • 关键字 vpath

可以指定某个文件在哪个目录下寻找:vpath < pattern模式> < directories>

vpath %.h …/header

表示所有的.h文件都可以在上一层的header目录下找到

vpath %.h

表示符合模式%.h的文件目录

vpath

表示清除所有已被设置好了的文件搜索目录

当然目录的优先级最高的还是当前目录下的

连续使用vpath关键字来指定不同的搜索方式:

vpath %.c first

vpath % second

vpath %.c third

其表示“.c”结尾的文件,先在“first”目录,然后是“second”,最后是“third”目录

这里second比较特殊,什么文件都可以在second中搜索,比较浪费时间

可以通过改写成:

vpath %.c first:third

vpath % second

而上面的语句则表示“.c”结尾的文件,先在“first”目录,然后是“third”目录,最后才是“second”目录

伪目标

什么是伪目标

伪目标不是一个文件,所以无法使用依赖关系,我们必须使用一个特殊的标签来注明,使用时也得使用make+标签来表示

伪目标的使用要求

  • 不能与其他目标名重复,我们可以使用.PHONY来指明这是个伪目标

.PHONY:clean

  • 总是被执行的

伪目标同样可作为默认目标,就可以放在开头

all : prog1 prog2 prog3

.PHONY : all

由于伪目标总是被执行的,all作为一个伪目标,如果说prog1更新了,或者是prog3更新了,all也会更新

  • 伪目标也可以成为依赖

.PHONY : cleanall cleanobj cleaniff

cleanall : cleanobj cleaniff

多目标 涉及到函数后续

有时候多个目标可以共同使用一个依赖,这个叫做多目标

静态模式

更好的服务于多目标的使用

目标集合:目标集模式 依赖目标集模式

targets:%.o :%.c

表示对所有的.o文件进行了二次定义,也就是说去掉了.o的结尾,加上了.c的这个结尾

eg1:

objects = first.o second.o

$(object) : %.o : %.c

$(CC) -c $(CFLAGS) $< -o $@

也就是在objects这个变量中 将所有的.o文件修改成.c文件,所以修改之后我们的依赖目标集就是 first.c second.c

所以 < 表示依赖目标集, < 表示依赖目标集, <表示依赖目标集,@表示目标集

eg2:

file = 1.o 2.o 3.elc

( f i l t e r (filter %.o, (filter(file)) : %.o : %.c

gcc -c $< -o $@

$(filter %.elc,%(file)) : %.elc : %.el

emacs -f batch-byte-compile $<

filter是个函数,第一个参数是过滤条件,第二个参数过滤源

自动生成依赖性

对于每个.c文件,我们都得清楚包含了哪些头文件,这就大大增加了压力,但GNU编译器存在自动搜索头文件功能,使用 -MM参数

gcc -MM main.c = main.o : main.c defs.h

我们要为每个文件生成.d 文件之后才能自动化生成依赖关系

%.d : %.c

gcc -M $< > @ . @. @.$$$

书写命令

  • @

我们用“@”字符在命令行前,那么,这个命令将不被 make 显示出来

如果你要让上一条命令的结果应用在下一条命令时,你应该使用分号分隔这两条命令。比如你的第一条命令是 cd 命令,你希望第二条命令得在 cd 之后的基础上运行,那么你就不能把这两条命令写在两行上,而应该把这两条命令写在一行上,用分号分隔。

加一个减号“-”(在 Tab 键之后),标记为不管命令出不出错都认为是成功的

嵌套执行make

在不同的文件夹中编写不同的makefile,再由总控的makefile进行控制,可以有效的进行模块化的维护

例如我们在subdir下有个makefile,如果我们要在总控makefile中使用:

subsystem:

​ cd subdir && $(MAKE)

我们的make需要一点参数,所以定义成变量比较合适

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

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

相关文章

【Java动态代理如何实现】

✅Java动态代理如何实现 ✅JDK动态代理和Cglib动态代理的区别 ✅拓展知识仓✅静态代理和动态代理的区别✅动态代理的用途✅Spring AOP的实现方式&#x1f4d1;JDK 动态代理的代码段&#x1f4d1;Cglib动态代理的代码块 ✅注意事项&#xff1a; 在Java中&#xff0c;实现动态代理…

泛微OA xmlrpcServlet接口任意文件读取漏洞(CNVD-2022-43245)

CNVD-2022-43245 泛微e-cology XmlRpcServlet接口处存在任意文件读取漏洞&#xff0c;攻击者可利用漏洞获取敏感信息。 1.漏洞级别 中危 2.影响范围 e-office < 9.5 202201133.漏洞搜索 fofa 搜索 app"泛微-OA&#xff08;e-cology&#xff09;"4.漏洞复现 …

大模型做实体识别任务的原理

1、背景 命名实体识别&#xff08;named entity recognition&#xff0c;NER&#xff09;&#xff1a;通常是一个序列标注的任务&#xff0c;常见的模型框架有&#xff1a;LSTM-CRF、BERTBILSTMCRF等&#xff0c;该种任务通常被成为flat NER即&#xff1a;每一个token只分配一…

视频号小店需要多少资金?

我是电商珠珠 视频号团队自22年发展视频号小店以来&#xff0c;为人所知。和抖音电商一样&#xff0c;都是在发展的第二年掀起了浪花。 也就是今年&#xff0c;很多想要入驻的新手&#xff0c;对于视频号小店不太了解&#xff0c;不清楚到底需要多少资金。 今天&#xff0c;…

Unity协程的定义、使用及原理,与线程的区别、缺点全方面解析

目录 协程的定义及简介 协程的用途 定时器 将复杂程序分帧执行 等待某些条件完成后执行后续 异步加载资源 协程的原理 MonoBehaviour中每一帧的游戏循环 迭代器 IEnumerator 接口 具体执行过程 协程和线程的区别 协程的缺点 无法返回值 依赖于MonoBehaviour 维护…

一文让你搞明白文本或代码中 \n 和 \r 的区别

我们使用printf打印时基本都会用到 \n 和 \r 之类控制字符&#xff0c;比如&#xff1a; printf("hello world!\r\n"); 那么&#xff0c;你知道 \n 和 \r 的区别吗&#xff1f; 一、关于 \n 和 \r 在ASCII码中&#xff0c;我们会看到有一类不可显示的字符&#x…

jenkins Job华为云EIP变更带宽

引言: 在数字化时代&#xff0c;云服务资源的弹性管理是企业降低运营成本、提高效率的关键手段。通过弹性公网IP&#xff08;EIP&#xff09;服务&#xff0c;企业可以实现按需计费&#xff0c;优化网络支出。然而&#xff0c;根据业务流量的不同阶段调整计费模式&#xff0c;…

【数据结构】什么是二叉树?

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:数据结构 ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;二叉树的定义 &#x1f4cc;二叉树的特点 &#x1f4cc;特殊二叉树 &#x1f4cc;二叉树的性质 &#x1f4cc;二叉树的存储结构 &#x1f4cc;二叉树…

路径规划最全综述+代码+可视化绘图(Dijkstra算法+A*算法+RRT算法等)

路径规划综述 1. 背景介绍 路径规划是指在给定的环境中找到从起点到终点的最佳路径的过程。它在现实生活中有着广泛的应用&#xff0c;包括无人驾驶、物流配送、机器人导航等领域。随着人工智能和计算机技术的发展&#xff0c;路径规划技术也在不断地得到改进和应用。 路径规划…

宠物智能喂养系统App重新定义养宠体验

​ 在科技蓬勃发展的当今世界&#xff0c;宠物照顾和护理的更多可能性也随之扩大。宠物智能喂养系统App正改变着我们对宠物看护的传统理解。 一、对宠物用品店的影响 作为一款集成了先进的摄像头、传感器和自动投喂功能的设备&#xff0c;智能喂养系统App使得宠物用品店可以…

龙迅LT8713SX适用于一路Type-C/DP1.4转三路Type-C/DP1.4/HDMI2.0应用方案,分辨率高达4K60HZ,支持SST/MST模式!

1. 概述 LT8713SX是一款高性能Type-C/DP1.4转Type-C/DP1.4/HDMI2.0转换器&#xff0c;具有三个可配置的DP1.4/HDMI2.0/DP输出接口和音频输出接口。LT8713SX支持 DisplayPort™ 单流传输 &#xff08;SST&#xff09; 模式和多流传输 &#xff08;MST&#xff09; 模式。当接收…

【SpringBoot】之Security进阶使用(登陆授权)

&#x1f389;&#x1f389;欢迎来到我的CSDN主页&#xff01;&#x1f389;&#x1f389; &#x1f3c5;我是君易--鑨&#xff0c;一个在CSDN分享笔记的博主。&#x1f4da;&#x1f4da; &#x1f31f;推荐给大家我的博客专栏《SpringBoot开发之Security系列》。&#x1f3af…

C# Onnx yolov8 pokemon detection

目录 效果 模型信息 项目 代码 下载 C# Onnx yolov8 pokemon detectio 效果 模型信息 Model Properties ------------------------- date&#xff1a;2023-12-25T17:55:44.583431 author&#xff1a;Ultralytics task&#xff1a;detect license&#xff1a;AGPL-3.0 h…

4.9【共享源】流的多生产者和消费者

当一个系统中存在多个生产者和消费者时&#xff0c;情况可能会变得复杂。 了解生产者和消费者流之间支持的基数非常重要。 本质上&#xff0c;一个生产者流可以与多个消费者流连接&#xff0c;但一个消费者流只能连接到一个生产者流。请注意&#xff0c;基数关系仅限于单个流&…

竞赛保研 基于RSSI的室内wifi定位系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; wifi室内定位系统 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;…

asp.net mvc 重定向问题的解决方式

前端ajax发起请求&#xff0c;在后端接口中重定向&#xff0c;结果报错&#xff0c;无法跳转 Ajax实际上是通过XMLHttpRequest来向服务器发送异步请求的&#xff0c;从服务器获取数据&#xff0c;然后使用JS来更新页面&#xff0c;这也就是常说的局部刷新实现方式&#xff0c;所…

Linux部署MeterSphere结合内网穿透实现远程访问服务管理界面

文章目录 前言1. 安装MeterSphere2. 本地访问MeterSphere3. 安装 cpolar内网穿透软件4. 配置MeterSphere公网访问地址5. 公网远程访问MeterSphere6. 固定MeterSphere公网地址 前言 MeterSphere 是一站式开源持续测试平台, 涵盖测试跟踪、接口测试、UI 测试和性能测试等功能&am…

华为数通方向HCIP-DataCom H12-831题库(多选题:241-249)

第241题 (NEW) 以下哪些操作可能会影响客户网络的正常运行? A、从设备上下载日志 B、软件升级 C、路由协议配置变更 D、debug核心交换机上转发的所有IP报文 答案:ABCD 解析: 第242题 对于防火墙的默认安全区 Trust 和 Untrust 的说法,正确的有 A、从 Trust 区域访问 Untr…

安卓开发--RecyclerView快速上手【上】

效果图展示: 下面三个kml文件名即动态从服务器获取并列表加载。 RecyclerView简称 RV, 是作为 ListView 和 GridView 的加强版出现的,目的是在有限的屏幕之上展示大量的内容,因此 RecyclerView 的复用机制的实现是它的一个核心部分。 一般在动态获取服务器数据进行…

K8S理论

kubernetes&#xff1a;8个字母省略&#xff0c;就是k8s 自动部署自动扩展和管理容器化部署的应用程序的一个开源系统 k8s是负责自动化运维管理多个容器化程序的集群&#xff0c;是一个功能强大的容器编排工具 分布式和集群化的方式进行容器化管理 版本有1.15 .1.18 .1.20 …