MakeFile教程

news2024/9/28 13:03:04

前言

当我们需要编译一个比较大的项目时,编译命令会变得越来越复杂,需要编译的文件越来越多。其
次就是项目中并不是每一次编译都需要把所有文件都重新编译,比如没有被修改过的文件则不需要重
新编译。工程管理器就帮助我们来优化这两个问题。
MakeFile就类似于make工程管理的工作的脚本。用来告诉工程管理器如何正确的编译我们的程

在这里插入图片描述
依赖于目标的关系:
在MakeFile中依赖于目标是相互的,并不是绝对
在这里插入图片描述
比如 a.c 是生成a.o的一个依赖文件, 对于a.o 则是a.c的目标,a.o 又是image的依赖。
在我们使用make 进行编译的时候,工程管理器则会根据依赖于目标的关系来检查它们之间时间戳
关系,如果依赖有给你更新那么目标文件则需要执行。


安装make

sudo apt install make

语法

target : tgt_dependency1 tgt_dependency2 ...
    command

注意:
目标必须存在
依赖可以没有
命令前面必须是一个制表符TAB
Makefile 文件的命名一般是 Makefile没有后缀也没有前缀
如果规则中没有写依赖,则无论如何该规则该规则都会执行
如果目标已经存在,然后也没有写依赖则不执行该规则

在这里插入图片描述
示例1

Even:Jacy
	@echo "Hello Makefile"

Jacy:ChuiHua
	@echo "Hello Even"

ChuiHua:
	@echo "Hello Jacy"

执行

make // 工程管理器把第一个目标当成最终目标 Even
make Jacy // 告诉工程管理器 Jacy是我们需要的最终目标

示例2
在这里插入图片描述

./bin/main:./src/*.c
	gcc ./src/*.c -o ./bin/main -I./inc -L./lib -lmy_lib

示例3

animal_assembly : moose goose cat
    command
moose : antlers hooves fur
    command
goose : beak wings webbed_feet interest_in_bread
    command
cat : whiskers evil_personality
    command

当不带参数调用时,将尝试构建目标animal_assembly
假设依赖项moosegoosecat已经在目录中可用,它将完全忽略它们的规则,并animal_assembly从现有内容构建
如果moosecat可用,但goose不可用,它会注意到moose存在,看到goose不存在,寻找要构建的规则goose,找到规则,构建goose,然后注意cat存在和构建animal_assembly
如果 moose, goose, cat都不存在,则必须使用可用规则构建所有这些。
一个好的经验法则是将最后和最重要的命令(对于我们的目的,最终将目标文件链接在一起成为可执行文件的命令)放在顶部。

变量:

  1. 变量和函数的展开(除规则的命令行以外),是在make读取Makefile文件时进行的,这里的变量包括了使用“=”定义和使用指示符“define”定义的变量。
  2. 变量可以用来代表一个文件名列表、编译选项列表、程序运行的选项参数列表、搜
    索源文件的目录列表、编译输出的目录列表和所有我们能够想到的事物。
  3. 变量名不能包括“:”、“#”、“=”、前置空白和尾空白的任何字符串。需要注意的是,
    尽管在GNU make中没有对变量的命名有其它的限制,但定义一个包含除字母、数字和下
    划线以外的变量的做法也是不可取的,因为除字母、数字和下划线以外的其它字符可能会在
    以后的make版本中被赋予特殊含义,并且这样命名的变量对于一些Shell来说不能作为环
    境变量使用。
  4. 变量名是大小写敏感的。变量“foo”、“Foo”和“FOO”指的是三个不同的变量。Makefile传统做法是变量名是全采用大写的方式。推荐的做法是在对于内部定义的一般变量(例如:目标文件列表objects)使用小写方式,而对于一些参数列表(例如:编译选项CFLAGS)采用大写方式,这并不是要求的。但需要强调一点:对于一个工程,所Makefile
    中的变量命名应保持一种风格,否则会显得你是一个蹩脚的开发者(就像代码的变量命名风格一样),随时有被鄙视的危险。
  5. 另外有一些变量名只包含了一个或者很少的几个特殊的字符(符号)。称它们为自
    动化变量。像“<”、“@”、“?”、“*”、“@D”、“%F”、“^D”等等,后面会详
    述之。
  6. 变量的引用跟Shell脚本类似,使用美元符号和圆括号,比如有个变量叫A,那么对
    他的引用则是$(A),有个自动化变量叫@,则对他的引用是$(@),有个系统变量是CC
    对其引用的格式是$(CC)。对于前面两个变量而言,他们都是单字符变量,因此对他们引用
    的括号可以省略,写成$A$@。`

自定义变量

顾名思义就是用户自己定义的变量

 A = apple # 定义并赋值变量
B = I love China
C = $(A) tree # $() 则是对某一个变量进行引用

Even:
@echo $(A)
@echo $(B)
@echo $(C)

通过自定义变量来修改的Makefile 第二版本

TAG=./bin/main
SRC=./src/*.c
CC=gcc
O=-o
CONFIG=-I./inc -L./lib -lmy_lib


$(TAG):$(SRC)
	$(CC) $(SRC) $(O) $(TAG) $(CONFIG)


clean:
	rm ./bin/*

系统变量

在这里插入图片描述

自动化变量

自动化变量的值会自动发生变化
在这里插入图片描述

Makefile 中定义的变量有以下几种不同的方式:

1,递归定义方式:

A = I love $(B) # 在第一行使用到变量B但是还没有定义,以此管理器进行全文搜索找到B并引用
B = China

2,直接定义方式:

B = China
A := I love $(B)

此处,定义 A 时用的是所谓的“直接”定义方式,说白了就是如果其定义里出现有对
其他变量的引用的话,只会其前面的语句进行搜寻(不包含自己所在的那一行),而不是搜
寻整个文件,因此,如果此处将变量 A 和变量 B 的定义交换一个位置:

A := I love $(B) # A在B之前引用B 则为空
B = China

则 A 的值将不包含 China,因此在定义 A 时 B 的值为空。

3,条件定义方式:

有时我们需要先判断一个变量是否已经定义了,如果已经定义了则不作操作,如果没有
定义再来定义它的值,这时最方便的方法就是采用所谓的条件定义方式:

A = apple
A ?= I love China

此处对 A 进行了两次定义,其中第二次是条件定义,其含义是:如果 A 在此之前没有
定义,则定义为“I love China”,否则维持原有的值。

4,多行命令定义方式:

define commands
echo “thank you!echo “you are welcome.”
endef

此处定义了一个包含多行命令的变量commands,我们利用它的这个特点实现一个完
整命令包的定义。注意其语法格式:以define开头,以endef结束,所要定义的变量名必须
在指示符“define”的同一行之后,指示符define所在行的下一行开始一直到“end”所在行的
上一行之间的若干行,是变量的值。这种方式定义的所谓命令包,可以理解为编程语言中的
函数。

Makefile中的变量还有以下几种操作方式:

1,追加变量的值,例如:

A = apple
A += tree

这样,变量A的值就是apple tree。
2,修改变量的值,例如:

A = srt.c string.c tcl.c
B = $(A:%.c=%.o)

输出为srt.o string.o tcl.o
第三个版本:

TAG=./bin/main
SRC=./src/Input.c ./src/main.c ./src/Oper.c ./src/Output.c 
OBJ=$(SRC:%.c=%.o)
CC=gcc
O=-o
CONFIG=-I./inc 


$(TAG):$(OBJ)
	 $(CC) $(^) $(O) $(@) $(CONFIG)


%.o:%.c
	$(CC) $< -o $(@) $(CONFIG) -c 

clean:
	$(RM) ./bin/* ./src/*.o

函数

 $(subst FROM,TO,TEXT)

功能:将字符串 TEXT 中的字符 FROM 替换为 TO。
返回:替换之后的新字符串。
范例:

A = $(subst pp,PP,apple tree)

替换之后变量 A 的值是”aPPle tree”


$(wildcard PATTERN)

功能:获取匹配模式为 PATTERN 的文件名。
返回:匹配模式为 PATTERN 的文件名。
范例:

A = $(wildcard *.c)

假设当前路径下有两个.c 文件 a.c 和 b.c,则处理后 A 的值为:”a.c b.c”。


override一个变量,例如:

override CFLAGS += -Wall

.PHONY 来明确地告诉 Makefile,不要对 clean 运用任何隐式规则,不能运用隐式规则的目标被称为
伪目标

 .PHONY:clean 
用来修饰 clean 清空的工作不会被误以为是一个目标来执行

第四版本(通用版本)

TAG=./bin/main
SRC= $(wildcard src/*.c)
OBJ=$(SRC:%.c=%.o)
CC=gcc
override CONFIG += -I./inc 

$(TAG):$(OBJ)
	$(CC) $(^) -o $(@) $(CONFIG)

%.o:%.c
	$(CC) $< -o $(@) $(CONFIG) -c 
clean:
	$(RM) ./bin/* ./src/*.o

.PHONY:clean

在这里插入图片描述

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

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

相关文章

Elasticsearch7.8.0版本进阶——IK中文分词器

目录一、ES 的默认分词器测试示例二、IK 中文分词器2.1、IK 中文分词器下载地址2.2、ES 引入IK 中文分词器2.3、IK 中文分词器测试示例三、ES 扩展词汇测试示例一、ES 的默认分词器测试示例 通过 Postman 发送 GET 请求查询分词效果&#xff0c;在消息体里&#xff0c;指定要分…

python社团 培训记录(自2023年2月24日始)

在单位开设了Python社团&#xff0c;在此记录上课的有关情况&#xff1a; 课程概述&#xff1a;本社团主要针对五、六年级&#xff0c;初始招生&#xff08;上课前&#xff09;28人&#xff08;五、六年级各14人&#xff09;&#xff0c;后&#xff08;上课时&#xff09;人员…

一文让你彻底理解Linux内核调度器进程优先级

一、前言 本文主要描述的是进程优先级这个概念。从用户空间来看&#xff0c;进程优先级就是nice value和scheduling priority&#xff0c;对应到内核&#xff0c;有静态优先级、realtime优先级、归一化优先级和动态优先级等概念。我们希望能在第二章将这些相关的概念描述清楚。…

优秀的网络安全工程师应该有哪些能力?

网络安全工程师是一个各行各业都需要的职业&#xff0c;工作内容属性决定了它不会只在某一方面专精&#xff0c;需要掌握网络维护、设计、部署、运维、网络安全等技能。目前稍有经验的薪资在10K-30K之间&#xff0c;全国的网络安全工程师还处于一个供不应求的状态&#xff0c;因…

Linux | 项目自动化构建工具 - make/Makefile

make / Makefile一、前言二、make/Makefile背景介绍1、Makefile是干什么的&#xff1f;2、make又是什么&#xff1f;三、demo实现【见见猪跑&#x1f416;】三、依赖关系与依赖方法1、概念理清2、感性理解【父与子】3、深层理解【程序的翻译环境 栈的原理】四、多学一招&#…

网络编程(Java)

网络协议通信 IP和端口号 要想使计算机能够通信&#xff0c;必需为每台计算机指定一个标识号&#xff0c;通过这个标识号指定接受数据的计算机或者发送数据的计算机。一般的&#xff0c;IP地址就是一个计算机的标识号&#xff0c;它可以唯一标识一台计算机。 IP地址由两部分组…

AUTOSAR 自适应平台

总目录链接>> AutoSAR入门和实战系列总目录 文章目录AUTOSAR 自适应平台动机标准自适应平台基础基本功能通信安全保障自适应平台服务DemonstratorDemonstrator实现路线图本系列文章由两部分组成&#xff1a;第一部分讨论了AUTOSAR 经典平台&#xff0c;该平台旨在基于微…

Linux下的进程地址空间

Linux下的进程地址空间程序地址空间回顾从代码结果推结论引入进程地址空间页表为什么要有进程地址空间重新理解进程地址空间程序地址空间回顾 我们在初学C/C的时候&#xff0c;我们会经常看见老师们画这样的内存布局图&#xff1a; 可是这真的是内存吗&#xff1f; 如果不是它…

【设计模式】 模板方法模式介绍及C代码实现

【设计模式】 模板方法模式介绍及C代码实现 背景 在软件构建过程中&#xff0c;对于某一项任务&#xff0c;它常常有稳定的整体操作结构&#xff0c;但各个子步骤却有很多改变的需求&#xff0c;或者由于固有的原因&#xff08;比如框架与应用之间的关系&#xff09;而无法和任…

2023年1月综合预订类APP用户洞察——旅游市场复苏明显,三年需求春节集中释放

2023年1月&#xff0c;随着国家对新型冠状病毒感染实施“乙类乙管”&#xff0c;不再对入境人员和货物等采取检疫传染病管理措施&#xff0c;并且取消入境后全员核酸检测和集中隔离&#xff0c;横亘在旅游者与旅游目的地之间的隔阂从此彻底消失。2023年1月恰逢春节假期&#xf…

SQL零基础入门学习(十一)

SQL零基础入门学习&#xff08;十&#xff09; SQL NOT NULL 约束 NOT NULL 约束强制列不接受 NULL 值。 NOT NULL 约束强制字段始终包含值。这意味着&#xff0c;如果不向字段添加值&#xff0c;就无法插入新记录或者更新记录。 下面的 SQL 强制 “ID” 列、 “LastName” …

Mac OSX下使用VMware Fusion 配置静态IP 图文教程指南

目录一. 前言二. Mac OSX下使用VMware Fusion 配置静态IP2.1 了解静态IP如何划分基础知识2.2 Centos7 安装操作系统时图形界面配置静态IP2.3 Centos7安装操作系统后修改动态IP为静态IP三参考文献一. 前言 Mac OSX 下使用VMware Fusion 创建的虚拟机&#xff0c;默认是通过DHCP…

雷达实战之射频前端配置说明

在无线通信领域&#xff0c;射频系统主要分为射频前端,以及基带。从发射通路来看&#xff0c;基带完成语音等原始信息通过AD转化等手段转化成基带信号&#xff0c;然后经过调制生成包含跟多有效信息&#xff0c;且适合信道传输的信号&#xff0c;最后通过射频前端将信号发射出去…

msys2+minGW方案编译ffmpeg的最佳实践

一、Win10 64bit编译环境的建立1&#xff09;从http://www.msys2.org/下载 msys2-x86_64-xxx.exe2&#xff09; 安装msys2到默认路径 C:\msys64\3&#xff09; 运行MSYS2 w644&#xff09;执行 pacman -Syu 更新系统当出现提示时&#xff0c;选择y5) 当窗口关闭时&#xff0c;重…

九龙证券|美股创年内最大周跌幅!美联储官员密集发声!波音重挫近5%

当地时刻2月24日&#xff0c;美股三大指数收盘明显跌落。道指跌1.02%&#xff0c;标普500指数跌1.05%&#xff0c;纳指跌1.69%。 大型科技股普跌&#xff0c;微软、亚马逊跌超2%。波音大跌4.8%&#xff0c;居道指跌幅榜首位&#xff0c;公司因机身部件有问题再次暂停向用户交付…

zabbix4.0-动作-邮件告警

目录 1、创建动作Actions 动作触发流程 创建一个动作 2、配置 Media types 媒介类型&#xff0c;添加一个发件邮箱来发送告警邮件 3、配置 Users Media&#xff0c;添加一个收件邮箱来接收告警邮件 4、更改一个触发器表达式来触发动作Action&#xff0c;最终发送告警邮…

【数据库】MongoDB数据库详解

目录 一&#xff0c;数据库管理系统 1&#xff0c; 什么是数据库 2&#xff0c;什么是数据库管理系统 二&#xff0c; NoSQL 是什么 1&#xff0c;NoSQL 简介 2&#xff0c;NoSQL数据库 3&#xff0c;NoSQL 与 RDBMS 对比 三&#xff0c;MongoDB简介 1&#xff0c; MongoDB 是什…

Python入门教程(非常详细)从零基础入门到精通,看完这一篇就够了

前言 本文罗列了了python零基础入门到精通的详细教程&#xff0c;内容均以知识目录的形式展开。 第一章&#xff1a;python基础之markdown Typora软件下载Typora基本使用Typora补充说明编程与编程语言计算机的本质计算机五大组成部分计算机三大核心硬件操作系统 第二章&…

【LeetCode】剑指 Offer 15. 二进制中1的个数 p100 -- Java Version

题目链接&#xff1a;https://leetcode.cn/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/?favoritexb9nqhhg 1. 题目介绍&#xff08;15. 二进制中1的个数&#xff09; 编写一个函数&#xff0c;输入是一个无符号整数&#xff08;以二进制串的形式&#xff09;&#xff0c;返回…

Systemverilog覆盖率的合并和计算方式

在systemverilog中&#xff0c;对于一个covergroup来说&#xff0c;可能会有多个instance&#xff0c;我们可能需要对这些instance覆盖率进行操作。 只保存covergroup type的覆盖率&#xff0c;不需要保存instance-specified的覆盖率coverage type和instance-specified的覆盖率…