Makefile学习之路5——通过函数增强功能
通过函数能显著增强Makefile的功能。对于simple项目的Makefile,尽管使用了模式规则,但还是有一件比较麻烦的事情,就是要在Makefile中指明每一个项目源文件。下面介绍几个后期会使用到的函数,更多请参考《GUN Make》。
1.abspath函数
从命名就应该能够猜出它的作用。abspath函数用于将_name中的各路径名转化成绝对路径,并将转化后的结果返回。调用形式为:
$(abspath _name)
.PHONY: all
root :=$(abspath /uer/../lib)
all:
@echo $(root)

2.addprefix函数
addprefix函数用于给名字列表_name中的每一个名字增加前缀_prefix,并将增加了前缀的名字列表返回,调用形式为:
$(addprefix _prefix,_name)
.PHONY: all
without_dir=main.c foo.c
with_dir :=$(addprefix objs/,$(without_dir))
all:
@echo $(with_dir)

3.addsuffix函数
和前面addprefix刚好相反,addsuffix函数为_name增加后缀_suffix,调用形式为:
$(addsuffix _suffix,_name)
.PHONY: all
without_dir=main foo
with_dir :=$(addsuffix .c,$(without_dir))
all:
@echo $(with_dir)

4.filter函数
filter函数被用于从一个名字列表_text中根据模式_patterm得到满足需要的名字列表并返回,其形式是:
$(filter _pattern,_text)
.PHONY: all
sources =foo.o bar.c main.c hell.s
sources :=$(filter %.c %.s,$(sources))
all:
@echo $(sources)

5.eval函数
eval函数的存在使得Makefile具有动态语言的特征。eval函数使得make将再一次解析_text语句。eval返回空字符串,调用形式为:
$(eval _text)
.PHONY: all
sources =foo.o bar.c main.c hell.s
$(eval sources :=$(filter %.c %.s,$(sources)))
all:
@echo $(sources)

虽然它和上面第四个函数运行结果完全一样,但是在某些场合却必须用eval。可参考:http://bbs.chinaunix.net/thread-2321462-3-1.html
eval的二次展开,是递归的一种形式,因为有时候在Makefile的表达式中,最后得出来的可能还是Makefile的表达式而非真正我们想要传递的值,需要再展开Makefile的表达式得到最终的结果。
6.filter-out函数
该函数用于从名字列表_text中根据模式_pattern滤除一部分名字并将滤除后的列表返回,其形式为:
$(filter-out _pattern,_text)
.PHONY: all
objs =foo.o main.o main1.o main2.o
result :=$(filter-out main%.o,$(objs))
all:
@echo $(result)

7.notdir函数
该函数用来从路径_name中抽取文件名,并将文件名返回。其形式为:
$(notdir _name)
.PHONY: all
file_name :=$(notdir c/d/e/f/a.c q/w/e/r/b.c)
all:
@echo $(file_name)

8.patsubst函数
该函数用来将名字列表_text中符合_pattern模式的名字替换成_replacement,并将替换后的名字列表返回。其形式为:
$(patsubst _pattern,_replacement,_text)
.PHONY: all
mixed=foo.c bar.c main.o
objs :=$(patsubst %.c,%.o,$(mixed))
all:
@echo $(objs)

9.realpath函数
该函数用于获取_name所对应的真实路径名。其形式为:
$(realpath _name)
.PHONY: all
root :=$(realpath ./)
all:
@echo $(root)

10.strip函数
如果希望清除名字列表中的多余空格,strip函数是最佳选择,它将_string中的多余空格去除后返回。其形式为:
$(strip _string)
.PHONY: all
ori=foo.c main.c
res:=$(strip $(ori))
all:
@echo "$(ori)"
@echo "$(res)"

这里对echo命令做了一点变动,细心的人已经发现加了一个双引号,如果不加双引号,这里的两个输出将是相同的。
双引号用于保持引号内所有字符的字面值(回车和空格也不例外)。
11.wildcard函数
该函数是通配符函数,通过它可以得到当前工作目录中满足_pattern模式的文件或目录名列表。其形式为:
$(wildcard _pattern)
.PHONY:all
srcs=$(wildcard *.c)
all:
@echo $(srcs)

有了上面函数的基础之后,我们来看看之前的simple项目,对它进行改进:
之前的代码:
.PHONY: clean CC = gcc
RM = rm EXE =simple
OBJS =main.o foo.o $(EXE): $(OBJS)
$(CC) -o $@ $^
%.o : %.c
$(CC) -o $@ -c $^
clean:
$(RM) -rf $(EXE) $(OBJS)
还是要手动添加源文件,麻烦,运用函数之后,改进如下:
.PHONY: clean CC = gcc
RM = rm EXE =simple
SRCS =$(wildcard *.c)
OBJS =$(patsubst %.c, %.o, $(SRCS))
$(EXE): $(OBJS)
$(CC) -o $@ $^
%.o : %.c
$(CC) -o $@ -c $^
clean:
$(RM) -rf $(EXE) $(OBJS)

此时我们增加一个源文件,touch bar.c,看看我们的Makefile需不需要修改。

从结果看,不用修改Makefile就可以增加源文件了,同理,删除也一样,这样的Makefile具有更好的鲁棒性。
Makefile学习之路5——通过函数增强功能的更多相关文章
- Makefile学习之路6——让编译环境更加有序
在大多项目中都会合理设计目录结构来提高维护性,在编译一个项目时会产生大量中间文件,如果中间文件直接和源文件放在一起,就显得杂乱而不利于维护.在为现在这个complicated项目编写makefile之 ...
- IOS学习之路-- 指针&宏函数
如果*p被()包住,说明指针变量p将来指向的是函数 //声明一个指针变量 //int (*p)(int, int) = sum; int (*p)(int, int); p = sum; // 如果* ...
- Python3学习之路~3.1 函数基本语法及特性、返回值、参数、局部与全局变量
1 函数基本语法及特性 定义: 函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执行这个函数,只需调用其函数名即可 特性: 减少重复代码 使程序变的可扩展 使程序变得易维护 语法定义: d ...
- Makefile学习之路——4
变量的类别有递归扩展变量和简单扩展变量.只用一个“=”符号定义的变量被称为递归扩展变量.通过下面例子观察递归扩展变量的特点. .PHONY: all foo=$(bar) bar=$(ugh) ugh ...
- Makefile学习之路——2
让你的makefile更专业. 在上一个Makefile所在目录下通过touch命令创建一个clean文件,执行make clean,将发现make总是提示clean文件是最新的,而不是按我们期望的那 ...
- Makefile学习之路——3
特殊变量: 在Makefile中,有两个变量特殊变量会经常用到:MAKE和MAKECMDGOALS.MAKE变量表示的是当前处理Makefile的命令名是什么.当需要在Makefile中运行另一个Ma ...
- Makefile学习之路——1
编写makefile,不是一个猛子扎进去试着写一个规则并对之调试,而应该先采用面向依赖关系的思考方法勾勒出makefile要表达怎样的依赖关系,这一点尤为重要.通过不断地练习这种思考方法,才可能达到流 ...
- php学习之路:php在iconv功能 详细解释
iconv函数库可以完毕各种字符集间的转换,是php编程中必不可少的基础函数库. 使用方法例如以下: $string = "亲爱的朋友欢迎訪问胡文芳的博客.希望给您带来一点点的帮助!&quo ...
- Python3学习之路~0 目录
目录 Python3学习之路~2.1 列表.元组操作 Python3学习之路~2.2 简单的购物车程序 Python3学习之路~2.3 字符串操作 Python3学习之路~2.4 字典操作 Pytho ...
随机推荐
- go语言基础之有参有返回值函数的使用
1.有参有返回值函数的使用 示例1: package main //必须 import "fmt" //go官方推荐写法 func MaxAndMin(a, b int) (max ...
- 我的Mac必备软件
1.Svn工具: Cornerstone_v2.7.10 2.iPhone配置文件管理 iPhoneConfigUtility.dmg 3.有道 for mac http://cidian.youda ...
- js版根据经纬度计算多边形面积(墨卡托投影)
[摘要:var earthRadiusMeters = 6371000.0; var metersPerDegree = 2.0 * Math.PI * earthRadiusMeters / 360 ...
- Thinkphp学习笔记2-
因为操作方法就是控制器的一个方法,所以遇到有和系统的关键字冲突的方法可能就不能定义了,这个时候我们可以设置操作方法的后缀来解决,例如: 'ACTION_SUFFIX' => 'Action', ...
- SQLServer 之 聚合函数
一.聚合函数介绍 1.聚合函数最常用的: (1) COUNT:求个数 count函数用于计算满足条件的数据项数,返回int数据类型的值. [1] 语法结构:COUNT( {[[ all | disti ...
- Quartz.Net的使用(简单配置方法)定时任务框架
Quartz.dll 安装nuget在线获取dll包管理器,从中获取最新版 Quartz.Net是一个定时任务框架,可以实现异常灵活的定时任务,开发人员只要编写少量的代码就可以实现“每隔1小时执行”. ...
- 阿里云服务器 centos7 ftp安装
昨天租了阿里云服务器一个月,想玩一下linux系统,结果想用ftp上传本地文件的时候,发现用不了,结果在安装配置的时候折腾了几个小时,在网上查了无数的资料,有的说要改配置文件,有的说要关防火墙,说啥的 ...
- Linux中setup命令command not found如何解决?
1.安装setuptool yum -y install setuptool 2.系统服务管理 yum -y install ntsysv 3.setup中配套的防火墙设置也得装上去,不然会出 ...
- PotPlayer 如何设置多屏幕全屏播放
如何在播放器中,设置扩展播放模式? 全屏设置/主全屏显示设备:Display2 如何使视频播放时,没有黑边并且全屏充满? 高宽比/处理方式:保持全屏宽高比 如果取消掉视频上方的文字提示信息 ...
- HDU 5336 XYZ and Drops
Problem Description XYZ is playing an interesting game called "drops". It is played on a r ...