【Linux】Linux开发利器:make与Makefile自动化构建详解

Linux 相关知识点 可以通过点击 以下链接进行学习 一起加油!
初识指令 指令进阶 权限管理 yum包管理与vim编辑器 GCC/G++编译器

在现代软件开发中,自动化构建工具显得尤为重要,make和Makefile是Linux环境下的常用选择。它们通过定义规则和依赖关系,帮助开发者高效管理项目的构建过程。本文将简要介绍make与Makefile的基本原理和用法,帮助提升构建效率。

文章目录

一、Linux项目自动化构建工具-make/Makefile

背景

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

make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建其中makefile/Makefile都是可以的,该文件应同源文件同一目录下。

二、Makefile/makefile文件内容组成

  • 目标文件mytest 】:构建过程中生成的文件,通常是最终产品或中间结果
  • 依赖文件列表test.c】:构建目标文件所需的其他文件。可以按照空格分割多依赖文件,也可以为空
  • 依赖关系mytest:test.c】:目标文件与其依赖文件之间的关系。依赖关系通常用于定义如何通过源文件或其他中间文件生成目标文件。
  • 依赖方法Tab command 】:生成目标文件所使用的具体方式或过程
  • 目标文件与其依赖文件之间形成了依赖关系,依赖方法通过这些依赖文件生成目标文件。
  • clean: rm -f mytest 】: 这个规则并不属于依赖关系。它实际上是一个清理操作的定义,用于删除生成的文件,而不是用于生成目标文件的依赖关系。

三、make/Makefile使用示例

这个make指令会在当前目录下去寻找makefile/Makefile文件,然后读取整个文件里面的内容。根据提供的依赖关系知道你想使用依赖文件列表中test.c文件形成目标文件mytest可执行程序。

四、拦截信息原理与处理方式

4.1 拦截信息含义

当使用 make 生成目标文件后,再次运行 make 时,如果目标文件已经是最新的,make 会提示 '目标文件' is up to date,表示该可执行程序已经是最新版本。由于系统判断没有必要重新编译(因为依赖文件没有发生变化),所以 make 不会执行编译操作,而是直接跳过,提示文件已经是最新的。

4.2 依赖方式总是被执行

如果希望编译操作始终执行并避免拦截信息,可以使用 .PHONY: 依赖目标 来声明依赖关系总是被执行。.PHONY 是一个特殊目标,用于指示某些目标不是文件,而是命令。

4.3 拦截信息出现原理

我们需要了解一个常识:源代码和可执行程序的最后修改时间不可能相同。一般来说,源代码在编译生成可执行程序之前会被编写,因此源代码的时间戳通常早于可执行程序的时间戳。如果修改了源代码,源文件的时间戳会更新,变得比可执行程序晚。

如果需要修改现存文件的时间,可以使用 touch 指令。touch 不仅可以创建新文件,还能修改文件的时间戳。此外,不同环境中对于文件时间的更新策略可能存在差异,某些情况下更新时间可能不是立即生效,而是周期性或在几次操作后更新。这意味着在检查时间戳时,代码可能已经被修改并生成了可执行程序,但未及时更新的文件时间仍可能导致潜在的问题。

五、自动替换符号 @ 与 @与 @与^

通过 @ 与 @与 @与^两个符号,会在make执行Makefile/makefile文件时,自动替换目标文件和依赖文件列表(重复的依赖会被去重)。

六、依赖关系缺失某个依赖文件

**在 Makefile 中,如果存在多对依赖关系,make 找到一对满足条件的依赖关系后,会停止检查下一对。**如果找到的依赖关系缺失某个依赖文件,make 会继续向下查找其他目标,以确定是否有其他目标能够满足该关系的依赖。这样可以确保在某个目标无法满足时,make 会寻找替代的依赖项,最后找不到就会报错。

如果将这些顺序打乱

makefile你必须把最重要形成的文放到前面,总是需要一个开头吧。

如果你选择不将最重要的目标放在前面,make 仍然会尝试按照文件顺序处理依赖关系。不过,这可能导致一些意外的行为,因为 make 会在找到第一个满足条件的依赖后停止检查,可能会忽略后面的重要目标或依赖。

八、makefile支持定义变量(解释性)

Makefile 也支持变量定义,类似于 C 语言中的宏。变量的定义格式为 变量名=值,注意等号两侧不能有空格。通过使用变量,可以简化 Makefile 的编写,避免重复输入相同的内容。

在 Makefile 中,bin: src 是有效的,但这要求 src 必须是一个具体的文件名,而不是一个变量。通常,如果你使用变量来定义源文件,应该写成 bin: $(src),这样 make 才能正确解析 src 的值。

$() 用于引用变量

$() 的作用是告诉 make 引用该变量的值,而不是直接使用文字。例如,如果你写 BINmake 会认为这是目标名称,而不是变量。

如果你不用 $(),而直接写 BINmake 会把它当作目标或命令的一部分,而不会理解为变量。这会导致 make 无法找到正确的目标或依赖,最终导致错误。

九、相关指令不被显示符号@

如果不想在执行命令时看到命令的打印输出,可以使用 @ 符号在命令前面。例如:

在这个例子中,@ 符号使得 gcc 命令在执行时不被打印到控制台。这样可以让输出更清晰,只显示最终结果。

十、make原理

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

以上就是本篇文章的所有内容,在此感谢大家的观看!这里是店小二呀Linux笔记,希望对你在学习Linux语言旅途中有所帮助!

相关推荐
卫生纸不够用8 分钟前
子Shell及Shell嵌套模式
linux·bash
world=hello21 分钟前
关于科研中使用linux服务器的集锦
linux·服务器
华纳云IDC服务商26 分钟前
如何自动解决服务器弹性伸缩问题?
运维·服务器
soragui1 小时前
【ChatGPT】OpenAI 如何使用流模式进行回答
linux·运维·游戏
白云coy2 小时前
Redis 安装部署[主从、哨兵、集群](linux版)
linux·redis
Logintern092 小时前
Linux如何设置redis可以外网访问—执行使用指定配置文件启动redis
linux·运维·redis
娶不到胡一菲的汪大东2 小时前
Linux之ARM(MX6U)裸机篇----1.开发环境搭建
linux·运维·服务器
fat house cat_2 小时前
Linux环境下使用tomcat+nginx部署若依项目
linux·nginx·tomcat
shada2 小时前
Ubuntu 24.04 APT源配置详解
linux·ubuntu