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

news2024/11/14 19:42:58

文章目录

  • 🎪 Linux自动化构建工具make/makefile
    • 🚀 1.Makefile文件格式
      • ⭐1.1 简单makefile例子
      • ⭐1.2 概述
      • ⭐1.3 目标(target)
      • ⭐1.4 前置条件(prerequisites)
      • ⭐1.5 命令(commands)
    • 🚀 2.Makefile文件语法
      • ⭐2.1 注释
      • ⭐2.2 回声
      • ⭐2.3 通配符
      • ⭐2.4 变量和赋值符
      • ⭐2.5 内置变量
      • ⭐2.6 自动变量
      • ⭐2.7 函数
    • 🚀 3.Linux小程序进度条
      • ⭐3.1 缓冲区概念
      • ⭐3.2 进度条代码


🎪 Linux自动化构建工具make/makefile

为什么Linux会有自动化构建工具呢?一个工程中的源文件不计数,其按类型、功能、模块分别放在若干个目录中,makefile定义了一系列的规则来指定,哪些文件需要先编译,哪些文件需要后编译,哪些文件需要重新编译,甚至于进行更复杂
的功能操作,makefile带来的好处就是——“自动化编译”,一旦写好,只需要一个make命令,整个工程完全自动编译,极大的提高了软件开发的效率,会不会写makefile,从一个侧面说明了一个人是否具备完成大型工程的能力。make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建

🚀 1.Makefile文件格式

make会在当前目录下找名字叫“Makefile”或“makefile”的文件,然后开始自动化构建,下面我们先来看一个例子。

⭐1.1 简单makefile例子

在这里插入图片描述

⭐1.2 概述

Makefile文件由一系列规则(rules)构成。每条规则的形式如下:

    <target> : <prerequisites> 
    [tab]  <commands>

上述例子中形成的可执行文件myfile就是target,而myfile.c就是prerequisites,下面一行commands就是"命令",第二行必须以tab键起首

我们在构建之前必须清楚:构建目标的前置条件是什么,以及怎么构建

⭐1.3 目标(target)

一个目标(target)就构成一条规则。目标通常是文件名,指明Make命令所要构建的对象,比如上文的 myfile 。目标可以是一个文件名,也可以是多个文件名,之间用空格分隔
在这里插入图片描述
关于目标我们还得注意以下几点:

  • 默认输入make执行的是第一个目标

我们将Makefile文件修改为如下:

在这里插入图片描述

这时我们键入make

在这里插入图片描述

  • 声明伪目标

除了文件名,目标还可以是某个操作的名字,这称为"伪目标"(phony target),例如:

clean:
	rm -rf myflie

如果这样的话那么make每次需要检查clean是否是一个文件,我们可以用.PHONY来声明clean是个伪目标,这样make就不会检查clean是否是个文件,而是直接执行以下的命令.

我们还可以查询手册知道其它关于makefile的关键字:makefile关键字手册

⭐1.4 前置条件(prerequisites)

前置条件通常是一组文件名,之间用空格分隔。它指定了"目标"是否重新构建的判断标准:只要有一个前置文件不存在,或者有过更新(前置文件的last-modification时间戳比目标的时间戳新),"目标"就需要重新构建。

在这里插入图片描述

  • 多级构建:当第一个目标的前置条件不存在时,make会自动调用后续目标生成前置条件

在这里插入图片描述
在这里插入图片描述
这就是整个make的依赖性,make会一层又一层地去找文件的依赖关系,直到最终编译出第一个目标文件。

  • 多步执行:当我们需要生成多个文件或者执行多不时,只需要再定义一个目标,再将其余需要构建的目标加入即可

Makefile:

a.txt:                                                                             
	echo "a.txt" > a.txt 
m.txt:
    echo "b.txt" > m.txt 
t.txt:
    echo "t.txt" > t.txt 
source: a.txt m.txt t.txt

在这里插入图片描述

⭐1.5 命令(commands)

命令(commands)表示如何更新目标文件,由一行或多行的Shell命令组成。它是构建"目标"的具体指令,它的运行结果通常就是生成目标文件。

  • 每个命令前都必须有一个tab键,我们也可以用.RECIPEPREFIX声明其它键
.RECIPEPREFIX = >
myfile:myfile.c
>gcc myfile.c -o myfile
.PHONY:clean
clean:
>rm -rf myfile

我们用>号代替了tab键,每个命令前用>就可以了

🚀 2.Makefile文件语法

⭐2.1 注释

#在Makefile中表示注释。

# 这是注释
myfile: myfile.c
    # 这是注释
    gcc myfile.c -o myfile # 这也是注释

⭐2.2 回声

正常情况下我们每次执行make命令时,系统都会打印相应的命令再执行
在这里插入图片描述
我们在命令前加上@就可以关闭回声。

.PHONT:source
source:
       	@echo "这是第二次" > test.c
        @cat test.c

在这里插入图片描述
注意:由于我们具体要看我们到底执行了哪些命令,所以我们一般只在注释和纯echo显示命令前加上@

⭐2.3 通配符

通配符(wildcard)用来指定一组符合条件的文件名。Makefile 的通配符与 Bash 一致。

  • 星号*:可以使用星号代替零个、单个或多个字符
  • 问号?:可以匹配任意一个字符
  • 中括号[]:匹配中括号任意一个字符,如[ljk]代表匹配一个l,j或k的字符
  • [-]:匹配范围,[0-9]代表匹配任一个数字
  • [!]:匹配不是中括号的一个字符,[!0-9]表示不匹配a-z中任意字符

关于通配符更详细的讲解:Linux通配符

⭐2.4 变量和赋值符

Makefile 允许使用=自定义变量。

ret = hello world
test:
	@echo $(ret) 

上面代码中,变量 ret 等于 Hello World。调用时,变量需要放在 $( ) 之中。此时会打印出hello world

有时变量的值可能会指向另外一个变量。

a1 = $(a2)

这时就出现了问题,a1 的值到底在定义时扩展(静态扩展),还是在运行时扩展(动态扩展)?如果 a2 的值是动态的,这两种扩展方式的结果可能会差异很大。

为了解决类似问题,makefile提供了四个运算符:

a1 := $(a2)
# 在执行时扩展,允许递归扩展。

a1 := $(a2)
# 在定义时扩展。

a1 ?= $(a2)
# 只有在该变量为空时才设置值。

a1 += $(a2)
# 将值追加到变量的尾端。

⭐2.5 内置变量

Make命令提供一系列内置变量,比如,(CC) 指向当前使用的编译器,(MAKE) 指向当前使用的Make工具。这主要是为了跨平台的兼容性,详细的内置变量清单见手册。

output:
    $(CC) -o output input.c

⭐2.6 自动变量

Make命令还提供一些自动变量,它们的值与当前规则有关。主要有以下几个:

  • $ @
    @指代当前目标,就是Make命令当前构建的那个目标。比如,make clean的@ 就指代clean。
a.txt b.txt: 
    touch $@

等同于下面的写法

a.txt:
    touch a.txt
b.txt:
    touch b.txt
  • $ <
    <指代第一个前置条件,比如规则为 a.txt: b.txt c.txt,那么$<就指代b.txt
a.txt: b.txt c.txt
    cp $< $@ 

等同于下面的写法

a.txt: b.txt c.txt
    cp b.txt a.txt 
  • $ ?
    ?指代比目标时间戳更新的所有前置条件,例如t:p1 p2 p3,p1,p2时间戳新于t,则$?指代p1,p2

  • $ ^
    ^指代所有前置条件,例如t:p1 p2 p3,p1,p2时间戳新于t,则$^指代p1,p2,p3

⭐2.7 函数

Makefile还可以使用函数,格式如下:

$(function arguments)

Makefile提供了许多内置函数,可供调用。下面是几个常用的内置函数。

1. shell函数
shell 函数用来执行 shell 命令。

srcfiles := $(shell echo src/{00..99}.txt)

2. wildcard函数
wildcard 函数用来在 Makefile 中,替换 Bash 的通配符。

srcfiles := $(wildcard src/*.txt)

3. subst函数
subst 函数用来文本替换,格式如下:

$(subst from,to,text)

下面的例子将字符串"feet on the street"替换成"fEEt on the strEEt"。

$(subst ee,EE,feet on the street)

4. patsubst函数
patsubst 函数用于模式匹配的替换,格式如下。

$(patsubst pattern,replacement,text)

下面的例子将文件名"x.c.c bar.c",替换成"x.c.o bar.o"。

$(patsubst %.c,%.o,x.c.c bar.c)

5. 替换后缀名
替换后缀名函数的写法是:变量名 + 冒号 + 后缀名替换规则。它实际上patsubst函数的一种简写形式。

min: $(OUTPUT:.js=.min.js)

上面代码的意思是,将变量OUTPUT中的后缀名 .js 全部替换成 .min.js

🚀 3.Linux小程序进度条

⭐3.1 缓冲区概念

我们利用printf函数进行输出的时候,实际上编译器会将我们的输出内容写到缓冲区,等到系统刷新缓冲区的时候,屏幕上才会输出相应内容,同时清空缓冲区

所以我们进行输出的时候会带上/n等选项,因为那会帮我们自动刷新缓冲区,但是加上/r,会将光标移动到行开头,然后刷新缓冲区,我们的结果就会被新打印出来的结果给覆盖掉,所以我们应该在之前刷新缓冲区,我们有一个刷新缓冲区的函数fflush,以下为test.c用例

在这里插入图片描述
此时会观察到屏幕先打印了结果,并且光标移动到了行首,因此接下打印出的命令行将原结果覆盖掉了
在这里插入图片描述

⭐3.2 进度条代码

#include "proc.h"
#define SIZE 102
#define STYLE '='
#define ARR '>'

// "|/-\\"
void process()
{
    const char *lable = "|/-\\";
    char bar[SIZE];
    memset(bar, '\0', sizeof(bar));
    int i = 0;
    while( i <= 100 )
    {
        printf("[%c][\033[42;32;31m%-100s\033[0m][%d%%]\r", lable[i%4], bar, i);
        fflush(stdout);
        bar[i++] = STYLE;
        if(i != 100) bar[i] = ARR;
        usleep(100000);
    }
    printf("\n");
}

我们还可以自己添加颜色输出:printf颜色输出

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

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

相关文章

4-异步:非阻塞IO

4-异步&#xff1a;非阻塞I_O 简介 什么是Node.js的非阻塞I/O I/O 即 Input/Output. 也就是一个系统的输入和输出阻塞I/O和非阻塞I/O的却别就在于系统接收输入再到输出期间&#xff0c;能不能接收其他输入 对于这两句话的理解&#xff0c;可以把系统比作服务员&#xff0c;…

React 实现自动上报 PV/Click 的埋点 Hooks

自定义 hooks 是基于 React Hooks 的一个拓展&#xff0c;我们可以根据业务需求制定满足业务需要的组合 hooks&#xff0c;更注重的是逻辑单元。怎样把一段逻辑封装起来&#xff0c;做到复用&#xff0c;这才是自定义 hooks 的初衷。 自定义 hooks 也可以说是 React Hooks 的聚…

【并发编程十三】c++原子操作

【并发编程十三】c原子操作一、改动序列1、改动序列2、预测执行二、原子操作及其类别1、原子操作2、非原子操作3、原子类型三、标准原子类型1、标准原子类型的两种实现方式2、原子操作的用途3、原子操作的宏四、操作std:atomic_flag1、简介2、使用说明3、使用std:atomic_flag实…

Kettle(16):Kitchen作业执行引擎

在Linux中对Kettle做Linux配置(和Windows相同,添加驱动jar包) 上传以后需要重启。 1 在Windows中开发作业 2 配置Start组件 3 配置转换组件 修改Kettle&

【HBase——陌陌海量存储案例】1.案例介绍与HBase表结构设计(上)

前言 本系列接【HBase入门】系列文章后实战案例的学习。 学习目标 能够掌握HBase表结构设计&#xff08;表设计、ROWKEY设计、预分区&#xff09; 能够安装部署Apache Phoenix 能够掌握Phoenix的基本操作 能够掌握使用Phoenix建立二级索引提升性能 能够基于Phoenix JDBC API编…

Ubuntu安装ROS(每个步骤图文详细)

Ubuntu安装ROS&#xff08;每个步骤图文详细&#xff09;前言&#xff08;推荐安装&#xff09;ROS对应的Ubuntu的版本换源安装ROS一、添加ROS软件源二、添加密钥三、安装ROS-melodic四、初始化rosdep可能出现的问题&#xff1a;一 、 **sudo: rosdep&#xff1a;找不到命令**二…

算法_位运算x(-x)和x(x-1)

最近在跟着y总学算法。 今天学到了两个很经典的位运算&#xff0c;x&(-x)和x&(x-1)&#xff1a; x&(-x)&#xff1a;保留二进制下最后出现的1的位置&#xff0c;其余位置置0&#xff08;即一个数中最大的2的n次幂的因数 x&(x-1)&#xff1a;消除二进制下最后…

SpringCloud整合Zookeeper代替Eureka

目录 一、注册中心Zookeeper 二、服务提供者 三、服务消费者 一、注册中心Zookeeper zookeeper是一个分布式协调工具&#xff0c;可以实现注册中心功能 关闭Linux服务器防火墙后启动zookeeper服务器 zookeeper服务器取代Eureka服务器&#xff0c;zk作为服务注册中心 Lin…

ORA-600 kcbzpbuf_1故障恢复----惜分飞

数据库启动报错ORA-03113SQL> startup;ORACLE instance started. Total System GlobalArea 5.1310E10 bytesFixed Size 2265224 bytesVariable Size 1.8119E10 bytesDatabaseBuffers 3.3152E10 bytesRedo Buffers 36069376 bytesDatabasemounted. ORA-03113: end-of-file on…

二叉树的层序遍历

二叉树的层序遍历 层序遍历一个二叉树。就是从左到右一层一层的去遍历二叉树。 需要借用一个辅助数据结构即队列来实现&#xff0c;队列先进先出&#xff0c;符合一层一层遍历的逻辑&#xff0c;而用栈先进后出适合模拟深度优先遍历也就是递归的逻辑。 而这种层序遍历方式就是…

Java:基于XML的Spring使用

基于XML的Spring使用一、Spring IOC 底层实现1.1 BeanFactory与ApplicationContexet1.2 图解IOC类的结构二、 Spring依赖注入数值问题【重点】2.1 字面量数值2.2 CDATA区2.3 外部已声明bean及级联属性赋值2.4 内部bean2.5 集合三、 Spring依赖注入方式【基于XML】3.1 set注入3.…

白炽灯护眼还是LED护眼?盘点专业护眼的LED护眼灯

目前大多数家庭都会购买台灯使用&#xff0c;选择白炽灯还是LED灯呢&#xff1f;建议是LED灯更护眼。白炽灯缺点&#xff1a;耗电、发光效率低、温度过高不安全。白炽灯优点&#xff1a;体积小、显色能力好。LED灯缺点:价格较高、显色能力比白炽灯弱一些。LED灯优点&#xff1a…

JDBC(powernode CD2206)详尽版(内含教学视频、源代码、SQL文件)

JDBC&#xff08;powernode CD2206&#xff09;详尽版&#xff08;内含教学视频、源代码、SQL文件&#xff09; 包含&#xff1a;教学视频、源代码&#xff08;与博客同步&#xff09;、SQL文件 下载链接地址&#xff1a; https://download.csdn.net/download/weixin_4641135…

使用kubebuilder开发operator详解--踩坑记录

跟着教程&#xff1a;使用kubebuilder开发operator详解出现&#xff1a; 国内无法访问该ip&#xff0c;需要设置go env&#xff1a; go envGOPROXYhttps://goproxy.c 查看go env&#xff1a; 修改镜像后仍然无法解决&#xff1a;借鉴该问题https://github.com/goproxy/goprox…

springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater(推荐-简单方便使用)两种方式配置druid数据源

springboot-druid数据源的配置方式及配置后台监控-自定义和导入stater&#xff08;推荐-简单方便使用&#xff09;两种方式配置druid数据源druid数据源自定义配置druid数据源1.引入依赖2.配置自定义dataSoruce的Bean组件3.测试sql,验证数据源是否配置成功4.开启 StatFilter,wal…

哈希的应用 -- 布隆过滤器

作者&#xff1a;小萌新 专栏&#xff1a;C进阶 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;介绍并模拟实现哈希的应用 – 布隆过滤器 布隆过滤器布隆过滤器的提出布隆过滤器的概念布隆过滤器的实现框架与算法插入函数查找函数删…

JVM学习(五):JVM运行时参数

一、JVM参数选项1.1 标准参数选项标准参数选项的特点是以-开头&#xff0c;比较稳定&#xff0c;后续版本基本不会变化也就是在命令行输入java 或 java -help之后显示的参数&#xff0c;其中选项包括:-d32 使用 32 位数据模型 (如果可用)-d64 使用 64 位数据模型 (如果可用)-…

Spring Security in Action 第十章 SpringSecurity应用CSRF保护和CORS跨域请求

本专栏将从基础开始&#xff0c;循序渐进&#xff0c;以实战为线索&#xff0c;逐步深入SpringSecurity相关知识相关知识&#xff0c;打造完整的SpringSecurity学习步骤&#xff0c;提升工程化编码能力和思维能力&#xff0c;写出高质量代码。希望大家都能够从中有所收获&#…

分布式链路追踪SkyWalking快速入门之环境安装界面指标介绍(一)

目录 一、先抛几个分布式常见的问题 二、分布式链路追踪Skywalking介绍 2.1 Skywalking是什么 2.2 市场上同类解决方案 2.3 skywalking的性能对比 三、Apache Skywalking特点和整体架构组件介绍 3.1 Skywalking特点 3.2 Skywalking整体架构 3.3 部署组件介绍 四.Apac…

HTML当中元素的id属性

<!DOCTYPE html> <html> <head> <meta charset"utf-8"> <title>HTML当中元素的id属性</title> </head> <body> <!-- 1、在HTML文档当中&#xff0c;任何元素/节…