当前位置: 首页 > news >正文

Makefile泛谈

Makefile工作原理

1、检查规则中的依赖文件是否存在。
2、若依赖文件不存在,则寻找是否有规则用来生成该依赖文件。

譬如,执行文件会先寻找.o文件是否存在,如果不存在,就会再寻找是否有规则可以生成该依赖文件。如果缺少了main.o这个依赖文件,Makefile就会在它下面寻找是否有规则生成main.o。当它发现gcc main.c -o main.o这条规则可以生成main.o时,它就利用此规则生成main.o,然后再生成执行文件。

语法规则

目标文件: 依赖文件 ... 可以有很多个执行命令 (可以有一些选项)

1、目标文件就是要生成的文件。
2、依赖文件就是源头。
3、执行命令:即通过执行命令由依赖文件生成目标文件。注意每条命令之前必须有一个tab

All

Makefile文件默认只生成第一个目标文件即完成编译,但是我们可以通过all 指定所需要生成的目标文件,也就是我们编译的终极目标。

all: target1 target2 target3
target1:
# 编译规则1
target2:
# 编译规则2
target3:
# 编译规则3

all被设置为第一个目标,并且target1、target2和target3被列为all的依赖。当你在命令行中运行make时,make命令会寻找并执行all目标规则,这将依次执行target1、target2和target3的编译。


$符号

$符号表示取变量的值
$^ 表示所有的依赖文件
$@ 表示生成的目标文件
$< 表示第一个依赖文件

%符号

%.c匹配所有.c文件

%.o:%.cgcc -c $<

用路径下所有.c文件都各自生成一个.o文件

赋值

=

使用 “=”进行赋值,变量的值是整个Makefile中最后被指定的值。

VIR_A = A
VIR_B = $(VIR_A) B
VIR_A = AA

最后VIR_B的值是AA B,而不是A B,会把整个变量展开。

:=

直接赋值,赋予当前位置的值。

VIR_A := A
VIR_B := $(VIR_A) B
VIR_A := AA

最后BIR_B的值是A B,即根据当前位置进行赋值。

?=

表示如果该变量没有被赋值,赋值予等号后面的值。

VIR ?= new_value

如果VIR在之前没有被赋值,那么VIR的值就为new_value。

+=

表示将符号后面的值添加到前面的变量后面

常用函数

取目录函数dir

从字符串中取出目录部分,目录部分是指最后一个反斜杠(“/”)之前的部分。

dir src/foo.c hacks

取到的是src/./

shell函数

可以借助这个函数来执行一些shell能够执行的命令

$(shell pwd)

这样就可以执行pwd命令了

ALL_DIRS = $(shell "find" $(SRC_PATH) -type d)

-type d参数用于限定find命令只返回路径(无文件名)。

ALL_DIRS将包含通过find命令获取的指定目录下的所有子目录路径列表。

过滤函数filter

过滤掉一个指定的字符串

FILE = a.c b.h c.s d.cpp   
SRC = $(filter %.c, $(FILE))

留下所有.c文件,最后SRC = a.c

排除函数filter-out

FILE = a.c b.h c.s d.cpp   
SRC = $(filter-out %.c, $(FILE))

去掉所有.c文件,最后SRC = b.h c.s d.cpp

通配符函数wildcard

SRC = $(wildcard ./*.c)

匹配当前目录下所有.c 文件,并将其赋值给SRC变量。

wildcard $(dir)/*.c

匹配所有目录下.c文件

扩展通配符函数patsubst

文件名替换

sources := main.c foo.c bar.c
objects := $(patsubst %.c,%.o,$(sources))

将sources中所有的.c文件名替换为.o,所以objects的值将是 main.o foo.o bar.o。

wildcard $(dir)/*.c

在某个目录中获取所有以 .c 扩展名结尾的文件路径。

$(dir) 是一个变量,表示当前迭代的目录。

/*.c 表示在该目录中搜索所有以 .c 结尾的文件。

目录替换

vpath := src/foo
new_vpath := $(patsubst src/%,obj/%,$(vpath))

将vpath中的src/替换为obj/,所以new_vpath的值将是 obj/foo。

文件扩展名替换

txt_files := file1.txt file2.txt file3.txt
md_files := $(patsubst %.txt,%.md,$(txt_files))

将txt_files中所有的.txt文件名替换为.md,所以md_files的值将是 file1.md file2.md file3.md。

添加前缀

names := apple orange banana
prefixed_names := $(patsubst %,fruit_%,$(names))

为names中的每个名字添加了前缀"fruit_",所以prefixed_names的值将是 fruit_apple fruit_orange fruit_banana。

从路径中提取文件名(去除路径)

full_paths := /home/user/main.c /home/user/foo.c
file_names := $(patsubst /home/user/%.c,%,$(full_paths))

从full_paths中提取了每个文件的文件名,所以file_names的值将是 main foo。

foreach遍历集合所有元素

ALL_SRCS = $(foreach dir, $(DIRS), $(wildcard $(dir)/*.c))

伪目标 .PHONY

伪目标只是一个标签,clean是个伪目标没有依赖文件。当目标文件已存在时,忽略,继续执行规则。

clean:rm -rf $(OBJ) all.out.PHONY: clean ALL

清理

清理make命令所产生的所有文件

 clean:rm -rf $(OBJ) hello.out

有些用clear

删除中间生成.o文件

clear:rm *.o

指定头文件路径

一般都是通过"-I"来指定头文件路径

CFLAGS=-I/home/develop/include
app:*.cgcc $(CFLAGS) -o app

指定库文件路径

一般都是通过"-L"来指定头文件路径

CFLAGS=-L/home/develop/lib1 -L/home/develop/lib2
app:*.cgcc $(CFLAGS) -o app

循环函数foreach

$(foreach dir, $(DIRS), $(wildcard $(dir)/*.c))

遍历所有DIRS(纯目录,无文件名)里面的.c文件,以带目录的方式返回。

去除路径notdir

OBJ=$(notdir  a/b/c.cpp, aaa.cpp)

将带路径的文件名去除路径,只保留文件名。

提取前缀basename

返回字符串 “.”之前的所有字段

SRC := src/main.c src/hello.c
OBJ := $(basename $(SRC)) 

返回文件名序列 <names> 的前缀序列,如果文件没有前缀,则返回空字串。

最后返回src/main src/hello

添加前缀addprefix

给字符串中的每一个子串前加上一个前缀

SOURCE = main.c foo.c bar.c
OBJ = $(PWD)
add_source = $(addprefix $(OBJ)/, $(SOURCE))

这样就给每个文件前面添加了路径

字符串替换函数subst

$(subst from,to,text),对 text 文本执行文本替换:每次出现的 from 都替换为 to。

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

生成值 fEEt on the strEEt

参数选择

编译的时候有很多参数可以选择,在这里举点例子。

-cpu=rh850g3kh:指定编译器的目标CPU架构为rh850g3kh。
-bsp generic:使用通用的BSP(板级支持包)。
-dwarf2:使用DWARF2调试信息格式。
-nothreshold:禁用阈值优化。
-preprocess_assembly_files:对汇编文件进行预处理。
-fsoft:启用软浮点支持。
-list:生成一个列表文件。
-object_dir=$(OBJ_OUTPUT_DIR):指定目标文件的输出目录为$(OBJ_OUTPUT_DIR)。
--no_additional_output:不生成额外的输出文件。
-callgraph:生成函数调用图。
-Ogeneral:启用一般优化级别。
-Mx:启用所有的警告信息。
-e _RESET:指定程序入口点为_RESET。
-D__GHS__:定义一个名为__GHS__的宏。
-elf:生成ELF可执行文件格式的输出。
-no_v850_simd:禁用V850 SIMD(单指令多数据)指令集。
-g:生成调试信息。
-passsource:将源代码传递给后续处理阶段。
-v:详细显示编译过程中的操作信息。
-w:禁用警告信息的显示。
-nofpu:禁用FPU(浮点运算单元)支持。
-nomacro:禁用宏展开。
-b0:设置链接器的起始地址为0。
-DSAIOS_GLOBAL_A1SAMPLE_ENABLE=$(SAIOS_GLOBAL_A1SAMPLE_ENABLE):定义一个名为SAIOS_GLOBAL_A1SAMPLE_ENABLE的宏,并将其值设置为$(SAIOS_GLOBAL_A1SAMPLE_ENABLE)。
-c:表示生成目标文件而不进行链接,即只进行编译而不进行链接。
-c99:表示使用C99标准进行编译,启用C99的新特性和语法。
-map="$(TARGET_OUTPUT_DIR)/$(CURRENT_APPL_NAME).map":表示生成一个链接地图文件,将其指定为TARGET_OUTPUT_DIR目录下的CURRENT_APPL_NAME.map。
-o "$(TARGET_OUTPUT_DIR)/$(CURRENT_APPL_NAME).out":表示指定输出文件的名称和路径,将其设置为TARGET_OUTPUT_DIR目录下的CURRENT_APPL_NAME.out

简单例程优化

文件结构

hello.c hello.h list.c list.h main.c makefile

Makefile内容

main:mian.o hello.ogcc main.o he11o.o -o main
mian.o:main.c hello.hgcc -c main.c 
he11o.o: hello.c hello.hgcc -c he11o.c
clean:rm -f *.o main

可以通过变量指定目标文件

OBJ=mian.o he11o.o
main:$(OBJ)gcc $(OBJ) -o main
mian.o:main.c hello.hgcc -c main.c 
he11o.o: hello.c hello.hgcc -c he11o.c
clean:rm -f *.o main

利用隐式规则

OBJ=mian.o he11o.o
main:$(OBJ)gcc $(OBJ) -o main
mian.o:hello.h
he11o.o:hello.h
clean:rm -f *.o main

利用$符号

OBJ=mian.o he11o.o
CC=gcc
TARGETS=main
$(TARGETS):$(OBJ)$(CC) $^ -o $@
%.o:%.c$(CC) -c $<
clean:rm -f *.o $@

经典例程

CC := g++  
CFLAGS := -g  
TARGET := test  
SRCS := $(wildcard *.cpp)  
OBJS := $(patsubst %cpp,%o,$(SRCS))  all:$(TARGET)  
%.o:%.cpp  $(CC) $(CFLAGS) -c $< -o $@ 
$(TARGET):$(OBJS)  $(CC) $(CFLAGS) -o $@  
clean:  rm -rf $(TARGET) *.o  

相关文章:

Makefile泛谈

Makefile工作原理 1、检查规则中的依赖文件是否存在。 2、若依赖文件不存在&#xff0c;则寻找是否有规则用来生成该依赖文件。 譬如&#xff0c;执行文件会先寻找.o文件是否存在&#xff0c;如果不存在&#xff0c;就会再寻找是否有规则可以生成该依赖文件。如果缺少了main.…...

Python的快捷键

Python Python使用的小快招关于注释关于格式写主函数如何看函数源代码 Python使用的小快招 本文主要记录了写python代码的时候提高效率的一些小妙招 关于注释 选中要注释的代码&#xff0c;然后按下Ctrl /即可对多段代码注释。 关于格式 对于python代码的格式&#xff0c…...

css为盒子设置滚动条隐藏滚动条

省流&#xff1a;为盒子设置宽高&#xff0c;设置滚动条方向&#xff0c;隐藏滚动条。 首先&#xff0c;要为需要添加滚动条的盒子设置固定的高度和宽度&#xff0c;这样才能让内容超过盒子的边缘。 .box {width: 300px;height: 300px; }然后&#xff0c;给盒子加入overflow属…...

音视频开发常见问题(四):视频花屏和绿屏

摘要 本文介绍了视频视频花屏/绿屏问题的常见原因&#xff0c;如丢失关键帧、metadata的变化、硬件编解码的兼容性问题和颜色格式不一致问题。以及排查方法和解决策略&#xff0c;包括检查视频数据格式、排查自采集/自渲染模块问题、联系第三方音视频SDK技术支持等。最后&…...

设计模式—创建型模式之单例模式

设计模式—创建型模式之单例模式 介绍 单例模式说明&#xff1a;一个单一的类&#xff0c;负责创建自己的对象&#xff0c;同时确保系统中只有单个对象被创建。 单例模式特点&#xff1a; 某个类只能有一个实例&#xff1b;&#xff08;构造器私有&#xff09;它必须自行创…...

7.现代卷积神经网络

#pic_center R 1 R_1 R1​ R 2 R^2 R2 目录 知识框架No.1 深度卷积神经网络 AlexNet一、AlexNet二、D2L代码注意点三、QA No.2 使用块的网络 VGG一、VGG二、D2L代码注意点三、QA No.3 网络中的网络 NiN一、NIN二、D2L代码注意点三、QA No.4 含并行连结的网络 GoogLeNet / Incep…...

配置Super-VLAN下的DHCP服务器示例

组网需求 如图1所示&#xff0c;某公司拥有两个部门&#xff0c;为了节省IP地址&#xff0c;部门A和部门B规划为同一网段&#xff1b;为了提升业务安全性&#xff0c;将不同部门的用户划分到不同VLAN中。企业管理员为了方便统一管理&#xff0c;希望部门内终端通过DHCP服务器动…...

【开源】基于SpringBoot的城市桥梁道路管理系统的设计和实现

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统展示四、核心代码4.1 查询城市桥梁4.2 新增城市桥梁4.3 编辑城市桥梁4.4 删除城市桥梁4.5 查询单个城市桥梁 五、免责说明 一、摘要 1.1 项目介绍 基于VueSpringBootMySQL的城市桥梁道路管理系统&#xff0c;支持…...

关于根据动态数量的对象的某属性的数组数量呈乘机式增长的数据处理

adta是原始数组,currentIndex默认是零,currentObject初始对象,result处理生成的结果 function generateObjects(data, currentIndex, currentObject, result) {if (currentIndex data.length) {result.push(currentObject);return;}const currentCode data[currentIndex].co…...

数据分析和互联网医院小程序:提高医疗决策的准确性和效率

互联网医院小程序已经在医疗领域取得了显著的进展&#xff0c;为患者和医疗从业者提供了更便捷和高效的医疗服务。随着数据分析技术的快速发展&#xff0c;互联网医院小程序能够利用大数据来提高医疗决策的准确性和效率。本文将探讨数据分析在互联网医院小程序中的应用&#xf…...

asp.net学生考试报名管理系统VS开发sqlserver数据库web结构c#编程Microsoft Visual Studio

一、源码特点 asp.net学生考试报名管理系统是一套完善的web设计管理系统系统&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为vs2010&#xff0c;数据库为sqlserver2008&#xff0c;使 用c#语言开发 应用技术&#xff1a;asp…...

Python之前端的学习

前端学哪些内容 1. HTML # 网页的骨架、只是负责显示一些内容&#xff0c;但是显示出来的内容不好看&#xff0c;没样式 2. CSS # 对网页骨架的美化、让网页变得更加的好看而已 3. JavaScript # html、css都是不能动的&#xff0c;静态的&#xff0c;js就是让网页能够动起来…...

Python之numpy数组学习(五)——广播

Python之numpy数组学习(五)——广播 目录 Python之numpy数组学习(五)——广播 本文章向大家介绍Python之numpy数组学习(五)——广播,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。 前言 前面我们…...

k8s-----19、Helm

Helm 1、引入2、概述2.1 重点2.2 V3版本的Helm2.2.1 与之前版本的不同之处2.2.2 V3版本的运行流程 3、安装和配置仓库、一些附带操作3.1 安装3.2 配置仓库3.3 常用命令3.4 添加helm的自动补齐 4、快速部署应用(weave应用)5、 自行创建Chart5.1 Chart目录内容解析5.2 简单安装部…...

怒刷LeetCode的第28天(Java版)

目录 第一题 题目来源 题目内容 解决方法 方法一&#xff1a;动态规划 方法二&#xff1a;迭代 方法三&#xff1a;斐波那契数列公式 第二题 题目来源 题目内容 解决方法 方法一&#xff1a;栈 方法二&#xff1a;路径处理类 方法三&#xff1a;正则表达式 方法…...

Kotlin(八) 数据类、单例

目录 一&#xff1a;创建数据类 二&#xff1a;单例类 一&#xff1a;创建数据类 和Java的不同&#xff0c;kotlin的数据类比较简单&#xff0c;New→Kotlin File/Class&#xff0c;在弹出的对话框中输入“Book”&#xff0c;创建类型选择“Data”。如图&#xff1a; 然后编…...

IAR For ARM 安装教程

电脑环境 安装包下载 1、官网下载 ①搜索 IAR ②切换产品&#xff0c;选择Arm ③选择IAR Embedded Workbench for Arm ④免费试用 2、网盘下载 EWARM-CD-8202-14838.exe(访问密码: 1666) https://url48.ctfile.com/f/33868548-961057458-611638?p1666 软件下载 1、点击安…...

向量数据库Weaviate Cloud 和 Milvus Cloud:性能大比拼

最近,随着检索增强生成系统(RAG)的持续火爆,开发者对于“如何选择一个向量数据库”的疑惑也越来越多。过去几周,我们从性能和特性能力两个方面对 Weaviate Cloud 和 MilvusCloud 进行了详细的对比。在对比过程中,我们使用了开源的性能基准测试套件 VectorDBBench,围绕诸…...

微信小程序控制元素显示隐藏

微信小程序是一种轻量级的应用程序&#xff0c;它可以在微信中运行&#xff0c;具有快速、便捷、易用等特点。在微信小程序中&#xff0c;我们可以通过控制元素的显示和隐藏来实现特定的功能。本文将介绍如何使用微信小程序控制元素的显示和隐藏&#xff0c;以及如何应用这些技…...

轻量封装WebGPU渲染系统示例<2>-彩色立方体(源码)

当前示例源码github地址: https://github.com/vilyLei/voxwebgpu/blob/version-1.01/src/voxgpu/sample/VertColorCube.ts 此示例渲染系统实现的特性: 1. 用户态与系统态隔离。 2. 高频调用与低频调用隔离。 3. 面向用户的易用性封装。 4. 渲染数据和渲染机制分离。 5. …...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上&#xff0c;你可以使用apt包管理器来安装NFS服务器。打开终端并运行&#xff1a; sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享&#xff0c;例如/shared&#xff1a; sudo mkdir /shared sud…...

DeepSeek 赋能智慧能源:微电网优化调度的智能革新路径

目录 一、智慧能源微电网优化调度概述1.1 智慧能源微电网概念1.2 优化调度的重要性1.3 目前面临的挑战 二、DeepSeek 技术探秘2.1 DeepSeek 技术原理2.2 DeepSeek 独特优势2.3 DeepSeek 在 AI 领域地位 三、DeepSeek 在微电网优化调度中的应用剖析3.1 数据处理与分析3.2 预测与…...

Qt Widget类解析与代码注释

#include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this); }Widget::~Widget() {delete ui; }//解释这串代码&#xff0c;写上注释 当然可以&#xff01;这段代码是 Qt …...

【配置 YOLOX 用于按目录分类的图片数据集】

现在的图标点选越来越多&#xff0c;如何一步解决&#xff0c;采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集&#xff08;每个目录代表一个类别&#xff0c;目录下是该类别的所有图片&#xff09;&#xff0c;你需要进行以下配置步骤&#x…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存

文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

云原生玩法三问:构建自定义开发环境

云原生玩法三问&#xff1a;构建自定义开发环境 引言 临时运维一个古董项目&#xff0c;无文档&#xff0c;无环境&#xff0c;无交接人&#xff0c;俗称三无。 运行设备的环境老&#xff0c;本地环境版本高&#xff0c;ssh不过去。正好最近对 腾讯出品的云原生 cnb 感兴趣&…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中&#xff0c;我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道&#xff0c;它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...