GNU make笔记

是看跟我一起写makefile做的一点笔记。

编译和链接

在Makefile中定义整个编译流程以及各个目标文件与源文件之间的依赖关系,并且只重新编译新的修改会影响到的部分,从而降低编译的时间。

编译只检查函数、变量是否被声明,并生成.o(Linux)或.obj(Windows)文件。由于编译生成的中间目标文件太多,因此通常会将其打包成为.a(Linux)或.lib(Windows)文件,以进行链接。

依赖关系

target ... : prerequisites ...command...
  • target:可以是一个目标文件,可执行文件,或一个标签。
  • prerequisites:target所依赖的文件和target。
  • command:该target要执行的shell命令。

注意makefile中的command必须以Tab开头。
另外,在执行有顺序性要求的命令时,不应该分写两行,而应该用分号隔开,例如:

	# 错误写法!pwd将在本目录执行cd ../pwd# 正确写法cd ../; pwd

makefile会检查文件的更新时间,当prerequisites中有文件比target新时,command所定义的命令就会被执行。

以1个.h文件 + 2个.c文件为例:

# myProcess是可执行文件
myProcess : main.o somec.ogcc -o myProcess main.o somec.omain.o : main.c somec.hgcc -c main.c
somec.o : somec.c somec.hgcc -c somec.cclean :rm myProcess main.o somec.o

注意,这里的clean是一个标签而非文件,使用类似make clean这样的形式来执行标签后的命令。

makefile会以完成第一个target为目标,逐次展开依赖,去更新涉及到的依赖的文件。

变量

将上例改为用变量的形式:

OBJ = main.o somec.o
TARGET = myProcess
CC = gcc$(TARGET) : $(OBJ)$(CC) -o $(TARGET) $(OBJ)main.o : main.c somec.h$(CC) -c main.c
somec.o : somec.c somec.h$(CC) -c somec.cclean :rm $(TARGET) $(OBJ)

也可以将clean改为下面这种写法:

.PHONY : clean
clean :-rm $(TARGET) $(OBJ)

其中,.PHONY显式地表示clean是一个伪目标,即表明clean不是需要检查依赖的目标。
另外,rm前的-表示执行时即使出错,也继续执行命令。

一般更推荐使用:=来赋值变量,与=的区别在于,前者立即展开,而后者在使用时才会展开。

定义空格变量

使用如下的方法定义空格变量:

nullstring :=
space := $(nullstring) #end of line

nullstring是空变量,其后加一个空格,在用注释表示结束,即可将space展开为一个空格变量。

变量的替换

例如:

var1 := a.o b.o
var2 := $(var1:.o=.c)

表示var2是将var1中的.o替换为.c,即var2为a.c b.c。

override

override强制修改变量,例如:

var := var1
override var1 := var2

多行变量

define multi_line_var
xxx
xxx
endef

目标变量

在目标后的依赖里写变量,表示不管全局上该变量如何,在此目标引发的行为中变量都是这样的,例如:

CFLAGS := -o
# 由prog引发的行为中CFLAGS都是-g
prog : CFLAGS = -g

自动变量

使用模式规则来定义一个隐含规则,需要在目标中使用%。目标中的%取决于依赖中的值。
而自动化变量,就会把模式中所定义的一系列的文件自动地挨个取出。

下面是一些常用的自动变量:

自动变量含义
$@规则中的目标文件名
$<第一个依赖文件
$^所有依赖文件
$*匹配通配符%的部分

make自动推导

make看到xx.o,可以自动地推导出它依赖同名的xx.c,并且gcc -c xx.c也会被自动加上。
由此,上例又可以省略为:

OBJ = main.o somec.o
TARGET = myProcess
CC = gcc$(TARGET) : $(OBJ)$(CC) -o $(TARGET) $(OBJ)main.o : somec.h
somec.o : somec.hclean :rm $(TARGET) $(OBJ)

包含其他makefile文件

默认情况下,make会寻找命名为makefile和Makefile的文件,当然也可以是其他任意命名的makefile文件,不过需要使用make -f <filename>来显式地指定。

在一个makefile中使用include <filenames>来包含其他makefile文件,

文件搜索

默认情况下,makefile只会在当前目录搜索文件。

  • 使用VPATH变量指明其他的目录用于搜索。
    例如VPATH = src:../headers,其中src和headers都是搜索目录,它们之间用:隔开。
  • 使用vpath关键字。
    例如vpath %.h ../headers表示在headers下搜索所有以.h结尾的文件。

一次生成多个程序

按基本的写法,makefile只会从第一行,即第一个生成程序开始查找依赖,如果后面还有程序要生成则可能被忽略。
可以使用伪目标来达成这一目的:

all : prog1 prog2
.PHONY : allprog1 : prog1.ogcc -o prog1 prog1.oprog2 : prog2.ogcc -o prog2 prog2.o

声明一个伪目标all,它依赖于两个程序,但由于伪目标不会被生成文件,因此all总是需要更新其依赖,也就总是生成这多个程序。

条件判断

使用ifeq, ifneq, ifdef, ifndef来进行条件判断,并且都以endif结尾。
make读取Makefile时就计算条件表达式的值,并根据其值来选择语句,所以,不要把自动化变量放入条件表达式中,因为自动化变量是在运行时才有的。

函数

格式为$(function argument1,argument2)。函数和参数以空格隔开,参数见以逗号隔开。
下面介绍一些常用的函数。

字符串函数

  • subst
    $(subst from,to,text),把字符串text中的from替换为to。
  • patsubst
    $(patsubst pattern,replacement,text),模式替换,把text中的单词pattern替换为replacement。
  • strip
    $(strip string),去空格
  • filter
    $(filter pattern,text),只保留text中符合pattern模式的单词。
    例如```
sources := a.c b.o c.s
$(filter %.c %.o,$(sourecs))
返回a.c b.o
  • sort
    $(sort string),给string中的单词排序,注意会去重。
  • word
    $(word n,string),取string中的第n个单词。
  • words
    $(words string),统计单词个数。

文件函数

  • dir
    $(dir names),从文件名列表names中取出目录,例如$(dir /src/foo.c temp)返回/src/ ./
  • suffix
    $(suffix names),从names中取出各个文件的后缀。
  • basename
    同上,只不过取的是前缀名。

控制流函数

  • foreach
    $(foreach var,list,expr),把list中的单词拿出来赋给var,然后执行expr。expr每次的返回会以空格隔开,最后组成整个函数的返回值。
    例如:$(foreach n,a b,$(n).o)返回a.o b.o
    注意var是一个局部变量,其作用域只在foreach中。
  • if
    $(if condition,then-part,else-part),else-part可以省略。
  • shell
    $(shell expr),执行一个shell命令作为返回值。
  • error
    $(error text),停止make并报错text。
  • warning
    同上,不过不退出make而是继续执行。

总结

GNU make的执行步骤如下:

  1. 读入所有的Makefile。
  2. 读入被include的其它Makefile。
  3. 初始化文件中的变量。
  4. 推导隐式规则,并分析所有规则。
  5. 为所有的目标文件创建依赖关系链。
  6. 根据依赖关系,决定哪些目标要重新生成。
  7. 执行生成命令。

第三步并非一开始就将所有变量展开,而是其出现在依赖关系中且要被使用了才展开。

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

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

相关文章

前端复制带上版权信息

前端复制带上版权信息 当用户复制内容时&#xff0c;自动添加版权信息。 HTML内容 <body><h1 inputmode"text">复制我</h1> </body>Js内容 document.addEventListener("copy", (event) > {event.preventDefault(); // 阻止…

云闪付app拉新推广一手渠道 附详细教程

云闪付推广拉新可以通过“聚量推客”申请 云闪付是什么呢&#xff1f;是中国银联出的支付平台&#xff0c;在地推和网推项目里也算是比较火热的app拉新产品&#xff0c;属于地推和网推的百搭项目&#xff0c;操作也简单 只需要动账就算一个数据&#xff0c;目前主要招收地推、…

重新思考边缘负载均衡

本文介绍了Netflix在基于轮询的负载均衡的基础上&#xff0c;集成了包括服务器使用率在内的多因素指标&#xff0c;并对冷启动服务器进行了特殊处理&#xff0c;从而优化了负载均衡逻辑&#xff0c;提升了整体业务性能。原文: Rethinking Netflix’s Edge Load Balancing[1] 我…

第十五章 EM期望极大算法及其推广

文章目录 导读符号说明混合模型伯努利混合模型(三硬币模型)问题描述三硬币模型的EM算法1.初值2.E步3.M步初值影响p,q 含义 EM算法另外视角Q 函数BMM的EM算法目标函数LEM算法导出 高斯混合模型GMM的EM算法1. 明确隐变量, 初值2. E步,确定Q函数3. M步4. 停止条件 如何应用GMM在聚…

软测推荐第二期:10本高质量测试书籍

在不断发展的软件开发领域&#xff0c;测试是质量的守护者&#xff0c;确保产品不仅满足功能要求&#xff0c;而且提供无缝的用户体验。随着软件复杂性的增加&#xff0c;对完善的测试方法和见解的需求也随之增加。 上次给大家推荐了五本书&#xff0c;获得了大家的积极反馈&a…

RT-Thread系统使用常见问题处理记录

1.使用telnet连接系统时发送help指令显示不全的问题。 原因&#xff1a;telnet发送缓存太小。 解决办法&#xff1a;更改agile_telnet软件包里Set agile_telnet tx buffer size的大小。 2.使用Paho MQTT软件包过一段时间报错hard fault on thread: mqtt0 解决办法&#xff1…

UE5加载websocket模块为空

今天测试UE 发现工程启动不了&#xff0c;后来看到原来是websocket模块无法加载。 解决的它的方法很简单&#xff0c;这种问题一般会出现在源码版本的引擎或者是停电了&#xff0c;导致UElaunch版本损坏&#xff0c;解决方法是来到源码版本的引擎 这个目录下&#xff1a; D:\…

稳定性测试—fastboot和monkey区别

一、什么是稳定性测试 稳定性测试是指检验程序在一定时间内能否稳定地运行&#xff0c;在不同的场景下能否正常地工作的过程。主要目的是检测崩溃、内存泄漏、堆栈错误等缺陷。 二、Monkey 1.什么是Monkey 是一个命令行工具&#xff0c;通常在adb安卓调试运行&#xff0c;模…

ABAP简单的队列设置QRFC

场景&#xff1a;用job的方式在接口里启用job&#xff0c;如果接口调用比较频繁&#xff0c;存在同一时间启动相同job的情况&#xff0c;会导致锁表锁程序这种情况。 查阅job函数&#xff0c;发现在JOB_CLOSE函数里自带了类似队列的参数&#xff0c;但是因为是接口&#xff0c…

Java Script基础-数组遍历的6种方式

前言 现在因为需要写Web前端&#xff0c;也超级喜欢上了JS&#xff0c;数组作为最常用的数据结构&#xff0c;6种常用的数组遍历方式&#xff0c;希望和大家一起来掌握 for in var babys [sun, zhu, tang] for (let index in babys) { console.log(babys[index]); } for in语法…

如何卸载干净 IDEA(图文讲解)windows和Mac教程

大家好&#xff0c;我是sun~ 很多小伙伴会问 Windows / Mac 系统上要怎么彻底卸载 IDEA 呢&#xff1f; 本文通过图片文字&#xff0c;详细讲解具体步骤&#xff1a; 如何卸载干净 IDEA&#xff08;图文讲解&#xff09; Windows1、卸载 IDEA 程序2、注册表清理3、残留清理 M…

“Notepad++“ 官网地址

notepad官网下载地址&#xff1a;https://notepad-plus-plus.org/downloads/ npp.8.5.8.Installer.x64 本下载地址- https://download.csdn.net/download/namekong8/88494023 1. Fix session file data loss issue. 2. Fix Explorer context menu "Edit with Notepad…

重生奇迹mu下载后仅仅只是挂机吗?

挂挂机、聊聊天&#xff0c;打打怪&#xff0c;如此简单、轻松的游戏或许有&#xff0c;但绝对不是重生奇迹mu&#xff01;因为重生奇迹mu挂机也不是那么容易&#xff0c;即便是多名高端玩家组队挂机&#xff0c;也有可能是全队惨灭&#xff0c;这样的情况时常发生在游戏中。 …

Autosar诊断实战系列26-Dem(DTCEvent)要点及配置开发详解

本文框架 前言1. Dem及其与其他模块交互介绍1.1 与DCM模块交互1.1.1 0x14服务调用时序1.1.2 0x85服务调用时序1.1.3 0x19服务调用时序1.2 与Fim模块交互1.3 与NvM模块交互1.4 与BswM模块交互1.5 与其他BSW及APP模块交互2. Dem配置开发介绍2.1 DemGeneral配置2.1.1 DemGeneral一…

【入门Flink】- 05Flink运行时架构以及一些核心概念

系统架构 Flink运行时架构Standalone会话模式为例 1&#xff09;作业管理器&#xff08;JobManager&#xff09; JobManager 是一个 Flink 集群中任务管理和调度的核心&#xff0c;是控制应用执行的主进程。每个应用都应该被唯一的 JobManager 所控制执行。 JobManger 又包含…

在windows中搭建vue开发环境

1.环境搭建 具体环境搭建步骤参考链接 注意该博客中初始化命令&#xff1a; vue init webpack MyPortalProject需改为小写&#xff1a; vue init webpack myportalproject不然会报错 Warning: name can no longer contain capital letters2.创建第一个vueelement ui项目 …

聚观早报 |盒马参战双11;真我GT5 Pro将压轴登场

【聚观365】11月4日消息 盒马参战双11 真我GT5 Pro将压轴登场 奇瑞汽车10月销量创新高 iQOO 12系列将首发电竞芯片Q1 苹果CEO库克称正改善供需平衡 盒马参战双11 不少消费者反映&#xff0c;今年盒马的双11已悄然开始&#xff1a;10月20日起&#xff0c;盒马APP很多商品页…

【FPGA教程1】Verilog基础语法

Verilog基础语法 1. 常用关键字/保留字模块 module endmodule输入输出信号 input output inout变量 wire reg参数 parameter localparam常数赋值alwaysassign 运算符归约运算符、按位运算符逻辑运算符关系运算符移位运算符位拼接运算符条件运算符优先级 分支控制语句if-elsecas…

pytorh模型训练、测试

目录 1 导入数据集 2 使用tensorboard展示经过各个层的图片数据 3 完整的模型训练测试流程 使用Gpu训练的两种方式 使用tensorboard显示模型 模型训练测试 L1Loss函数 保存未训练模型或者已经训练完的模型 4 加载训练好的模型进行测试 1 导入数据集 import torch from torch.u…

【3D图像分割】基于 Pytorch 的 VNet 3D 图像分割3(3D UNet 模型篇)

在本文中&#xff0c;主要是对3D UNet 进行一个学习和梳理。对于3D UNet 网上的资料和GitHub直接获取的代码很多&#xff0c;不需要自己从0开始。那么本文的目的是啥呢&#xff1f; 本文就是想拆解下其中的结构&#xff0c;看看对于一个3D的UNet&#xff0c;和2D的UNet&#x…