Linux运维:makefile

news2025/5/18 19:56:41

一.makefile

1.makefile介绍

Makefile 是一种用于自动化构建的文件,它描述了一个软件项目的编译规则和依赖关系,并提供了一些工具来自动执行这些规则。

Makefile 的主要作用如下:

  1. 自动化编译:通过 Makefile,可以定义项目中的编译规则和依赖关系。这样,当源代码发生变化时,只需要执行 make 命令,就可以自动地重新编译修改过的源文件,并生成最终的可执行文件或库文件。
  2. 统一构建流程:通过 Makefile,可以将多个编译命令、链接命令、打包命令等整合到一个统一的构建流程中。这样,所有的开发人员都可以使用相同的构建方式,从而减少了因为构建方式不同而导致的问题和错误。
  3. 管理依赖关系:Makefile 中的规则可以描述各个文件之间的依赖关系,从而让 Make 工具知道哪些文件需要被重编译。这样,当某个文件被修改后,只有依赖它的文件才会被重新编译,从而提高了编译的效率。
  4. 定义伪目标:通过 Makefile,可以定义一些伪目标,用于执行一些特殊的操作,例如清除临时文件、打包发布代码、运行测试等等。这些操作可以通过简单的命令来完成,从而提高了开发和测试的效率。

综上所述,Makefile 是一个用于自动化构建的强大工具,它可以让编译、构建、打包等操作变得更加高效和可靠。

2.个人理解

首先我们知道一个项目文件它包含许多.c文件,当程序运行时,它首先需要经过编译和链接生成可执行文件。

其中程序链接时,如果手动编译,需要敲很多命令,尤其文件大的的时候,这个时候我们可以在项目文件目录内执行make命令,makemingl可以自动的帮我们完成链接步骤。

但是make 在执行时,需要一个命名为 Makefile 的文件。这个文件告诉 make 以何种方式编译源代码和链接程序。执行make命令时,它会自动在当前目录下寻找一个叫“makefile”的文件然后去执行它,这个makefile文件就是我们要写的内容,当我们把makefile写好后,其内容就是告诉程序怎么执行。

二.makefile基础

1.makefile规则

基本语法:

target: dependencies
[tab] command

其中,“target”表示要生成的目标文件的名称,“dependencies”表示目标文件所依赖的其他文件,“command”是用于生成目标文件的命令。

注意:这里的[tab]指的是缩进用tab键,而不能用空格,makefile里面格式要求严格。

规则:

  • make会在当前目录下找到一个名字叫Makefile或makefile的文件
  • 如果找到,它会找文件中第一个目标文件 (target) ,并把这个文件作为最终的目标文件。如果target文件不存在,或是target文件依赖的.o文件(prerequities)的文件修改时间要比target这个文件新,就会执行后面所定义的命令command来生成target这个文件。如果target依赖的.o文件(prerequisties) 也存在,make会在当前文件中找到target为.o文件的依赖性,如果找到,再根据那个规则生成.o文件。

2.伪目标

在 Makefile 中,伪目标是一种特殊的目标,它不对应于实际的文件或命令,而是用于定义一些特殊的行为或控制流程。

通常,伪目标在 Makefile 中以一个 .PHONY 指示符声明。这样一来,当使用 make 命令时,make 将不会检查是否存在同名的文件,而仅仅按照规则执行相应的命令。

例如,以下是一个包含伪目标的 Makefile:

.PHONY: clean

clean:
    rm -rf *.o

在上面的例子中,clean 是一个伪目标,当我们运行 make clean 命令时,Makefile 会执行 rm -rf *.o 命令,清除当前目录下所有的 .o 文件。由于 clean 不是一个真正的文件,因此需要使用 .PHONY 指示符显式地声明它是一个伪目标。

伪目标在 Makefile 中的应用非常广泛,例如用于清理临时文件、打包发布代码、运行测试等等操作,都可以通过建立相应的伪目标来简化命令行操作。

3.makefile变量

Makefile 变量是 Makefile 中用来保存值的标识符。它们可以包含任何文本,如文件名、目录名、命令行选项或其他任何字符串。

Makefile 变量使用 $ 符号进行引用,例如 $(VAR),其中 VAR 是变量的名称。在 Makefile 中,变量的值可以通过以下方式定义:

  1. 直接赋值:VAR = value
  2. 延迟赋值:VAR := value
  3. 追加赋值:VAR += value
  4. 条件赋值:VAR ?= value

其中,直接赋值和条件赋值的区别在于,如果变量已经被定义,条件赋值将不会对其进行覆盖,而直接赋值则会对其进行覆盖。

延迟赋值和追加赋值的区别在于,延迟赋值会立即展开变量,而追加赋值会在变量后面添加新的内容。例如:

Copy CodeFOO = bar
BAZ := $(FOO) qux
QUX += xyzzy

在这个例子中,BAZ 的值为 bar quxQUX 的值为 xyzzy

4.makefile常用符号

这四种赋值方式的区别如下:

  1. 直接赋值:VAR = value

直接赋值将变量 VAR 的值设置为 value。如果变量 VAR 已经存在,那么它将被覆盖。

  1. 延迟赋值:VAR := value

延迟赋值允许在定义变量时立即展开所有变量引用。也就是说,在变量定义之后的任何地方引用 VAR 都会得到其值 value,或者说永远是第一次定义的值,即使后面修改也不行,这个赋值方式通常用于保存命令输出等需要立即展开的值。

  1. 追加赋值:VAR += value

追加赋值将 value 添加到变量 VAR 的末尾。如果变量 VAR 不存在,则等同于直接赋值。如果变量 VAR 已经存在,则将 value 添加到其末尾,并且每次使用 += 将会添加一个新的 value

​ 4. 条件赋值:VAR ?= value

条件赋值只有在变量未被定义时才会设置变量的值。如果 VAR 已经定义,则不会进行任何操作。这种赋值方式通常用于默认值。

三.makefile常用函数

在 Makefile 中,函数的格式为:

$(function arguments)

其中,function 是函数名,而 arguments 则是被传递给函数的参数。多个参数之间用逗号 , 分隔。

1.shell

语法:$(shell command)

作用:执行 shell 命令,并返回其输出结果。

2.subst

语法:$(subst from,to,text)

作用:将文本 text 中所有的 from 替换为 to

3.patsubst

语法:$(patsubst pattern,replacement,text)

作用:按照模式 pattern 匹配文本 text 中的内容,并替换为 replacement

假设我们有一个文件列表,其中包含了一些以 .txt 结尾的文件名。现在我们想把这些文件名中的 .txt 去掉,可以使用 patsubst 函数来实现:

假设我们的文件列表为:

file1.txt file2.txt file3.doc file4.txt

我们可以使用以下命令将所有的 .txt 后缀去掉:

$(patsubst %.txt,%,$(FILES))

其中,%.txt 是模式,表示匹配任意以 .txt 结尾的字符串;% 是替换文本,表示将模式匹配到的部分替换为空字符串;$(FILES) 是需要进行替换的文本。

运行上述命令后,得到的输出为:

file1 file2 file3.doc file4

可以看到,所有的 .txt 后缀都被成功地去掉了。

4.foreach

基本格式:

$(foreach var,list,text)`

作用::将变量 var 依次设置为 list 中的每个元素,并将结果拼接成一个字符串 text

例如:

clean : 
        @echo "hello word"
.PHONY : clean
all :
        @echo $b
        @$(foreach var,$(c),echo $(var))

a = $(shell find . -name '*.c')
c := h e l l o w o r d

b = $(subst main,max,$(a))

5.dir、notdir

在Makefile中,dir函数可以用于获取一个文件路径的目录部分。其语法如下:

Copy Code$(dir names...)

其中,names是要处理的文件名列表,可以是一个或多个文件名,使用空格分隔。如果names中某个文件名带有路径部分,则dir函数将返回该文件名的目录部分;否则,dir函数将返回当前目录。

下面是一个示例 Makefile 文件,演示了如何使用 dir 函数:

SRC := src/main.c src/foo/bar.c
OBJS := $(patsubst %.c,%.o,$(SRC))

all: $(OBJS)

%.o: %.c
    @echo "Compiling $<"
    gcc -c $< -o $@

clean:
    rm -f $(OBJS)

dirs:
    @echo $(dir $(SRC))

在上述 Makefile 中,我们定义了一个变量 SRC,它包含了两个源代码文件:src/main.c 和 src/foo/bar.c。然后,我们使用 patsubst 函数将 SRC 中的每个 .c 文件名称替换成相应的 .o 文件名称,并将结果存储到变量 OBJS 中。

接着,我们为每个 .o 文件生成一条编译规则,并将其作为 all 目标的依赖项。在编译规则中,我们使用 $< 自动化变量指代当前目标的第一个依赖项(即对应的 .c 文件),并使用 dir 函数获取该 .c 文件所在的目录。

最后,我们定义了一个名为 dirs 的伪目标,用于输出 SRC 中每个文件的目录部分。在规则中,我们使用 $(dir $(SRC)) 获取 SRC 中所有文件的目录部分,并将其打印到终端上。

这里没有介绍notdir命令,顾名思义就是于获取一个文件路径的文件名部分,即最后一个/后面的内容。

6.filter

在Makefile中,filter函数可以用于从一个列表中筛选出满足某些条件的元素。其语法如下:

$(filter pattern...,text)

其中,pattern是要匹配的模式,可以使用通配符%,即表示任意长度的字符串;text是要处理的列表,可以是一个或多个元素,使用空格分隔。

filter函数将返回text列表中所有匹配成功的元素。如果pattern以%号开头,则表示以该模式结尾的字符串均可匹配成功。

7.basename

在 Makefile 中,basename 函数用于获取路径中的文件名部分。

语法如下:

$(basename names...)

其中 names 参数是一个或多个路径名称。该函数会返回 names 参数中每个路径名称的文件名(此时没有后缀名)部分。

8.演示

TWxk.jpg

四.几个符号

1.$<

在Makefile中,$<是一个自动化变量,用于表示当前规则的第一个依赖文件名。举个例子:

main.o: main.c foo.h bar.h
    gcc -c $< -o $@

在这个规则中,我们指定了目标文件main.o依赖于源文件main.c和头文件foo.h、bar.h。当执行该规则时,Make会自动将$<替换成当前规则的第一个依赖文件(即main.c),并将其作为编译器的源文件参数。

需要注意的是,<只能在规则的命令行中使用,而不能在规则的其他地方,比如依赖关系或者目标文件名中使用。如果需要使用其他依赖文件,可以使用<只能在规则的命令行中使用,而不能在规则的其他地方,比如依赖关系或者目标文件名中使用。如果需要使用其他依赖文件,可以使用^(表示所有依赖文件)或者$+(表示所有依赖文件,但不去除重复项)自动化变量来代替。

2.$^

$^表示所有依赖项,以空格分隔。例如,在下面的规则中:

my_program: main.o utils.o
	$(CC) $(LDFLAGS) $^ -o $@

$^表示main.o utils.o

注意,如果有多个依赖项,使用$^将会把它们一起传递给编译器或链接器。而如果只需要传递其中的某些依赖项,则可以使用$<或手动指定依赖项的名称。

3.$@

$@ 是 Makefile 的一个自动变量,表示规则中的目标文件名。在一个规则中,可以使用 $@ 来引用该规则的目标文件。

例如,考虑以下 Makefile 规则:

my_program: main.o utils.o
    $(CC) $^ -o $@

这个规则将 main.outils.o 编译成一个名为 my_program 的可执行文件。$^ 展开为所有依赖文件,而 $@ 表示规则的目标文件即 my_program。在这里,$@ 被用于指定生成文件的名称,即告诉编译器要把编译后的文件输出到 my_program 文件中。

五.个人实践

理解了这么多,我们直接来一点实际操作,这里以静态链接库为例:

all : main

main : main.o libmymath.a
        gcc -L /usr/lib $^ -o $@

main.o : main.c
        gcc -c main.c -o main.o

libmymath.a : mymath.o
        ar rcs $@ $^

mymath.o : mymath.c
        gcc -c $^ -o $@

clean :
        rm -rf main
.PHONY: clean

这是本人基于上篇博客Linux下链接库编写的makefile,初次接触,个人理解就行。

现在我们对main.c文件就行修改,修改后只需要执行make命令就行了,不需要又重新按照静态链接的步骤一步步去弄,makefile本身简化操作。

我们把main.ca=8改成了a=15,接下来看演示。

六.说明

makefile是一个比较基础的知识点,当然它也可以深化,我们这里仅仅学习使用,网上也有相关教程,几乎都是几个小时就讲完了,相当于补充知识点。同时这也是Linux运维中make命令的原理介绍。

新星计划:Linux运维@刘晨阳导师创作打卡6!

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

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

相关文章

使用 nvcc 的时候出现“helper_cuda.h”: No such file or directory错误该怎么办(其他xxx.h也是同样的解决方法)

今天在命令行中使用nvcc的时候&#xff0c;出现了“helper_cuda.h”: No such file or directory错误。这个错误信息表示&#xff1a;在编译的时候&#xff0c;找不到helper_cuda.h头文件&#xff08;其他xxx.h如果也找不到&#xff0c;那么下面的解释和解决方法也通用&#xf…

Java流式操作——Collectors工具类

文章目录 方法实践说明一、前提条件Person类Data类 二、操作maxBy&#xff1a;获取流中最大元素&#xff1b;minBy&#xff1a;获取流中最小元素joining:合并&#xff0c;将流中的元素&#xff0c;以字符串的形式拼接起来summingInt:把流中的元素映射成int类型的元素&#xff0…

springboot第14集:MyBatis-CRUD讲解

注意点&#xff1a;增、删、改操作需要提交事务&#xff01; 为了规范操作&#xff0c;在SQL的配置文件中&#xff0c;我们尽量将Parameter参数和resultType都写上&#xff01; 编写Mapper接口类 import com.da.pojo.User; import java.util.List; public interface UserMapper…

4.1 指令系统的发展与性能要求

学习目标&#xff1a; 指令系统的发展与性能要求的学习目标&#xff1a; 理解指令系统的发展历程&#xff0c;包括CISC、RISC、VLIW等架构的特点、优缺点以及应用领域&#xff1b;掌握指令系统的性能要求&#xff0c;包括指令集的多样性、可编程性、并行性、效率、可靠性等&a…

ChatGPT学习-如何向ChatGPT提问

​ 最近在学习chatGPT,怎么样的提问是一个好的提问。通过网上找资料肯定不是最好的方法&#xff0c;我想起一句话&#xff0c;“不识庐山真面目&#xff0c;只缘身在此山中”。最好的老师就是chatGPT&#xff01; 下面先展示下提问成果&#xff0c;我通过xmind生成了思维导图 一…

为什么越来越多的企业选择云计算

目录 一、前言 二、云计算的基础概念 2.1 云计算的定义 2.2 云计算的发展历程 2.3 云计算的基本架构 三、 企业采用云计算的优势 四、 行业应用案例 五、未来发展与挑战 六、总结 随着数字化转型的加速&#xff0c;越来越多的企业开始选择云计算作为信息技术应用的基础…

Linux 用户管理与文件权限

Linux 是一个多用户系统&#xff0c;它允许多个用户同时登陆主机&#xff0c;并为他们分配不同的资源和工作环境进行使用。当然&#xff0c;不同的用户都有文件的私有需求&#xff0c;所以设置不同用户文件的权限管理十分重要。 01 用户与用户组 Linux 中一般将文件访问权限的…

【matplotlib】可视化解决方案——如何正确设置图例

概述 matplotlib 中的图例&#xff08;Legend&#xff09;可以帮助我们展示每个数据对应的名称&#xff0c;让图像阅读者更好的认识到图像的数据结构以及绘图者想表达的意思。matplotlib 可以为每一个可见绘图对象&#xff08;Artist&#xff09;添加图例&#xff0c;官方建议…

windows10系统如何实现telnet内网穿透

在windows10系统环境中&#xff0c;我们常用的内网穿透方案是远程桌面内网穿透技术方案&#xff0c;存在的弊端是它属于视窗类操作工具。网上很多教人开启windows10的telnet服务的帖子&#xff0c;凡是通过系统设置进入启用或关闭windows应用后勾选telnet客户端这种方式&#x…

ChatGPT实现服务器体验沙箱

服务器体验沙箱 IT 人员在学习一门新技术时&#xff0c;第一个入门门槛通常都是"如何在本地安装并成功运行"。因此&#xff0c;很多技术的官网都会通过沙箱技术&#xff0c;提供在线试用的 playground 或者按步模拟的 tour。让爱好者先在线尝试效果是否满足预期&…

如何评估现代处理器的性能——以ARM Cortex-A53为例

如何评估现代处理器的性能——以ARM Cortex-A53为例 1 有哪些通用评价指标&#xff1f; 现代处理器内核的性能可以从以下几个方面进行评估&#xff1a; 时钟速度&#xff08;Clock Speed&#xff09;&#xff1a;它是CPU内部时钟发生器的频率&#xff0c;以赫兹&#xff08;…

IDEA2022版教程下()

8.快捷键的使用 8.1 常用快捷键 见《 尚硅谷_宋红康_IntelliJ IDEA 常用快捷键一览表.md 》 8.2 查看快捷键 1、已知快捷键操作名&#xff0c;未知快捷键 2、已知快捷键&#xff0c;不知道对应的操作名 8.3 自定义快捷键 8.4 使用其它平台快捷键 苹果电脑或者是用惯Eclips…

改进YOLOv5: | 涨点神器 | 即插即用| ICLR 2022!Intel提出ODConv:即插即用的动态卷积

OMNI-DIMENSIONAL DYNAMIC CONVOLUTION ODConv实验核心代码ODConv代码yaml文件运行:论文链接: https://openreview.net/forum?id=DmpCfq6Mg39 本文介绍了一篇动态卷积的工作:ODConv,其通过并行策略采用多维注意力机制沿核空间的四个维度学习互补性注意力。作为一种“即插…

Java8流式操作——中间操作

文章目录 什么是中间操作&#xff1f;方法实践说明一、前提条件Person类Data类 二、操作filter:过滤distinct:去重&#xff08;去除集合中重复的元素&#xff09;sorted:排序①、sorted():无参构造②、sorted(Compartor compartor)&#xff1a;有参构造 skip:跳过。从前往后数&…

【Python入门篇】Python开发环境的搭建——安装和配置PyCharm工具

作者简介&#xff1a; 辭七七&#xff0c;目前大一&#xff0c;正在学习C/C&#xff0c;Java&#xff0c;Python等 作者主页&#xff1a; 七七的个人主页 文章收录专栏&#xff1a; Python入门&#xff0c;本专栏主要内容为Python的基础语法&#xff0c;Python中的选择循环语句…

闲谈【Stable-Diffusion WEBUI】的插件:绘图过程动画输出

文章目录 &#xff08;零&#xff09;前言&#xff08;一&#xff09;过程动画输出&#xff08;Steps Animation&#xff09;&#xff08;1.1&#xff09;使用&#xff08;1.2&#xff09;成果 &#xff08;零&#xff09;前言 本篇主要提到WEBUI的过程动画输出插件&#xff0c…

Docker 持久化存储 Volumes

Docker 持久化存储 Volumes 简介如何选择 -v 和 --mount-v或--volume--mount 创建和管理卷启动带有卷的容器使用Docker Compose的卷使用卷启动服务使用只读卷备份、恢复或迁移数据卷备份卷 删除卷自动删除匿名卷删除所有未使用卷 简介 官方文档: https://docs.docker.com/stor…

Python JS逆向篇(四)

Python JS逆向篇&#xff08;四&#xff09; 找到参数加密位置跟进window.asrsea函数结果扣取的js代码扩展 逆向主题&#xff1a;某易云评论数据&#xff0c;请求时的加密参数。 &#xff08;注&#xff1a;文章所涉及内容只做学习参考交流&#xff0c;不做除此之外的任何其它用…

正则表达式基础一

BRE(basic regular expression)&#xff1a;匹配数据流中的文本字符 普通文本匹配 特殊字符 正则表达式存在一些特殊字符&#xff0c;如需当成普通文本来匹配&#xff0c;必须加上转义&#xff0c;即反斜杠\&#xff0c;如下所示 .*[]^${}?|() 指定出现位置的字符 ^ 指定行首…

Python两三行代码轻松批量添加~防韩还是很有必要的~

人生苦短&#xff0c;我用python 一直想做一个这种系列的但是因为七七八八的事情总是忘记&#xff0c; 今天正好有空&#xff0c;来开整一下~ 首先&#xff0c; 天冷防韩是什么梗&#xff1f; 【天冷防韩】 “天冷防韩”是“天冷防寒”的谐音&#xff0c; 不过“寒”指的…