【Linux学习笔记】 - 项目自动化工具make/Makefile的使用

news2024/11/29 20:31:48

一、背景知识

会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。一个工程中的源文件不计其数,其按类型、功能、模块分别放在若干个目录中。makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作

makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。

make是一个命令工具,是一个解释makefile中指令的命令工具;
make是一条命令makefile是一个文件,两个搭配使用,完成项目自动化构建。

二、使用方法

1、基本使用流程

(1)先在当前目录利用touch指令建立一个名为makefile或Makefile的文件
在这里插入图片描述
(2)提前用vim编辑器在同目录下建立好一个.c源文件用于测试
在这里插入图片描述

(3)接着再通过vim编辑器,在Makefile文件中写上相应的依赖关系和依赖方法(后文会解释这两个名词)
在这里插入图片描述

(4)最后执行make命令后,会执行makefile文件中对应的依赖方法,生成了一个可执行文件,能执行并正确输出
在这里插入图片描述
在这里插入图片描述
(5)也可执行make clean的命令用于对可执行文件的清理,因为更改代码后,可执行文件需要重新生成
在这里插入图片描述

由上可得,Makefile文件中的内容可抽象为:

依赖关系名: 依赖对象名
	依赖方法

补充使用技巧:
可用特殊符号$@$^分别表示冒号左边和右边内容,如:

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

就可写为:

testcode: testcode.c
	gcc testcode.c -o testcode

在依赖方法前加上@后,make依赖关系后,对应的依赖方法不会回显。
(PS:make指令使用的完整格式应为make+Makefile中写的依赖关系名;省略时默认执行第一个依赖关系

2、相关名词

下面对基本使用流程中出现的名词做一下说明:
(1)依赖关系
如上流程(3)中标记所示,其中的testcodeclean都称作依赖关系;不同的是testcode有具体的依赖对象(一般都是文件,故也可称为依赖文件),而clean没有。

testcode: testcode.c

如上就表示testcode依赖于testcode.c
(2)依赖方法
如上流程(3)中标记所示,依赖关系下的一条指令就是该依赖关系所对应的依赖方法。make+依赖关系时就会执行依赖方法部分的指令内容;故语句的执行

testcode: testcode.c
	gcc testcode.c -o testcode

就可理解为:testcode依赖于testcode.c,当依赖关系testcode被make时,make会在与Makefile同目录下去找相应的依赖对象,也就是testcode.c;若找到,则执行相应的依赖方法;否则直接报错

三、相关原理

1、执行原理

若有如下这么几组依赖关系:
PS:这里根据编译链接过程特意写复杂进行验证,实际直接gcc生成可执行文件即可

  1 testcode : testcode.o
  2   gcc testcode.o -o testcode 
  3 testcode.o : testcode.s
  4   gcc -c testcode.s -o testcode.o
  5 testcode.s : testcode.i
  6   gcc -S testcode.i -o testcode.s
  7 testcode.i : testcode.c
  8   gcc -E testcode.c -o testcode.i 

其中的依赖关系是:
testcode依赖于testcode.otestcode.o依赖于testcode.s
testcode.s依赖于testcode.itestcode.i依赖于testcode.c

执行make之后:
在这里插入图片描述
可以看到,系统会先找到文件Makefile,再从文件中搜索依赖关系按各组依赖关系间的彼此依赖顺序执行依赖方法。如上就会先执行gcc -E testcode.c -o testcode.i 生成test.i,然后根据依赖关系逐步执行其他相关依赖方法,直至生成最终目标testcode
(PS:这四组依赖关系的顺序可以打乱,打乱之后如果想生成testcode的可执行文件而该组依赖关系又不在Makefile文件的最开始时,就需把make命令写成:make testcode。因为前面说过啦,make后不加依赖关系默认执行的是第一个依赖关系

下面还有一个问题:
为什么make一次就不能make了
在这里插入图片描述

解答:我们平常编译的代码量都不大,编译耗时很短,但在实际工程中大文件中,代码量动辄就是百万行量级的,此时编译就需要很长时间。故make会根据一定的检查来决定是否需要重新执行依赖关系对源文件重新进行编译。

那么这个检查是否可以重新编译的依据就是文件的时间属性
即:如果我们更改了源文件,目录中若还有该源文件在更改前曾生成过的可执行文件,那么源文件的最近修改时间一定会比可执行文件要新

进一步说明前先补充一下关于文件时间的相关知识:
文件时间可分为三类:

  • Access访问文件的时间
  • Modify修改文件内容的时间
  • Change修改文件属性的时间

可用stat指令查看文件的这三类时间:
在这里插入图片描述
可以发现,源文件的三类时间都比可执行文件要早,或者说比可执行文件更旧(其实主要比较的是修改时间),所以无法重新进行编译。

当我们用touch指令将源文件时间属性全都更改至最新时间后,此时源文件的时间就比可执行文件的时间更新了,就可以通过make重新编译了:
在这里插入图片描述

如果我想无论什么情况都能执行相应的依赖关系下的依赖方法呢
可以通过伪目标关键字.PHONY实现,这个关键字一般用于clean等用于做清理工作的依赖关系,如下:

   .PHONY:clean
   clean:
     rm -rf testcode

那么最后总结一下make在用于自动化编译的原理:
(1)make会先在当前目录下找名字叫“Makefile”或“makefile”的文件。
(2)如果存在对应文章,它接着会在文件中找对应make指令后的依赖关系,若省略则默认是第一个依赖关系,并把这个依赖关系作为最终的目标文件,在上面的例子中就是testcode
(3)如果文件testcode(最终目标文件)不存在,或是其依赖对象即冒号后面的文件的文件修改时间属性要比其文件新(即代表源代码最近修改过,需重新生成可执行程序),那么,他就会执行后面所定义的命令来生成testcode这个文件。
(4)如果testcode所依赖的文件不存在,那么make会在当前文件中找目标为该依赖文件的依赖对象,如果找到,则再根据那一个规则生成对应的文件。(如上面的从.c到.i到.s再到.o文件,这有点像一个函数跳转建立堆栈的过程)。这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。
(5)在找寻的过程中,如果出现错误,比如最后被依赖的文件找不到或依赖方法中命令错误、源文件编译不成功等,那么make就会直接退出,并报错

本章完。

看完觉得有觉得帮助的话不妨点赞收藏鼓励一下,有疑问或看不懂的地方或有可优化的部分还恳请朋友们留个评论,多多指点,谢谢朋友们!🌹🌹🌹

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

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

相关文章

芯片学习记录SN74AHC1G14DBV

SN74AHC1G14DBV 芯片介绍 SN74AHC1G14器件是单个逆变器门。该器件执行布尔函数Y /A.The器件作为独立的逆变器门发挥作用,但由于施密特作用,门可能对正(VT)和负(VT−)信号具有不同的输入阈值电平。 引脚信…

07测试Maven中依赖的范围,依赖的传递原则,依赖排除的配置

依赖的特性 scope标签在dependencies/dependency标签内,可选值有compile(默认值),test,provided,system,runtime,import compile:在项目实际运行时真正要用到的jar包都是以compile的范围进行依赖 ,比如第三方框架SSM所需的jar包test:测试过程中使用的j…

大数据基础技能入门指南

本文介绍了数据工作中数据基础和复杂数据查询两个基础技能。 背景 当下,不管是业务升级迭代项目,还是体验优化项目,对于数据的需求都越来越大。数据需求主要集中在以下几个方面: 项目数据看板搭建:特别是一些AB实验的看…

【算法练习Day20】修剪二叉搜索树将有序数组转换为二叉搜索树把二叉搜索树转换为累加树

​📝个人主页:Sherry的成长之路 🏠学习社区:Sherry的成长之路(个人社区) 📖专栏链接:练题 🎯长路漫漫浩浩,万事皆有期待 文章目录 修剪二叉搜索树将有序数组转…

Grade 5 Math

数形结合 5 2 3 https://download.csdn.net/download/spencer_tseng/88431286

深入理解 Java 中的 synchronized 关键字

引入多线程的重要性和挑战 可以参考另一篇文章 https://blog.csdn.net/qq_41956309/article/details/133717408 JMM(Java Memory Model,Java 内存模型) 什么是JMM JMM(Java Memory Model,Java 内存模型&#xff09…

怎么在抖音上引流?分享五个抖音引流推广必备的几个方法

大家好,我是 小刘今天为大家分享的是抖音引流知识分享,今天咱们聊一些干货知识,绝对会让你们有一个重新的认知。抖音的流量大,是毋庸置疑的,抖音也是最早一批短视频平台。抖音于2017年上线,一开始主要是通过…

Golang学习记录:基础知识篇(一)

Golang学习:基础知识篇(一) 前言什么是Golang?Go语言的基础语法语言结构基础语法数据类型基础使用 前言 很久之前就想学Go语言了,但是一直有其他东西要学,因为我学的是Java嘛,所以后面学的东西…

配置VScode开发环境-CUDA编程

如果觉得本篇文章对您的学习起到帮助作用,请 点赞 关注 评论 ,留下您的足迹💪💪💪 本文主要介绍VScode下的CUDA编程配置,因此记录以备日后查看,同时,如果能够帮助到更多人&#xf…

操作系统导论-第四章作业(待更)

一、进程 进程就是运行中的程序,程序本身是没有生命周期的,它只是存储在磁盘上的一些指令(或者一些静态数据),操作系统将这些指令和数据加载到内存中,使其运行起来。 1.1 虚拟化CPU技术 根据我们平时使用…

基于Java的共享充电宝管理系统设计与实现(源码+lw+部署文档+讲解等)

文章目录 前言具体实现截图论文参考详细视频演示为什么选择我自己的网站自己的小程序(小蔡coding)有保障的售后福利 代码参考源码获取 前言 💗博主介绍:✌全网粉丝10W,CSDN特邀作者、博客专家、CSDN新星计划导师、全栈领域优质创作…

AI时代助力程序员与项目经理的双翼飞翔:从开发到成长的秘诀

❤️作者主页:小虚竹 ❤️作者简介:大家好,我是小虚竹。2022年度博客之星评选TOP 10🏆,Java领域优质创作者🏆,CSDN博客专家🏆,华为云享专家🏆,掘金年度人气作…

企业网盘中支持在线编辑的有哪些选项?

企业网盘作为现代企业不可或缺的工具之一,为企业提供了便捷的文件存储和共享功能。而其中支持在线编辑的解决方案更是减少了对额外软件的依赖,使团队成员可以直接在浏览器中进行实时协作。 什么是在线编辑? 在线编辑是指用户无需下载文件&a…

3D 生成重建008-zero123让扩散模型了解空间信息zero-shot 单图生3d

3D 生成重建008-zero123让扩散模型了解空间信息zero-shot 单图生3d 文章目录 00 论文工作1 论文方法1.1 条件生成微调1.2 维护3d表示 2 效果 0 0 论文工作 之前分享的工作主要尝试是从一个pre-trained 文生图的diffusion模型中去蒸馏知识,从而去维护一个3d的表示…

数据结构上机实验——栈和队列的实现、栈和队列的应用、进制转换、约瑟夫环问题

文章目录 栈和队列上机实验1.要求2.栈的实现(以顺序栈为例)3.队列的实现(以顺序队列为例)4.利用栈实现进制转换5.利用队列解决约瑟夫环问题6.全部源码Stack.hQueue.htest.cpp 栈和队列上机实验 1.要求 1.利用栈的基本操作实现将任…

docker-compose部署elk(8.9.0)并开启ssl认证

docker部署elk并开启ssl认证 docker-compose部署elk部署所需yml文件 —— docker-compose-elk.yml部署配置elasticsearch和kibana并开启ssl配置基础数据认证配置elasticsearch和kibana开启https访问 配置logstash创建springboot项目进行测试kibana创建视图,查询日志…

李宏毅生成式AI课程笔记(持续更新

01 ChatGPT在做的事情 02 预训练(Pre-train) ChatGPT G-Generative P-Pre-trained T-Transformer GPT3 ----> InstructGPT(经过预训练的GPT3) 生成式学习的两种策略 我们在使用ChatGPT的时候会注意到,网站上…

2023/10/15

文章目录 1.uniapp之Vue2升Vue3值得注意的几点1.1 页面生命周期的使用1.2 引入资源的方式 2. 浏览器本地存储之Cookie和webStorage3. CSS变量 var()的用法4. CSS之实现线性渐变背景5. 图片无法和文字对齐的正确解决方案6. 使用正则处理接口返回的富文本内的图片7. transition实…

Java练习题-获取数组元素最大值

✅作者简介:CSDN内容合伙人、阿里云专家博主、51CTO专家博主、新星计划第三季python赛道Top1🏆 📃个人主页:hacker707的csdn博客 🔥系列专栏:Java练习题 💬个人格言:不断的翻越一座又…

[cpp primer随笔] 11. 内联函数与constexpr函数

1. 内联函数 调用函数一般比对等价表达式求值要慢。因为调用函数除了对表达式求值外,还包含一系列过程,包括堆栈建立、拷贝实参、跳转执行等等。而在程序之中,通常存在一些优化规模较小、流程直接、却调用频率很高的函数,我们可以…