【Linux】make/Makefile --- 自动化构建项目的工具

news2024/11/17 14:31:23

目录

一、make/Makefile的简单使用

二、Makefile 的语法规则

三、实现的原理

3.1 make/Makefile识别文件新旧

3.2 .PHONY修饰的伪目标总是被执行

3.3 make/Makefile是具有依赖性的推导能力的

四、语法技巧

五、注意事项


Linux中自动化构建项目最简单的方式:make/Makefile
make:是一个命令
Makefile:是一个在当前目录下存在的一个具有特定格式的文本文件。
(Makefile首字母可以小写,但建议使用大写)

makefile文件中,保存了编译器和链接器的参数选项,并且描述了所有源文件之间的关系。make程序会读取makefile文件中的数据,然后根据规则调用编译器,汇编器,链接器产生最后的输出。

一、make/Makefile的简单使用

  • 创建Makefile
    touch Makefile
  •  编写Makefile:
    vim Makefile
  • 编写要生成的可执行程序mybin和项目清理clean:
  • 使用make命令生成可执行程序
    make
  • 使用make命令进行项目清理
    make clean

二、Makefile 的语法规则

Makefile 中包括依赖关系(目标依赖)依赖方法(命令)
下面是 Makefile 中一些要素的基本语法规则:

目标:指定了要生成的文件或要执行的操作名。

例如:上面的mybin就是要生成的目标文件名

依赖:指定了目标所依赖的文件或其他目标。

例如:上面的test.c 是目标文件依赖的文件。一个目标文件可以有多个依赖文件,用空格分开。
目标和依赖构成了依赖关系

命令(依赖方法):包含了生成目标所需的具体操作步骤,通常是一条或多条 Shell 命令。

第二行必须以Tab开头,不能是空格,紧接着是生成目标文件的命令。

例如:上面的gcc test.c -o mybin -std=c99
(gcc test.c -o mybin 与gcc -o mybin test.c 相同,-o后面跟目标文件名即可)

伪目标:伪目标是指在 Makefile 中.PHONY定义的不对应实际文件的目标,通常用于执行一些特定的操作,比如清理临时文件。 
例如:上面的clean目标用于执行清理操作,删除mybin文件。
注:make默认执行的是第一行的命令,一般把清理工作放在最后面。

注释:使用 # 符号来添加注释,注释从 # 开始一直到该行的末尾。

变量:可以使用变量来存储命令选项、编译器名称等信息,然后在规则中引用这些变量。
语法格式:VAR_NAME = value

条件判断:可以使用条件判断(ifeq、ifdef 等)来根据不同的条件执行不同的命令。

函数:Makefile 支持一些内置函数,可以用于字符串处理、文件查找等操作。

使用make和make clean,就可以方便地完成项目自动化构建和清理。

三、实现的原理

3.1 make/Makefile识别文件新旧

make命令不是每次都会重新编译,只有更改过的文件才会重新编译。(提高编译效率)
若源代码没有更改也重新编译,那么每次预处理编译汇编链接的时间比较长,成本高。

make/Makefile是如何知道文件更改过的?
答:通过源文件的修改时间和形成的可执行程序(也是文件)的修改时间做对比

重新编译的本质:重新写入一个二进制的可执行文件(bin文件),文件的修改时间会跟着更改。

  • 第一次的时候,一定是先有源文件,才有bin文件。
    源文件的修改时间 < bin文件的修改时间
  • 第二/n次的时候,我们对源文件做任何修改的时候,
    源文件的修改时间 > bin文件的修改时间
    ​​​​​
    重新编译形成可执行

大部分情况下重新编译都没问题,问题的产生不仅仅是修改新文件就能解决的。有些历史问题需要重新清理项目才可以解决。

文件 = 内容 + 属性,所以文件的ACM时间肯定与内容或属性有关。

Access(最近访问时间):普通文本文件打开:cat、vim,或者对目录进入、ls显示等

Modify (对内容修改):当文件内容发生变化时,修改时间(mtime)会被更新。

Change(对属性修改):当文件的权限、所有者、链接数或文件名发生变化时,更改时间(ctime)会被更新。

注:

  • 三种时间会出现联动,例如对内容修改,Access和Change时间也会更改。
  • Access时间不是每次访问时都更改,读取查看文件操作最频繁,如果每次都改的话,比较浪费时间,因为文件一般都在磁盘存放,更改时间的本质就是访问磁盘。但是访问磁盘的速度比较慢(相对cpu而言),读取查看文件操作又是很频繁,如果每次都更改Access time的话,系统效率就会降低很多,所以就会隔一段时间更改一次。
    (具体间隔时间和是否间隔,由内核版本决定)
  • 使用touch命令可以修改ACM时间。
    -a 选项  修改Access时间,但同时也修改了change时间,因为access时间也是属性。
    -m 选项 修改Modify时间,但是Change时间也会跟着改。

综上,make 是通过对比源文件和bin文件的Modify时间确定文件新旧的。

3.2 .PHONY修饰的伪目标总是被执行

通过时间对比,可以做到不让有些代码进行重新编译(不让某些操作进行)。

总是被执行就是:不考虑其他任何问题,总是执行依赖方法,不会被任何情况拦截
(make/makefile不再依靠时间对比了,直接执行对应的命令)

例如:mybin被.PHONY修饰,则多次make时,都会执行gcc命令,把可执行程序重新形成。

3.3 make/Makefile是具有依赖性的推导能力的

上一节讲到gcc编译生成一个可执行程序需要经过预处理、编译、汇编和连接,中间会产生.i,.o,.s文件。但是在上面的操作中都没有生成中间文件。
但是我们知道一件事:生成bin文件,就需要对应的.o文件。

以Makefile的推导过程如下:(类似一个栈结构)

生成了临时文件 code.o code.s code.i

以上写法只是为了了解编译推导的过程,实际上不推荐使用。

建议直接用gcc形成可执行!


四、语法技巧

  1. Makefile里面的指令执行时会自动回显出来,可以在前面加上 符号使其不回显,不显示指令信息。
  2. 可以使用 echo 添加一些输出信息。
  3. 依赖方法可以不止一个,用回车隔开。
  4. makefile中用 注释
  5. makefile中可以编写变量,表达式之间不建议带空格
    通过 $(变量名) 来引用变量的值。

    用途:之后如果想使用g++,只需要把gcc改成g++,mybin改成mybin.exe
  6. 可以用 #^ 符号代替依赖关系中的所有内容,#@ 代替要形成的目标文件

 


五、注意事项

  • 首次make时,make扫描Makefile文件时,自顶向下。如果发现第一个目标文件,则尝试根据该目标及其依赖关系构建目标文件。(默认一次形成一个最终的目标文件)
  • 伪目标文件没有实际的依赖关系,每次都会执行其定义的命令,而不是构建文件。
  • Makefile里主要包含了五个东西:显式规则、隐晦规则、变量定义、文件指示和注释。
    显式规则说明了,如何生成一个或多个目标文件。
  • make有自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写makefile,比如源文件与目标文件之间的时间关系判断。
  • 在makefile中可以定义变量,当makefile被执行时,其中的变量都会被扩展到相应的引用位置上,通常使用 $(var) 表示引用变量。
  • 文件指示。在一个makefile中引用另一个makefile,类似C语言中的include;
    ".mk" 是用来表示 Makefile 文件的扩展名。
    include path/to/another_makefile.mk
    
    target: dependency
        command
    
  • 注释,makefile中可以使用 # 在行首表示行注释
  • 默认的情况下,make命令会在当前目录下按顺序找寻文件名为"GNUmakefile"、"makefile"、"Makefile"的文件。

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

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

相关文章

shiro Filter加载和执行 源码解析

一、背景 在使用若依框架&#xff08;前后端不分离包含shiro安全框架&#xff09;时&#xff0c;发现作者添加了验证码、登录帐号控制等自定义过滤器&#xff0c;于是对自定的过滤器加载和执行流程产生疑问。下面以验证码过滤器为例&#xff0c;对源码解析。注意类之间的继承关…

Kubernetes入门笔记 ——(3)理解pod对象

为什么需要pod 最为熟知的一句话&#xff1a;pod是k8s的最小调度单位。刚开始听到这句话时会想&#xff0c;已经有容器了&#xff0c;k8s为什么还要搞个pod出来&#xff1f;容器和pod是什么关系&#xff1f;容器的本质是进程&#xff0c;而k8s本质上类似操作系统。 熟悉Linux的…

导入PR的视频画面是黑屏的怎么办?

在现代视频编辑领域中&#xff0c;越来越多的人使用Adobe Premiere Pro来编辑和制作视频&#xff0c;但是在某些情况下&#xff0c;用户可能需要透明背景的视频进行创作&#xff0c;那么如何创作透明背景的视频呢&#xff1f; 要制作具有透明背景的视频&#xff0c;我们需要使…

科技改变旅游,道观漫游可视化:智能化管理助力道观游览

道观漫游可视化是一种通过技术手段实现道观游览的可视化展示方式&#xff0c;让游客能够更加直观地了解道观的历史、文化和建筑特色。 随着旅游业的不断发展&#xff0c;道观漫游可视化已经成为了旅游行业中的一个重要方向&#xff0c;吸引了越来越多的游客前来体验。 道观漫游…

5. Jetson Orin Nano CUDA 配置

5. Jetson Orin Nano CUDA 配置 1&#xff1a;安装Jtop jtop安装主要有以下三个步骤&#xff1a; 安装pip3 我们需要使用pip3来安装jtop&#xff0c;所以先安装pip3 sudo apt install python3-pip安装jtop sudo -H pip3 install -U jetson-stats运行jtop服务 sudo -H pip3 in…

芯片量产导入知识

什么是芯片量产 从芯片功能设计到生产制造、测试等环节&#xff0c;每一个环节都至关重要。 对于保障大规模发货后芯片指标表现的一致性&#xff0c;以及产品应用生命周期内的稳定性和可靠性&#xff0c;需要考虑多种因素。以下是一些相关的观点&#xff1a; 可量产性设计&am…

C语言趣练习:两个字符串不用strcmp函数怎么比较大小

目录 1习题一&#xff1a;两个字符串不用strcmp函数怎么比较大小&#xff0c;并输出其差值 2不用strcpy函数将s2字符串中内容复制到s1中 3译密码问题 4总结&#xff1a; 1习题一&#xff1a;两个字符串不用strcmp函数怎么比较大小&#xff0c;并输出其差值 解题思路&#x…

redis 三主三从高可用集群docker swarm

由于数据量过大&#xff0c;单个Master复制集难以承担&#xff0c;因此需要对多个复制集进行集群&#xff0c;形成水平扩展每个复制集只负责存储整个数据集的一部分&#xff0c;这就是Redis的集群&#xff0c;其作用是提供在多个Redis节点间共享数据的程序集。 官网介绍地址 re…

【Python】手把手教你用tkinter设计图书管理登录UI界面(一)

下一篇&#xff1a; 本项目将分段设计“图书管理登录UI界面”的用户登录、用户注册、用户账号找回等。主要围绕GUI标准库tkinter、以及类的继承&#xff08;重点&#xff09;来设计本项目。 首先新建一个文件夹命名为“图书管理系统项目”&#xff0c;并在其目录下新建文件co…

LV.13 D1 嵌入式系统移植导学 学习笔记

一、嵌入式系统分层 操作系统&#xff1a;向下管理硬件、向上提供接口 操作系统为我们提供了&#xff1a; 1.进程管理 2.内存管理 3.网络接口 4.文件系统 5.设备管理 那系统移植是干什么呢&#xff1f; 就是将Linux操作系统移植到基于ARM处理器的开发板中。 那为什么要移植系…

PHP基础 - 注释变量

一. 语言开始标识 在PHP中,文件的开头需要使用语言开始标识来指定该文件是PHP代码。标识通常为"<?php",也可以是"<?",但建议使用"<?php"以确保代码的兼容性和可读性。 <?php // PHP代码从这里开始写 二. PHP注释 注释是用…

售权益网络科技的秦明军,创业计划的意义?

售权益网络科技的秦明军&#xff0c;创业计划的意义&#xff1f; 声明&#xff1a;本篇分享来自手机[售权益网络科技]蝴蝶号&#xff0c;严禁抄袭&#xff0c;复制&#xff0c;粘贴&#xff0c;以免发生著作版权纠纷&#xff01;创业计划对于创业者来说具有重要的意义&#xf…

微软 Power Platform 零基础 Power Pages 网页搭建高阶实际案例实践(四)

微软 Power Platform 零基础 Power Pages 网页搭建教程之高阶案例实践学习&#xff08;四&#xff09; Power Pages 实际案例学习进阶 微软 Power Platform 零基础 Power Pages 网页搭建教程之高阶案例实践学习&#xff08;四&#xff09;1、新增视图&#xff0c;添加List页面2…

OFDM模糊函数仿真

文章目录 前言一、OFDM 信号及模糊函数1、OFDM 信号表达式2、模糊函数表达式 二、MATLAB 仿真1、MATLAB 核心源码2、仿真结果①、OFDM 模糊函数②、OFDM 距离模糊函数③、OFDM 速度模糊函数 前言 本文进行 OFDM 的仿真&#xff0c;首先看一下 OFDM 的模糊函数仿真效果&#xf…

AcWing 93. 递归实现组合型枚举

Every day a AcWing 题目来源&#xff1a;93. 递归实现组合型枚举 解法1&#xff1a;回溯算法 标准的回溯算法模板题。 如果把 n、m 和数组 nums 都设置成全局变量的话&#xff0c;backtracking 回溯函数可以只用一个参数 level。 注意传参时 nums 不能用引用&#xff0c;…

Linux 压缩、文件传输与安装

目录 1. 压缩 1.1 tar 1.2 gzip 1.3 zip 1.4 rar 2 文件传输 2.1 网站下载 2.2 scp 传输 2.3 rz 和 sz 2.4 xftp 3.安装 3.1 编译安装 &#xff08;ngnix&#xff09; 3.2 rpm 安装 3.3 yum 安装 1. 压缩 1.1 tar 使用 tar 压缩文件时&#xff0c;会保留源文件…

(一)五种最新算法(SWO、COA、LSO、GRO、LO)求解无人机路径规划MATLAB

一、五种算法&#xff08;SWO、COA、LSO、GRO、LO&#xff09;简介 1、蜘蛛蜂优化算法SWO 蜘蛛蜂优化算法&#xff08;Spider wasp optimizer&#xff0c;SWO&#xff09;由Mohamed Abdel-Basset等人于2023年提出&#xff0c;该算法模型雌性蜘蛛蜂的狩猎、筑巢和交配行为&…

项目一 分析并设计学生管理数据库

项目一 分析并设计学生管理数据库 1&#xff0c;做好管理数据库的知识准备 1.1&#xff0c;初识数据库 **1&#xff0c;DBMS&#xff1a;**数据库管理系统(Database Management System)。数据库 是通过DBMS创建和操作的 容器。 **2&#xff0c;DB&#xff1a;**数据库(data…

Ubuntu20.04使用cephadm部署ceph集群

文章目录 Requirements环境安装Cephadm部署Ceph单机集群引导&#xff08;bootstrap&#xff09;建立新集群 管理OSD列出可用的OSD设备部署OSD删除OSD 管理主机列出主机信息添加主机到集群从集群中删除主机 部署Ceph集群 Cephadm通过在单个主机上创建一个Ceph单机集群&#xff0…

最长子串问题(LCS)--动态规划解法

题目描述&#xff1a; 如果Z既是X的子串&#xff0c;又是Y的子串&#xff0c;则称Z为X和Y的公共子串。 如果给定X、Y&#xff0c;求出最长Z及其长度。 注意&#xff1a;这里求的不是子序列&#xff0c;两者的意思并不相同。子串要求连续&#xff0c;子序列并不需要。 如果想…