【Linux】自动化构建工具:make/Makefile

news2024/12/23 8:29:06

在这里插入图片描述

​👻内容专栏: Linux操作系统基础
🐨本文概括: 工具使用的背景、理解make/makefile工具、探索工作原理(文件修改时间的对比)、.PHONY伪目标、特性等。
🐼本文作者: 阿四啊
🐸发布时间:2023.9.14

背景

  • make” 和 “Makefile” 是用于自动化构建和编译软件项目的工具和文件。它们通常用于编译源代码并生成可执行文件,库文件或其他项目构建目标。
  • 一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂的功能操作。
  • makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率。
  • make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建。

理解

make

📌"make" 是一个命令行,用于构建项目。它根据一个称为 “Makefile” 的文本文件中的规则来确定需要构建哪些文件以及如何构建它们。“make” 工具的基本语法如下:

make [目标]

⚠️注:其中 “目标” 是您要构建的项目中的一个特定目标,例如生成可执行文件或库。如果不提供目标,则 “make” 将默认构建 Makefile 中定义的第一个目标。

Makefile

📌Makefile是一个文本文件,文件名首字母M一般建议大写,也可以写成makefile,其中包含构建项目的依赖关系和依赖方法。每个依赖关系都描述了如何生成一个目标文件以及哪些文件或其他目标是其依赖方法。Makefile 使用如下:

  • 规则指定了依赖关系依赖方法
  1. 我们用C语言写一个简单的code.c文件:
    在这里插入图片描述

  2. 以下是一个简单的示例 Makefile,用于构建一个名为 “mybin” 的可执行文件:

    1 mybin: code.c #指定了依赖关系
    2   gcc code.c -o mybin #依赖方法,比如以制表符开头。
    3 clean:
    4 	rm -f mybin
    

    示例中,"mybin"是目标,依赖于code.c,与code.c构成依赖关系。 依赖方法是构建“mybin”的命令:gcc code.c -o mybin(用gcc命令编译code.c文件)。“clean”是另一个目标,用于删除生成的可执行文件mybin

  3. 运行“make”命令,指定要构建的目标。(注:若不指定目标,系统将自动扫描Makefile中第一个目标)

    [Asi@localhost ~]$ make
    gcc code.c -o mybin
    

    运行"make clean"命令。

    [Asi@localhost ~]$ make clean
    rm -f mybin
    

工作原理

原理

  • 如果我们再次执行几次make命令,发现编译不了了,会报出以下错误:

    [Asi@localhost ~]$ make
    make: `mybin' is up to date.
    [Asi@localhost ~]$ make
    make: `mybin' is up to date.
    [Asi@localhost ~]$ make
    make: `mybin' is up to date.
    

    为什么会出现这样的问题呢?对于没有更改的code.c文件,系统会进行识别,不会再进行编译链接,到这可能有小伙伴们会问,这么一个小文件,对编译器来说不算什么吧?但是你们想想,若项目中有几百个上千个文件呢,程序翻译的过程的周期是非常长的,所以编译器会进行识别对于没更改过的源文件可以跳过,大大缩短编译的时间。所以make/Makefile可以提高编译效率!

  • 编译器是如何知道源文件是否被更改过呢?make是如何工作的?

    1. 源文件可执行程序时间的对比,就能体现源文件的新旧(重新编译会重新写入一个二进制可执行文件,其修改时间也会被修改)
    2. 第一次编译的时候,一定是源文件的修改时间 小于 可执行程序的修改时间,当我们对源文件做任何修改之后,源文件的修改时间就 大于 可执行程序的修改时间,然后进行程序编译之后,那么源文件的修改时间又 小于可执行程序的修改时间。

文件的修改时间(ACM时间)

下面,我们执行stat + [文件名]命令,可查看一个文件的修改时间
在这里插入图片描述

Access time(Atime):这是文件的最后一次访问时间。当文件被读取、浏览或访问时,Atime时间会被更新。
Modify time(Mtime):这是文件的最后一次内容上修改时间。Mtime的更新,很可能会和Ctime或者Atime联动更改。
Change time(Ctime):这是文件的最后一次属性上修改时间。Ctime的更新,其他时间基本不会更新。

  1. 我们尝试给源文件code.c修改他的任意属性,比如给所属组添加了执行权限,再次stat命令查看code.c的时间,发现与原来时间相比,修改文件权限,只改变了Ctime,其他时间则是保持不变。

    [Asi@localhost ~]$ ll
    total 36
    -rw-rw-r-- 1 Asi Asi  130 Sep 14 15:29 code.c
    [Asi@localhost ~]$ chmod g+x code.c
    

    在这里插入图片描述

  2. 下一步,我们试着修改一下code.c文件的内容,如下所示
    在这里插入图片描述
    我们可以发现,Mtime的更新,AtimeCtime发生了联动更改。

    在这里插入图片描述

  3. 然后,我们查看一下code.c文件,发现它的ACM时间都没有发生变化,再进行两次查看,时间也照样没有发生变化。

    [Asi@localhost ~]$ cat code.c
    #include <stdio.h>
    
    int main()
    {
        int i;
        for(i = 0; i <= 10; i++)
        {
          printf("num = %d\n",i);
        }
        printf("complete!\n");
      return 0;
    }
    [Asi@localhost ~]$ stat code.c
      File: ‘code.c’
      Size: 156       	Blocks: 8          IO Block: 4096   regular file
    Device: fd01h/64769d	Inode: 1063658     Links: 1
    Access: (0674/-rw-rwxr--)  Uid: ( 1003/     Asi)   Gid: ( 1003/     Asi)
    Access: 2023-09-14 15:39:11.012008120 +0800
    Modify: 2023-09-14 15:39:11.010008051 +0800
    Change: 2023-09-14 15:39:11.010008051 +0800
     Birth: -
    

    🤔💡:那么为什么会这样子呢?
    PS:一般而言,一个文件被查看的频率是最高的。而文件是存放到磁盘中的,访问、更改文件本质其实就是访问磁盘,那么每次访问更改access time就是访问磁盘,这会让Linux系统充满大量的访问磁盘的IO操作,简介地减缓系统效率。所以,一些编译器一般会配置减少文件atime的更新频率,以提高性能。

不修改内容,更新文件的修改时间

我们再次回到前面一个问题,系统究竟是根据三个时间中的哪个时间来进行源文件与可执行程序的对比呢?当然最合理的是Modify time(Mtime)。
所以我们这里再次去执行make命令,编译不了,其根本原因是因为code.c的Mtime早于mybin的Mtime!

[Asi@localhost ~]$ make
make: `mybin' is up to date.
[Asi@localhost ~]$ stat code.c
  File: ‘code.c’
  Size: 156       	Blocks: 8          IO Block: 4096   regular file
Device: fd01h/64769d	Inode: 1063658     Links: 1
Access: (0674/-rw-rwxr--)  Uid: ( 1003/     Asi)   Gid: ( 1003/     Asi)
Access: 2023-09-14 15:43:46.586536040 +0800
Modify: 2023-09-14 15:43:46.584535971 +0800
Change: 2023-09-14 15:43:46.584535971 +0800
 Birth: -
[Asi@localhost ~]$ stat mybin
  File: ‘mybin’
  Size: 8496      	Blocks: 24         IO Block: 4096   regular file
Device: fd01h/64769d	Inode: 1063645     Links: 1
Access: (0775/-rwxrwxr-x)  Uid: ( 1003/     Asi)   Gid: ( 1003/     Asi)
Access: 2023-09-14 16:09:31.152943398 +0800
Modify: 2023-09-14 16:09:31.152943398 +0800
Change: 2023-09-14 16:09:31.152943398 +0800
 Birth: -

所以我们可以通过对Mtime进行修改以更新文件的时间,那么除了修改源文件的内容,我们可以使用touch命令,对,你没看错,touch命令不仅仅可以创建一个新文件,它也可以去更新已存在文件的时间!

touch [文件名]:所有时间都更新
touch -a [文件名]:更新atime
touch -m [文件名]:更新mtime

[Asi@localhost ~]$ make
make: `mybin' is up to date.
[Asi@localhost ~]$ touch  -m code.c
[Asi@localhost ~]$ make
gcc code.c -o mybin
[Asi@localhost ~]$ make
make: `mybin' is up to date.
[Asi@localhost ~]$ touch code.c
[Asi@localhost ~]$ make
gcc code.c -o mybin

.PHONY

📌.PHONY 的主要作用是告诉 make 工具,不管是否存在对应的文件,总是执行这些目标中的命令,其依赖方法总是会被执行,不会被任何情况拦截。它用于指定一个伪目标(phony target)。

.PHONY: target_name
  • 样例测试:
    .PHONY指定了mybin为伪目标,所以我们执行make命令,无论是否存在可执行程序,始终会执行依赖方法相关联的命令。
    在这里插入图片描述
  • 结果:
    [Asi@localhost ~]$ make
    gcc code.c -o mybin
    [Asi@localhost ~]$ make
    gcc code.c -o mybin
    [Asi@localhost ~]$ make
    gcc code.c -o mybin
    [Asi@localhost ~]$ make
    gcc code.c -o mybin
    

项目清理

  • 在开发中,我们的工程会根据情况来清理的,像clean这种,没有被第一个目标文件直接或间接关联,那么它后面所定义的命令将不会被自动执行。
  • 不过,我们可以显示用make执行。即命令“make clean”,我们在测试时,以此来清理所有的目标文件,以便重新编译。

特性

用 make/makefile 写出整个程序的翻译过程

“make” 和 “Makefile” 具有依赖性的推导能力的。当运行make命令,make会自动检测依赖关系,mybin根据依赖关系去寻找code.o,如果code.o文件不存在,它不会执行依赖方法,回向下寻找code.o,如果向下没有找到code.o,编译器可能会报错,可能会隐式形成。那么code.o找到之后,它会根据依赖关系去寻找code.scode.s继续向下寻找……以此类推。直到找到code.c,执行依赖方法模块的命令之后形成code.i,然后在逆向回去扫描,执行其他尚未执行成功的依赖方法。此过程就如同入栈、出栈的过程,所以"make" 和 “Makefile” 就是根据这么一套逻辑执行完依赖关系和依赖方法。
在这里插入图片描述

执行结果

[Asi@localhost ~]$ make
gcc code.c -E -o code.i
gcc code.i -S -o code.s
gcc code.s -c -o code.o
gcc code.o -o mybin

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

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

相关文章

18.3 【Linux】登录文件的轮替(logrotate)

18.3.1 logrotate 的配置文件 logrotate 主要是针对登录文件来进行轮替的动作&#xff0c;他必须要记载“ 在什么状态下才将登录文件进行轮替”的设置。logrotate 这个程序的参数配置文件在&#xff1a; /etc/logrotate.conf /etc/logrotate.d/ logrotate.conf 才是主要的参…

无涯教程-JavaScript - ADDRESS函数

描述 给定指定的行号和列号,您可以使用ADDRESS函数获取工作表中单元格的地址。 如,ADDRESS(2,3)返回$C $2。再举一个Example,ADDRESS(77,300)返回$KN $77。您可以使用其他函数(如ROW和COLUMN函数)为ADDRESS函数提供行号和列号参数。 语法 ADDRESS (row_num, column_num, [a…

跨境电商和TikTok广告:突破地理界限的机会

随着全球数字化的快速发展&#xff0c;跨境电商已经成为了现代商业的关键驱动力。同时&#xff0c;TikTok作为一款全球范围内广受欢迎的社交媒体平台&#xff0c;也在商业领域崭露头角。 本文将探讨跨境电商如何与TikTok广告相结合&#xff0c;为企业提供突破地理界限的机会。…

苹果宣布9月26日发布全新macOS Sonoma系统 新增不少实用功能

苹果公司在召开的特别活动中&#xff0c;宣布将于 9 月 26 日正式发布 macOS Sonoma&#xff0c;用户可以打开“设置”->“通用”->“软件更新”路径进行更新&#xff0c;新版本主要增强空间函数、为 AirPods 测试自适应音频、个性化音量和对话感知等新功能。 macOS Sono…

1.0零基础尝试DCM通讯(c-store)

前言 本项目是对医院放疗及相关设备的互通互联。对dcm文件及数据协议是本项目的基础。 今天在项目组成员支持下,对dcm通讯进行了初步的尝试,有人之路,这个过程可以说是非常愉快,于是乎准备将这个愉快的过程记录,方便自己查阅和后来人。 c-store 本次的安装和测试使用的…

乔哈里视窗:助力项目团队高效沟通

项目研发通常涉及多个团队成员、不同的职能部门和利益相关者&#xff0c;如果干系人间缺乏沟通&#xff0c;缺乏对项目目标、需求的共识和理解&#xff0c;团队成员间容易产生隔阂和矛盾&#xff0c;无法有效协调和管理&#xff0c;导致项目无法按时交付、质量下降、成本增加等…

视频怎么压缩?把视频压缩的小一点这样做

视频压缩在我们的生活和工作中有着广泛的应用需求&#xff0c;是一种减少视频文件大小的方法&#xff0c;可以给我们带来以下几个方面的作用&#xff1a; 1、减少存储空间占用&#xff1a;视频压缩可以显著减少视频的大小&#xff0c;从而腾出更多的存储空间&#xff0c;对于手…

一套精简的springboot后台管理系统

概述 本后台管理系统&#xff0c;基于SpringBoot2.0 Spring Data Jpa Thymeleaf Shiro 开发的后台管理系统&#xff0c;采用分模块的方式便于开发和维护&#xff0c;拓展性高&#xff0c;可作为您后台开发的基础框架 详细 运行截图&#xff1a; 项目结构&#xff1a; 详细…

EndNote21 | 杂志输出样式(参考文献格式模板)下载及安装

EndNote | 杂志输出样式下载及安装 一、参考文献格式下载二、参考文献格式安装 在《 Endnote: 文献条目的添加编辑引用文献全称与缩写的互相转换》文章中&#xff0c;介绍了如何手动编辑杂志输出样式&#xff0c;本文主要介绍如何从官网快速下载并安装所需杂志输出样式。 一、…

程序单实例运行的一种实现

技术背景知识 来自《Windows核心编程》 创建自定义段 Section 来自《Windows核心编程》 举例&#xff08;获取当前总共运行的实例数&#xff09; 创建自定义段并设置属性 #include "stdafx.h" #include "MFCApplication1.h" #include "MFC…

恒运资本:三大利好来袭,人民币直线拉升!股市能否大反攻?

早盘&#xff0c;又有突发&#xff01; 9月15日&#xff0c;远洋集团在港交所公告&#xff0c;鉴于其流动性严重状况&#xff0c;经集团审慎考虑&#xff0c;将暂停其一切境外债款&#xff08;包含下述境外美元证券&#xff09;项下的付款&#xff0c;直至全体重组及╱或延期解…

JDK API文档地址(中文和英文)

JDK1.6 JDK 1.6 中文手册 JDK1.8 Java 8 中文版 - 在线API手册 - 码工具 Java 官方文档 |官方教程|Java 官方文档 API中文手册|Java 官方文档参考文档_w3cschool 网上还有很多百度网盘中也有 JDK17 https://doc.qzxdp.cn/jdk/17/zh/api/index.html 英文文档 所有版本 …

uniapp微信小程序地图实现周边

官方说明&#xff1a;小程序JavascriptSDK使用指南 - 微信小程序解决方案 | 腾讯位置服务https://lbs.qq.com/product/miniapp/jssdk/ 先申请腾讯地图的开发者密钥&#xff0c;申请地址&#xff1a;腾讯位置服务 - 立足生态&#xff0c;连接未来 申请密钥时&#xff0c;需要勾…

【MySQL基础|第三篇】--- 详谈SQL中的DQL语句

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【MySQL学习专栏】&#x1f388; 本专栏旨在分享学习MySQL的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 前言 DQL&…

浙江工商大学MBA项目哪些人在报考?职务、就业、薪资……

9月下旬到10月下旬是每一年全国研究生网上报名的时间&#xff0c;这段时间内很多MBA考生要确定自己最终一志愿报考的学校和专业&#xff0c;在浙江省内&#xff0c;如果不想报考浙江大学的话&#xff0c;那么其余还有8个MBA项目可以选择。本期杭州达立易考教育为大家整理了浙工…

使用 kind 搭建 Kubernetes学习环境

什么是 kind &#xff1f; kind &#xff08; Kubernetes in Docker &#xff09; 让 你 能 够 在 本 地 计 算 机 上 运 行 Kubernetes 。 使 用 这 个 工 具 需 要 你 安 装 Docker 或 者 Podman 。 kind 将 Kubernetes 所需要的所有组件&#xff0c; 全部部署在一个 Docker …

微信小程序 非机动车车辆充电维修管理系统

本课题要求实现一套非机动车车辆管理系统&#xff0c;系统主要包括&#xff08;管理员服务端和学生微信端、车辆管理员微信端、辅导员服务端、车辆管理员服务端、辅导员微信端&#xff09;六个模块功能。 设计并实现了非机动车车辆管理系统。系统选用java语言&#xff0c;应用S…

【Android取证篇】华为设备跳出“允许USB调试“界面方法的不同方法

【Android取证篇】华为设备跳出"允许USB调试"界面方法的不同方法 华为设备在鸿蒙OS3系统之后&#xff0c;部分设备启用"允许USB调试"方式会有所变化&#xff0c;再次做个记录—【蘇小沐】 1.实验环境 系统版本Windows 11 专业工作站版22H2&#xff08;2…

【送书活动】朋友圈大佬都去读研了,这份备考书单我码住了

前言 「作者主页」&#xff1a;雪碧有白泡泡 「个人网站」&#xff1a;雪碧的个人网站 「推荐专栏」&#xff1a; ★java一站式服务 ★ ★ React从入门到精通★ ★前端炫酷代码分享 ★ ★ 从0到英雄&#xff0c;vue成神之路★ ★ uniapp-从构建到提升★ ★ 从0到英雄&#xff…

AIGC做题能力谁家强呢?

通义千问刚发布了&#xff0c; 想和文心一言比较一下&#xff0c;就简单的问了三个问题 1 挖了个坑的鸡兔同笼问题&#xff0c;12个头35个脚的情况求解。 通义千问能意识到鸡兔脚都是偶数&#xff0c;计算出现小数点就自动舍弃了&#xff0c;结果就是7鸡5兔一共34只脚。 拒绝…