Linux:自动化构建 - make

Linux:自动化构建 - make

    • make基本概念
    • makefile语法
      • 变量
      • PHONY


make基本概念

make是一个用于自动化编译和构建过程的工具。它主要用于管理大型软件项目的构建过程,帮助开发者更高效地编译和部署代码,并减少人为错误的发生,这使得软件的编译和部署变得更加自动化和可靠。

其中make是一个命令,执行该命令需要当前操作目录下有一个名为makefile或者Makefile的文件,在makefile内部编写指令,随后就可以通过make快速执行一系列的指令了。

当前目录下有一个test.c文件,需要把该文件编译为可执行文件mybin。该过程就可以用make来自动执行。我先编写一个makefile,然后再讲解,代码如下:

mybin:test.cgcc -o mybin test.c
clean:rm -f mybin   

其中我们可以看到两条熟悉的指令:gcc -o mybin test.c,该指令完成把test.c文件编译为可执行文件mybinrm -f mybin,该指令完成对mybin的删除。

有了这个文件后,我们就可以直接输入make,完成对test.c的编译:

在这里插入图片描述

一开始目录下只有makefiletest.c两个文件,执行指令make后,Linux自动执行了指令gcc -o mybin test.c,最后目录中就出现了编译好的可执行文件mybin

我们也可以输入make clean,完成对mybin的删除:

在这里插入图片描述

执行make clean后,Linux自动执行了指令rm -f mybin,完成了mybin的删除。

看到其大致是如何执行后,我现在讲解以上代码中各个部分的作用是啥。

mybin:test.cgcc -o mybin test.c
  • mybin:test.c:这个由两个文件名通过一个:隔开的整体,叫做依赖关系。左侧的mybin叫做目标文件,右侧的test.c叫做依赖文件列表
  • gcc -o mybin test.c:这个语句叫做依赖方法

那么依赖关系目标文件依赖文件列表依赖方法之间有什么关系呢?

  1. 目标文件:

    • 目标文件是 make 命令要生成的文件,通常是可执行程序、库文件或中间目标文件。
    • 每个目标文件都有一条或多条命令来生成它。
    • 目标文件可以有多个依赖文件,这些依赖文件共同决定了目标文件的生成过程。
  2. 依赖文件列表:

    • 依赖文件列表描述了目标文件所依赖的输入文件,如源代码文件、头文件、库文件等。
    • 依赖文件列表告诉 make 哪些文件的变化会导致目标文件需要重新生成。
    • 依赖文件列表可以包含多个文件,用空格分隔。
  3. 依赖关系:

    • 目标文件与其依赖文件之间形成依赖关系。
    • 如果依赖文件中任何一个文件发生变化,目标文件就需要重新生成。
    • 依赖关系可以形成层次结构,实现文件之间的层次依赖。
  4. 依赖方法:

    • 依赖方法是生成目标文件所需执行的命令。
    • 依赖方法通常是 shell 命令,用于编译、链接等操作。
    • 依赖方法可以包含多条命令,每条命令用回车分隔。

这里要注意,依赖方法前面必须用一个Tab键隔开,不可以是四个空格。

再看到后半段:

clean:rm -f mybin   

该代码中,目标文件是clean,没有依赖文件列表,依赖关系是删除mybin的指令。只要执行make clean就会执行后面的代码rm -f mybin ,从而实现文件的删除。

左侧的目标文件clean叫做伪目标伪目标是 make 中的一种特殊目标,它不对应任何文件,只是用来执行一些命令。常见的伪目标有 all、clean、install 等。

那么现在有一个问题,为什么执行mybin:test.c直接使用make就可以,但是make clean才能执行clean呢?

make后面不接任何内容时,则在makefile中从上往下查找,找到第一个依赖关系执行

现有如下makefile

mybin:test.ogcc -o mybin test.o
test.o:test.sgcc -c -o test.o test.s
test.s:test.igcc -S -o test.s test.i
test.i:test.cgcc -E -o test.i test.cclean:rm -f test.i test.s test.o mybin

该文件完成了一个连续的C语言程序编译链接过程,但是其有一个问题在于,C语言编译过程应该依次生成.i.s.o文件,最后生成mybin。第一条依赖关系执行的时候,就缺少test.o文件,第二条依赖关系缺少test.s文件,以此类推,整个编译过程都是反的。那么该makefile可以执行成功吗?

我们试试:

在这里插入图片描述
可以看到,其执行成功了,这是为什么?我只输入了make指令,按理来说应该只执行第一条依赖关系,为什么除了clean的所有依赖关系都被执行了?

make会根据文件的依赖关系进行自动推导,以正确的顺序执行各个依赖关系

比如说一开始mybin缺少了test.o,于是makemakefile中查找,发现test.o:test.s的依赖关系可以生成test.o于是先执行该依赖关系。但是test.o:test.s的依赖关系缺少test.s,就再去找生成test.s的依赖关系,以此类推。


makefile语法

以上我们只简单讲解了一个基本的makefile例子,来帮助大家理解make,现在我们来讲解更多的makefile语法。

首先,在makefile中,指令内部的目标文件可以用$@代替,依赖文件列表可以用$^代替:

mybin:test.cgcc -o $@ $^  

在这里gcc -o $@ $^ gcc -o mybin test.c 是一样的。

变量

makefile中,是可以定义变量的,只需要用一个等号进行赋值即可:

bin=mybin
src=test.c

此时bin的值就是mybinsrc的值就是test.c,想要使用这个变量,就在对应的地方以$(变量名)的形式代替即可,这个变量可以放在任何地方,包括指令内部,依赖关系中等等。

比如下面这样:

bin=mybin
src=test.c$(bin):$(src)gcc -o $(bin) $(src)clean:rm -f $(bin)

任何需要test.cmybin的地方,都可以改为$(bin)$(src)


PHONY

讲解PHONY前,我们看到一个问题:

在这里插入图片描述
现在我们每次make都会生成一个mybin文件,如果直接gcc -o mybin test.c,那么新生成的mybin文件会覆盖原先的文件。但是make执行的指令,会进行一次检查,如果源文件test.c没有进行更新,那么make就会拒绝再次编译这个文件,因为编译出来的结果是一样的,导致mybin无法连续编译两次。

也就是上图中我们连续两次make,第二次拒绝了我们的原因。

PHONYMakefile中是一个非常有用的特殊目标。make执行到PHONY目标时,它会无条件执行该目标下定义的命令,而不会检查是否有同名的文件在

因此我们就可以对mybin使用这个PHONY,让它强制执行命令,不论当前目录下有没有mybin

修饰语法:

.PHONY:xxx

此时xxx对应的命令就会被强制执行。

makefile写法:

.PHONY:mybin
mybin:test.cgcc -o mybin test.c

此时mybin每次都会强制执行命令,不论之前是否存在mybin文件了。

但是这并不是PHONY的主要用途,其主要用于修饰伪目标。比如伪目标clean,如果当前目录下刚好有一个叫做clean的文件,那么clean作为一个目标文件,就有可能会被make禁止执行。可是我们的clean作为一个伪目标,其目的不是生成一个clean文件,而是执行命令,因此要用PHONY来强制执行clean对应的命令:

.PHONY: clean
clean:rm -rf *.o

在这里,clean是一个PHONY目标,即使当前目录下有一个名为clean的文件,make clean也会执行删除操作,而不是试图构建clean文件。


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

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

相关文章

电商技术揭秘十八:电商平台的云计算与大数据应用小结

电商技术揭秘相关系列文章 电商技术揭秘一:电商架构设计与核心技术 电商技术揭秘二:电商平台推荐系统的实现与优化 电商技术揭秘三:电商平台的支付与结算系统 电商技术揭秘四:电商平台的物流管理系统 电商技术揭秘五&#xf…

【STL】list的模拟实现

目录 前言 list概述 list的节点 list的迭代器 list的结构 构造与析构 拷贝构造与赋值 list的元素操作 insert() push_back() push_front() erase() pop_back() pop_front() clear() swap() size() 完整代码链接 前言 如果你对链表还不熟悉或者忘了的话…

Harmony鸿蒙南向驱动开发-PWM

PWM(Pulse Width Modulation)即脉冲宽度调制,是一种对模拟信号电平进行数字编码并将其转换为脉冲的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。通常情况下,在使用马达控制、背光亮度调节时会用到PWM模…

微信小程序实现输入appid跳转其他小程序

前言 本文记录wx.navigateToMiniProgram打开另一个小程序API使用方法&#xff0c;并封装为组件。 wxml 部分 输入框用来记录appid&#xff0c;按钮用来查询并跳转。 <view class"container"><input class"input" placeholder"请输入要查…

Flutter Your project requires a newer version of the Kotlin Gradle plugin

在开发Flutter项目的时候,遇到这个问题Flutter Your project requires a newer version of the Kotlin Gradle plugin 解决方案分两步: 1、在android/build.gradle里配置最新版本的kotlin 根据提示的kotlin官方网站搜到了Kotlin的最新版本是1.9.23,如下图所示: 同时在Ko…

python如何写入csv

在使用python对文件操作的过程中&#xff0c;你肯定碰到过对csv文件的操作&#xff0c;下面就python对csv文件的操作进行详述。 CSV&#xff08;Comma-Separated Values&#xff09;逗号分隔符&#xff0c;也就是每条记录中的值与值之间是用分号分隔的。 打开CSV文件并写入一…

实战项目——智慧社区(一)

1、项目介绍 系统功能 登录、修改密码、登出 &#xff08;1&#xff09;首页 &#xff08;1.1&#xff09;数据统计&#xff1a;小区人员统计对比图&#xff0c;占比图 &#xff08;2&#xff09;物业管理 &#xff08;2.1&#xff09;小区管理&#xff1a;小区数据的增删改…

在开发过程中使用 git rebase 还是 git merge

在开发过程中使用 git rebase 还是 git merge Merge(合并)的优点和缺点Rebase(变基)的优点和缺点总结&#xff1a; Git merge 和rebase的目的是一样的&#xff0c;它们都是将多个分支合并成一个。 虽然他们最终的目标是一样的&#xff0c;但这两种方法实现的方式是不同的。那么…

leetcode73 矩阵置零

题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用原地算法。 输入&#xff1a;matrix [[1,1,1],[1,0,1],[1,1,1]] 输出&#xff1a;[[1,0,1],[0,0,0],[1,0,1]] 输入&#xff1a;matrix [[0,1,2,0],[3,4…

【数据结构】单链表(一)

上一篇【数据结构】顺序表-CSDN博客 我们了解了顺序表&#xff0c;但是呢顺序表涉及到了一些问题&#xff0c;比如&#xff0c;中间/头部的插入/删除&#xff0c;时间复杂度为O(N);增容申请空间、拷贝、释放旧空间会有不小的消耗&#xff1b;增容所浪费的空间... 我们如何去解…

java数据结构与算法刷题-----LeetCode210. 课程表 II

java数据结构与算法刷题目录&#xff08;剑指Offer、LeetCode、ACM&#xff09;-----主目录-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/123063846 文章目录 深度优先遍历但不进行逆拓扑排序&#xff08;不用栈&#xff09;…

leetcode 343. 整数拆分

题目 给定一个正整数 n &#xff0c;将其拆分为 k 个 正整数 的和&#xff08; k > 2 &#xff09;&#xff0c;并使这些整数的乘积最大化。 返回 你可以获得的最大乘积 。 示例 1: 输入: n 2 输出: 1 解释: 2 1 1, 1 1 1。 示例 2: 输入: n 10 输出: 36 解释: 1…

记一次IP访问MySQL失败多次被自动锁定导致无法连接问题,解决方法只需一条SQL。

&#x1f469;&#x1f3fd;‍&#x1f4bb;个人主页&#xff1a;阿木木AEcru &#x1f525; 系列专栏&#xff1a;《Docker容器化部署系列》 《Java每日面筋》 &#x1f4b9;每一次技术突破&#xff0c;都是对自我能力的挑战和超越。 前言 今天下午还在带着耳机摸鱼&#xff…

Netty的基本架构与组件

Netty实战精髓 前言 Netty的组成部分 1、Channel 2、Callback 3、Future ChannelFuture 提供多个附件方法来允许一个或者多个 ChannelFutureListener 实例&#xff0c;这个回调方法 operationComplete() 会在操作完成时调用。 4、Event和Handler 5、EventLOOP Netty 通过触发…

如何在极狐GitLab 启用依赖代理功能

本文作者&#xff1a;徐晓伟 GitLab 是一个全球知名的一体化 DevOps 平台&#xff0c;很多人都通过私有化部署 GitLab 来进行源代码托管。极狐GitLab 是 GitLab 在中国的发行版&#xff0c;专门为中国程序员服务。可以一键式部署极狐GitLab。 本文主要讲述了如何在[极狐GitLab…

SSH穿透ECS访问内网RDS数据库

处于安全考虑&#xff0c;RDS一般只会允许指定的IP进行访问&#xff0c;而我们开发环境的IP往往是动态的&#xff0c;每次IP变动都需要去修改RDS的白名单&#xff0c;为我们的工作带来很大的不便。 那么如何去解决这个问题&#xff1f; 假如我们有一台ESC服务器&#xff0c;E…

STC89C52学习笔记(八)

STC89C52学习笔记&#xff08;八&#xff09; 综述&#xff1a;本文讲述了LED点阵屏以及如何进行数据串行输入&#xff0c;并行输出。 一、LED点阵屏 1.介绍 LED点阵屏由多个LED组成&#xff0c;以矩阵形式排列&#xff08;类似于矩阵键盘&#xff09;&#xff0c;像素一般…

CSS滚动条样式修改

前言 目前我们可以通过 CSS伪类 来实现滚动条的样式修改&#xff0c;以下为修改滚动条样式用到的CSS伪类&#xff1a; ::-webkit-scrollbar — 整个滚动条 ::-webkit-scrollbar-button — 滚动条上的按钮 (上下箭头) ::-webkit-scrollbar-thumb — 滚动条上的滚动滑块 ::-web…

了解大语言模型的参数高效微调(Parameter-Effcient Fine-Tuning)

&#x1f349; CSDN 叶庭云&#xff1a;https://yetingyun.blog.csdn.net/ 大语言模型在众多应用领域实现了突破性的进步&#xff0c;显著提升了各种任务的完成度。然而&#xff0c;其庞大的规模也带来了高昂的计算成本。这些模型往往包含数十亿甚至上千亿参数&#xff0c;需要…

Golang使用PGO优化程序性能

文章目录 参考文章PGO是什么使用PGO的好处PGO做了什么热函数内联什么是内联内联的好处Go默认的内联策略查看内联预算PGO的热函数内联 去虚拟化调用指令高速缓存 PGO有什么缺点可执行程序变大构建时间变长 PGO怎么使用典型的工作流程收集CPU配置文件生产环境启动PGO代码改动重新…