【Linux】项目自动化构建工具make/makefile

图片名称
🎉博主首页: 有趣的中国人

🎉专栏首页: Linux

🎉其它专栏: C++初阶 | C++进阶 | 初阶数据结构

在这里插入图片描述

小伙伴们大家好,本片文章将会讲解Linux项目自动化构建工具make/makefile的相关内容。


如果看到最后您觉得这篇文章写得不错,有所收获,麻烦点赞👍、收藏🌟、留下评论📝。您的支持是我最大的动力,让我们一起努力,共同成长!

文章目录

  • 1. 何为make/makefile
  • 2. make/makefile的原理
  • 3. makefile中的变量以及自动显示问题
  • 4. makefile 目标文件的生成顺序



1. 何为make/makefile


当谈到在Linux中进行项目构建时,makemakefile是两个非常重要的工具。它们提供了一种自动化构建的方法,使得开发者能够轻松地编译和构建复杂的软件项目。下面我会分别介绍一下makemakefile


⏳ make 简介⌛

make 是一个命令行工具(指令),用于自动化构建程序或项目。它通过读取一个称为 makefile 的文件来确定构建项目所需的步骤。make工具的核心理念是根据文件之间的依赖关系以及每个文件的修改时间,决定哪些文件需要重新编译,从而实现高效的构建。


⏳ makefile 简介⌛

makefile 是一个文本文件,其中包含了一系列规则和命令,用于指导 make 工具如何构建项目。makefile 定义了项目中的各种组件(例如源文件、目标文件和依赖关系),以及如何将它们组合在一起以生成最终的可执行文件或库文件。



2. make/makefile的原理


⏳ 我们先来看一个例子:⌛

  1. 首先新建一个名为code.c的文件,并写入一段简单的代码:
# 新建名为code.c的文件 [dsj@alicloud-dsj lesson11]$ touch code.c  # code.c中所输入的代码#include <stdio.h> int main(){ 	 int i = 0; 	 for (i = 0;i < 10; ++i) 	 {printf("%d\n",i); 	} 	 return 0; } 
  1. 新建一个名为makefile或者Makefile的文件,并在其中输入以下代码:

在这里插入图片描述

code.exe:code.c 	gcc -o code.exe code.c.PHONY: clean clean: 	rm -f code.exe 

  1. 退出,并依次输入makemake clean指令:

输入make指令:

在这里插入图片描述

[dsj@alicloud-dsj lesson11]$ ll total 20
-rw-rw-r-- 1 dsj dsj  116 May  9 21:33 code.c
-rwxrwxr-x 1 dsj dsj 8360 May  9 21:38 code.exe
-rw-rw-r-- 1 dsj dsj   79 May  9 21:36 makefile 

输入make clean指令:
在这里插入图片描述

⏳ 原理解释⌛

看完之后我们可能对make/makefile有以下几点疑问:

1. makefile文件中的代码是什么意思;

2. 为什么输入make就能生成code.exe的文件,而不是 make code.exe


接下来我来一一解释这几个问题:


问题1:makefile文件中的代码是什么意思:

在这里插入图片描述
在这里插入图片描述

我们把code.exe 称为目标文件code.c称为依赖关系,下面的指令gcc -o code.exe code.c称为依赖方法

目标文件(targets)指定要构建的文件或操作的名称。这可以是可执行文件、目标文件、清理操作等。

依赖关系(Dependencies )指定每个目标所依赖的文件或操作。如果某个目标的依赖文件发生了变化,那么该目标就需要重新构建。有时,依赖关系可以省略依赖关系也可以有多个

依赖方法(Commands)指定 make 工具执行的操作步骤。这些操作通常是编译源代码、链接目标文件、复制文件等有时可以有多个依赖方法


这个搞明白了,那clean这个目标文件前面一行的.PHONY又是什么意思呢?


在这里插入图片描述


我们先了解一个概念:makefile中的操作默认是只执行一次的,因为这样可以提高编译的效率

.PHONY.PHONY 是告诉 make 工具,该目标不是实际的文件,而是一个动作或操作,并且这个操作总是要被执行的。

总是要执行的意思就是只要你输入了指令make clean这个指令那么对应的操作方法就要被执行。


那么问题又来了,只执行一次是怎么做到的呢?


  1. 首先我们可以用命令 stat [filename] 来查看一个文件的修改时间
  2. 其次,对于每个要生成的目标文件要依赖于依赖关系,而我们也可以查看这些依赖关系中的文件的修改时间,也可以查看目标文件的修改时间
  3. 如果 目标文件修改时间 先于 依赖文件的修改时间,说明依赖文件在编译后进行了修改,那么执行make指令,重新生成一个目标文件
  4. 反之,如果 目标文件修改时间 晚于 依赖文件的修改时间,说明依赖文件并没有进行修改,那么执行make指令 不会 重新生成一个目标文件

那我们来验证一下,看一下下面的例子吧:

目标文件 修改时间 晚于 依赖文件 修改时间的例子:

在这里插入图片描述

目标文件 修改时间 早于 依赖文件 修改时间的例子:

在这里插入图片描述


问题2: 为什么输入make就能生成code.exe的文件,而不是make code.exe


因为make指令会默认生成 makefile 中的第一个目标文件。但是输入make code.exe也是可以的。

在这里插入图片描述



3. makefile中的变量以及自动显示问题


makefile中我们可以用$@来代替目标文件$^来代替依赖关系文件,例如:

在这里插入图片描述

也是可以编译通过的😁!
在这里插入图片描述

makefile中也是可以出现变量的,但是这里的变量和其他编程语言有些不同,先看个例子吧:

注意定义变量的时候不能出现空格,除非依赖多个文件!
在这里插入图片描述
也是可以编译通过的😁!
在这里插入图片描述

我们发现在每次输入make指令的时候都会打印出他所执行的指令,例如:


在这里插入图片描述


我们可以修改相关的`makefile`代码,只需要在每个依赖方法之前加上`@`符号即可,使得它不出现:

不加@符号:

在这里插入图片描述


make一下会发现他把他所执行的指令和我们要让他打印的东西一起打印了:
在这里插入图片描述
@符号:

在这里插入图片描述

make一下会发现他并没有把他所需要执行的指令打印出来,只打印了我们让他打印的东西:
在这里插入图片描述



4. makefile 目标文件的生成顺序


看一下这个makefile文件:

在这里插入图片描述

源码:

code.exe: code.sgcc -o $@ $^
code.o: code.sgcc -o $@ -c $^
code.s: code.igcc -o $@ -S $^
code.i: code.cgcc -o $@ -E $^.PHONY:clean
clean:rm -f code.i code.s code.o code.exe

如果我们直接make,由于找不到依赖文件code.s,但是此时不会停止执行,会继续向下寻找,但是向下找到了code.o文件,但是它的依赖文件是code.s文件,因为此时没有code.c文件,会继续向下寻找……
可以发现,这类似于递归的一个过程,没找到就会继续递归,直到找到为止。
当然如果最后还是找不到需要的依赖文件就会报错。

报错示例:

在这里插入图片描述

在这里插入图片描述

🤔当然,由于make指令默认生成的是第一个目标文件,所以指挥生成和第一个目标文件相关的内容,我们可以改一下顺序来验证一下,咱们将.o放在第一个:


在这里插入图片描述

在这里插入图片描述

🤔那如果咱们再改一下顺序,把.o需要的.s文件不放在直接顺序上的下一个会怎么样呢?


在这里插入图片描述

🤔可以发现还是可以的,不会报错。


在这里插入图片描述


🐼所以说,只要makefile文件中给出了所需要的依赖文件,make都能帮你找到,不会报错🎋

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

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

相关文章

单链表经典oj题(2)

前言 这次将要把剩下的oj题将以图解和自己的理解把它讲解完&#xff0c;希望对大家有所帮助&#xff0c;这次的讲解也是干货 第一题 21. 合并两个有序链表 - 力扣&#xff08;LeetCode&#xff09; ok这次就简单点&#xff0c;大家自己去看题目了 将两个升序链表合并为一个…

Ubuntu18.04--虚拟机配置Samba并从Windows登录

前言&#xff1a; 本文记录我自己在Windows上安装 Virtualbox &#xff0c;并在Virtualbox中安装 Ubuntu-18.04 虚拟机&#xff0c;在Ubuntu-18.04虚拟机里安装配置Smaba服务器&#xff0c;从 Windows 宿主系统上访问虚拟机共享samba目录的配置命令。 引用: N/A 正文 虚拟…

​​​【收录 Hello 算法】5.1 栈

目录 5.1 栈 5.1.1 栈的常用操作 5.1.2 栈的实现 1. 基于链表的实现 2. 基于数组的实现 5.1.3 两种实现对比 5.1.4 栈的典型应用 5.1 栈 栈&#xff08;stack&#xff09;是一种遵循先入后出逻辑的线性数据结构。 我们可以将栈类比为桌面上的一摞盘子…

Linux diff命令(比较两个文件或目录的内容差异)

文章目录 Linux diff 命令详解教程基本用法比较文件输出解释 递归比较&#xff08;-r&#xff09;示例代码 控制输出格式统一格式&#xff08;-u&#xff09;上下文格式&#xff08;-c&#xff09; 高级选项忽略所有空白差异&#xff08;-w&#xff09;仅报告文件是否不同 Linu…

SVN 合并到 Git 时有文件大于 100 M 被限制 Push

如果有文件大小大于 100M&#xff0c;GitHub 是会被限制推送到仓库中的&#xff0c;大概率情况会显示下面的错误&#xff1a; remote: Resolving deltas: 100% (3601/3601), done. remote: error: Trace: aea1f450da6f2ef7bfce457c715d0fbb9b0f6d428fdca80233aff34b601ff59b re…

RobbitMQ基本消息队列的消息发送过程

RabbitMQ: One broker to queue them all | RabbitMQ RabbitMQ官网 SpringAmqp的官方地址&#xff1a;Spring AMQP 代码示例:对着代码看应该能看明白 publisher:消息发送者的代码示例 package cn.itcast.mq.helloworld;import com.rabbitmq.client.Channel; import com.rabb…

线路和绕组中的波过程(一)

本篇为本科课程《高电压工程基础》的笔记。 本篇为这一单元的第一篇笔记。下一篇传送门。 当电路中的设备&#xff08;元件&#xff09;最大实际尺寸l大于人们所感兴趣的谐波波长 λ \lambda λ时&#xff0c;可以作为集中参数处理&#xff0c;否则就要当做分布参数处理。即&…

基于STM32移植lvgl(V8.2)(SPI接口的LCD)

目录 概述 1 认识LVGL 1.1 LVGL官网 1.2 LVGL库文件下载 2 认识SPI接口型LCD 2.1 PIN引脚定义 2.2 MCU IO与LCD PIN对应关系 3 实现LCD驱动 3.1 使用STM32Cube配置Project 3.2 STM32Cube生成工程 4 移植LVGL 4.1 准备移植文件 4.2 添加lvgl库文件到项目 4.2.1 src下…

linux fdisk 银河麒麟操作系统 v10 磁盘分区和挂载 详细教程

1查看 未加载的磁盘 fdisk -l 2 开始分区 fdisk /dev/vdb #查看分区 #新建分区和保存 3 格式化和挂载 fdisk -l mkfs.xfs /dev/vdb1 #查看uuid blkid /dev/vdb1 mkdir /data vi /etc/fstab UUID209daa-fb1c-48f2-bf5e-e63f38cb8a /data xfs defaults 0 0 #加载下 mo…

探秘未来科技:数字化无人巡检的奇妙之旅

嘿&#xff0c;朋友们&#xff01;下午茶时间到&#xff01;趁着这会儿咱们来聊一个超级炫酷的话题——数字化无人巡检。想象一下&#xff0c;那些曾经需要人工跋山涉水、风吹日晒的巡检工作&#xff0c;现在正被一群“智能小分队”悄悄接手&#xff0c;是不是觉得既神奇又方便…

Ascent DMS AE电源说明书和设备连接调试教程

Ascent DMS AE电源说明书和设备连接调试教程

彩虹聚合DNS管理系统

聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析&#xff0c;目前已支持的域名平台有&#xff1a;阿里云、腾讯云、华为云、西部数码、CloudFlare。本系统支持多用户&#xff0c;每个用户可分配不同的域名解析权限&#xff1b;支持API接口&#xff0c;支持获取域名…