当前位置:网站首页>make和Makefile总结二
make和Makefile总结二
2022-07-19 01:45:00 【加油!加油!再加油!】
该系列将会一步一步的从最基本的Makefile文件编写讲到复杂项目的Makefile编写
一:最基本的编译多文件的Makefile编写
编写Makefile的第一步,不是一个猛子扎进去试着写一个规则并对之调试,
而应先采用面向依赖关系的思考方法勾勒出Makefile要表达怎样的依赖关系,
这一点至关重要。通过不断地练习这种思考方法,才可能达到流畅地编写Makefile。
假如我们现在有这么一个项目:mian.c 和 fun.c
mian.c中有用到fun.c中定义的函数
我们第一反应的依赖关系应该是:
main 依赖于 main.c 和 fun.c
但这样的依赖关系,在现实的项目中,会使Makefile的可维护性很差,我们
应该让依赖关系尽可能详细当也不能太复杂
所以就有下面这样的依赖关系:
main 依赖于 main.o 和 fun.o
mian.o 依赖于 main.c
fun.o 依赖于 fun.c
也就可以写出下面这段Makefile
main:mian.o fun.o
gcc -o main main.o fun.o
mian.o:main.c
gcc -o main.o -c main.c
fun.o:fun.c
gcc -o fun.o -c fun.c
.PHONY:clean
clean:
rm fun.o main.o main
- 这样最基本的编译多文件的Makefile文件就写好了
二:使用变量,提高Makefile的可维护性
.PHONY:clean
CC = gcc
RM = rm
EXE = main
OBJS = main.o fun.o
$(EXE):$(OBJS)
$(CC) -o $(EXE) $(OBJS)
mian.o:main.c
$(CC) -o main.o -c main.c
fun.o:fun.c
$(CC) -o fun.o -c fun.c
clean:
$(RM) $(EXE) $(OBJS)
我们引入了CC,RM,EXE,OBJS四个变量,使用变量时采用$(变量名) 或 ${变量名}
或许对于这个项目来说使不使用变量都感觉差不多,但是在更一点的项目中变量就能起很大的作用了
三:自动变量
在Makefile经常会存在目标名和先决条件名在规则的命令中重复出现。
如果目标名或先决条件名发生了改变,那得在相应的命令中跟着改,这很麻烦。
为了省去这种麻烦,我们可以借助如下一些自动变量。
自动变量 | 说明 |
---|---|
[email protected] | 用于表示一个规则中的目标。当一个规则中有多个目标时,[email protected]所指的是其中任何造成规则命令被运行的目标。 |
$^ | 表示的是规则中的所有先决条件 |
$< | 表示的是规则中的第一个先决条件 |
$% | 当目标文件是一个静态库文件时,代表静态库的一个成员名 |
$? | 所有比目标文件更新的依赖文件列表,空格分隔。如果目标文件时静态库文件,代表的是库文件(.o 文件) |
$+ | 类似“$^”,但是它保留了依赖文件中重复出现的文件。主要用在程序链接时库的交叉引用场合 |
$* | 在模式规则和静态模式规则中,代表“茎”。“茎”是目标模式中“%”所代表的部分(当文件名中存在目录时,“茎”也包含目录部分) |
一般我常用的自动变量就前3个
还有两个特殊的变量:MAKE和MAKECMDGOALS
$(MAKE):就是当前处理Makefile的命令是什么,一般是就是make
$(MAKECMDGOALS):当前构建的目标名
四:变量的定义和赋值
1.递归扩展变量:只用"="来赋值的
例如:
name = $(ch) -o
ch = $(gd)
gd = sz
最后使用$(name)就是sz -o
如果是name = $(name) -o,就会形成一个死循环
2.简单扩展变量:就是使用":="来赋值的
例如:
name := $(ch) -o
ch := $(gd)
gd := sz
最后使用$(name)就是 -o
可以自行试一下下面这个例子来看看输出:
.PHONY:all
x=foo
y=$(x) b x-later
xx:=foo
yy:=$(xx)b xx*later
all:
@echo"x=$(y),xx=$(yy)"
3.判断赋值:“?=”,使用?=时然后变量之前没有定义就赋值,如果已经定义就不赋值
4.追加赋值:“+=”,就是在变量原本的值后面继续追加值
5.变量的值不仅是从Makefile文件中的定义获取,还可以来自shell环境中定义的变量
make_name ?= make_name
all:
@echo "make_name:$(make_name)"
先直接make看看这个段Makefile会输出什么
再先在shell上运行export make_name=111,然后再make看看会输出什么
6.引用变量的高级用法:
source = main.c fun.c fun2.c
objs = $(source:.c=.o)
这时候$(objs)就是main.o fun.o fun2.o
7.避免变量被覆盖的方法:
使用override name = xxx,这样后面就修改不了变量了
五:借助"模式"来精简规则
如果我们的项目有很多个.c文件,那每一个.c文件都要手动加一个规则来生成.o文件,那就太麻烦了
我们可以使用通配符来简化这一操作
就可以将上面第二点中的Makefile简化成这样:
.PHONY:clean
CC = gcc
RM = rm
EXE = main
OBJS = main.o fun.o
$(EXE):$(OBJS)
$(CC) -o $(EXE) $(OBJS)
%.o:%.c
$(CC) -o [email protected] -c $^
clean:
$(RM) $(EXE) $(OBJS)
- 这样Makefile文件又更进一步了
边栏推荐
猜你喜欢
带你认识C语言自定义类型——结构体、枚举、联合
【LeetCode每日一题】——109.有序链表转换二叉搜索树
VLAN aggregation
U++ 子系统
认证培训|StreamNative Certification 培训第 2 期
Introduce you to C language custom types - structure, enumeration, union
【论文阅读】CoaT:Co-Scale Conv-Attentional Image Transformers
走进企业系列 |StreamNative x 众安保险
Enter the enterprise series | streamnational x Zhong'an insurance
【读书笔记】用户画像方法论与工程化解决方案
随机推荐
Based on yarn1 Sharing of monorepo practice of X
INE Penetration Testing Basics 黑盒渗透测试过程
【自校正控制】递推最小二乘法
09基于ZigBee的水质监测系统设计
[leetcode daily question] - 108 Convert an ordered array into a binary search tree
Grass is flying all over the sky
B树 B+树
线程与进程------理论篇
Leetcode exercise - Sword finger offer 32 - III. print binary tree III from top to bottom
3、上传头像到七牛云并显示
云主机内网通信ping不通问题处理过程
Jenkins学习笔记详细
中信证券手机流程开户安全吗,VIP账户怎么开
Conditions and details of polar coordinate substitution for solving the limit of multivariate functions with high numbers
什么是JSX?
c语言---程序环境与预处理
二分查找 33. 搜索旋转排序数组
文章设置置顶
React.Context和redux缓存的数据无法跨浏览器Tab共享,怎么解决?
亲测五种高效实用的脱单方法,赶紧收藏帮你快速找到优质对象!