Makefile学习-9 常用函数

学习目标:

学习Makefile一下关键字:

addprefix :加前缀 

patsubst:更改后缀

参考: Makefile 简介 - Makefile基本概念介绍 - Makefile 简明教程 | 宅学部落

1- 分支

语法:

ifeq (arg1, xxx)
    do somethings
else ifeq (arg1, yyy)
    do somethings
else
    do somethings
endif

语法和C语言基本一致

注意: 

a- ifeq和后面的条件判断“(xxx)”之间必须有空格

b- 条件判断(arg1, xxx)的arg1和xxx之间可以有空格,也可以不加空格

c- do something可以缩进,也可以不缩进。

d- 如果do something为赋值语句CC = gcc。赋值语句等号前后可以有空格,也可以不加空格

示例:

ifeq ($(ARCH), x86)
	CC = gcc
    $(info "[info]: gcc") 
else ifeq ($(ARCH), arm)
    CC = arm-linux-gcc
    $(info "[info]: arm-linux-gcc") 
else
	CC = arm-linux-gnueabihf-gcc
    $(info "[info]: arm-linux-gnueabihf-gcc") 
endif
all:
	@echo ""

结果:

[root@localhost makefile]# make
"[info]: arm-linux-gnueabihf-gcc"

[root@localhost makefile]# make ARCH=x86
"[info]: gcc"

其他:

对于内核编译模块我们也会使用分支,比如《linux设备驱动程序》就有介绍:

ifneq ($(KERNELRELEASE),)
	obj-m := hello.o
else
	KERNELDIR ?= /lib/modules/$(shell uname -r)/build 
	PWD := $(shell pwd) 
default: 
	$(MAKE) -C $(KERNELDIR) M=$(PWD) modules 
endif

2- 字符处理

2.1- patsubst 正则替换

格式:$(patsubst <pattern>,<replacement>,<text> ) 

功能:查找<text>中的单词(单词以“空格”、“Tab”或“回车”“换行”分隔)是否符合模式<pattern>,如果匹配的话,则以<replacement>替换。这里,<pattern>可以包括通配符“%”,表示任意长度的字串。如果<replacement>中也包含“%”,那么,<replacement>中的这个“%”将是<pattern>中的那个“%”所代表的字串。可以用“\”来转义,以“\%”来表示真实含义的“%”字符
返回:函数返回被替换过后的字符串。如果没有匹配上的原样输出。

场景:替换文件后缀

示例:

ret = $(patsubst %.c,%.o, a.c b.c c.bat)

all:
	@echo "ret: $(ret)"

结果:

ret: a.o b.o c.bat

2.2- subst 普通替换

 格式:$(subst <from>,<to>,<text> ) 

功能:查找<text>中的单词,将from字符替换为to字符

场景:替换字符

示例:

ret = $(subst world, makefile, "hello world")

all:
	@echo "ret: $(ret)"

结果:

ret:  hello makefile

2.3- $(VAR:A=B)--变量替换

格式:$(VAR:A=B)

功能:将变量VAR中匹配A的字符替换成B

返回:返回替换结果。

场景:替换文件后缀

示例:

foo := a.c b.c c.bat
ret := $(foo:.c=.o)
all:
	@echo "ret: $(ret)"

结果:

ret: a.o b.o c.bat

这里发现$(VAR:A=B)和patsubst功能基本相似。

2.4- filter 过滤

 格式:$(filter PATTERN…,TEXT)
功能:过滤掉TEXT中不符合PATTERN的字符
返回:返回匹配结果


示例:

foo = a.c b.c c.s d.h
ret = $(filter %c %s,  $(foo))

all:
	@echo "ret: $(ret)"

结果:

ret: a.c b.c c.s

 2.5- filter-out 反过滤

 格式:$(filter-out PATTERN…,TEXT)
功能:过滤掉TEXT中符合PATTERN的字符
返回:返回匹配结果


示例:

foo = a.c b.c c.s d.h
ret = $(filter-out %c %s,  $(foo))

all:
	@echo "ret: $(ret)"

结果:

ret: d.h

2.6- findstring --字符查找

 格式:$(findstring FIND, IN)

功能:在IN中查找FIND字符

返回:返回查找结果。没找到返回空

示例:

ret1 = $(findstring world,  "hello world")
ret2 = $(findstring makefile,  "hello world")

all:
	@echo "ret1: $(ret1)"
	@echo "ret2: $(ret2)"

结果:

ret1: world
ret2:

2.7- strip--去除空格

格式:$(strip TEXT)

功能:去除TEXT前后空格字符,对于中间多个空格合并为1个空格

返回:返回去除后字符

示例:

str1 :=    abc
str2 := abc      
str3 := a   b  c      

all:
	@echo ---$(strip $(str1))---
	@echo ---$(strip $(str2))---
	@echo ---$(strip $(str3))---

结果:

---abc---
---abc---
---a b c---

2.7- 其他

sort : 排序
world : 取单词
wordlist函数:取字串
words函数:统计单词数目
firstword函数:取首个单词

详情参考:Makefile 文本处理函数(下) : sort、word、wordlist、words、firstword函数详解 - Makefile 简明教程 | 宅学部落

3- foreach 遍历操作

 格式:$(foreach VAR,LIST,TEXT)

功能:遍历LIST中每个变量,每次遍历的中间值保存在VAR,TEXT对VAR处理

返回:返回处理结果。

场景:遍历处理文件后缀;遍历获取所有.c文件等。参考:Makefile foreach函数 - Makefile 简明教程 | 宅学部落

示例:

foo := a b c
ret := $(foreach var,$(foo),$(var).o)

all:
	@echo "ret: $(ret)"

结果:

ret: a.o b.o c.o

4- 目录处理

4.1- wildcard --获取目录下文件

 格式:$(wildcard pattern)

功能:获取匹配pattern规则的信息

返回:返回匹配pattern规则的信息

场景:获取路径下所有.c文件。

示例:

#获取当前路径下的.c文件
ret := $(wildcard *.c)

all:
	@echo "ret: $(ret)"

结果:

ret: a.c b.c

4.2- notdir  dir --去除/获取路径

 格式:$(notdir 文件列表)

功能:去除文件路径

返回:返回去除文件路径后结果

 格式:$(dir 文件列表)

功能:获取文件路径

返回:返回文件路径

示例:

ret_dir := $(dir /home/lhk/a.c)

all:
	@echo "ret_notdir: $(ret_notdir)"
	@echo "ret_dir: $(ret_dir)"

结果:

ret_notdir: a.c
ret_dir: /home/lhk/

 4.3- suffix  basename --获取文件名后缀/前缀

 格式:$(suffix 文件列表) 

功能:获取后缀

 格式:$(basename 文件列表)

功能:获取前缀

示例:

ret_suffix := $(suffix /home/lhk/a.c)
ret_basename := $(basename /home/lhk/a.c)

all:
	@echo "ret_suffix: $(ret_suffix)"
	@echo "ret_basename: $(ret_basename)"

结果:

ret_suffix: .c
ret_basename: /home/lhk/a

 4.4- addprefix,addsuffix :加前缀/后缀 

格式:$(addprefix PREFIX, NAMES…) 
功能:给NAMES…加前缀 PREFIX

格式:$(addsuffix SUFFIX, NAMES…)
功能:给NAMES…加后缀SUFFIX

示例:

first := /home/lhk/
second := lhk_c/main.c
ret_addprefix = $(addprefix $(first), $(second))

foo := a b c
ret_addsuffix = $(addsuffix .c, $(foo))

all:
	@echo "ret_addprefix: $(ret_addprefix)"
	@echo "ret_addsuffix: $(ret_addsuffix)"

结果:

ret_addprefix: /home/lhk/lhk_c/main.c
ret_addsuffix: a.c b.c c.c

参考:addprefix语法介绍

4.5- join 连接

格式:$(join str1..., str2...) 
功能:将str1和str2连接起来

示例:

first = a b c
second = .c .h
ret = $(join $(first),$(second))

all:
	@echo "ret: $(ret)"

结果:

ret: a.c b.h c

综合示例:

摘录野火makefile : http://doc.embedfire.com/linux/imx6/base/zh/latest/linux_app/makefile.html#id13

#定义变量
#ARCH默认为x86,使用gcc编译器,
#否则使用arm编译器
ARCH ?= x86
TARGET = hello_main


#存放中间文件的路径
BUILD_DIR = build_$(ARCH)
#存放源文件的文件夹
SRC_DIR = sources
#存放头文件的文件夹
INC_DIR = includes .

#源文件
SRCS = $(wildcard $(SRC_DIR)/*.c)
#目标文件(*.o)
OBJS = $(patsubst %.c, $(BUILD_DIR)/%.o, $(notdir $(SRCS)))
#头文件
DEPS = $(wildcard $(INC_DIR)/*.h)

#指定头文件的路径
CFLAGS = $(patsubst %, -I%, $(INC_DIR))

#根据输入的ARCH变量来选择编译器
#ARCH=x86,使用gcc
#ARCH=arm,使用arm-gcc
ifeq ($(ARCH),x86)
CC = gcc
else
CC = arm-linux-gnueabihf-gcc
endif

#目标文件
$(BUILD_DIR)/$(TARGET): $(OBJS)
   $(CC) -o $@ $^ $(CFLAGS)

#*.o文件的生成规则
$(BUILD_DIR)/%.o: $(SRC_DIR)/%.c $(DEPS)
#创建一个编译目录,用于存放过程文件
#命令前带“@”,表示不在终端上输出
@mkdir -p $(BUILD_DIR)
$(CC) -c -o $@ $< $(CFLAGS)

#伪目标
.PHONY: clean cleanall
#按架构删除
clean:
   rm -rf $(BUILD_DIR)

#全部删除
cleanall:
   rm -rf build_x86 build_arm

5- origin--变量来源

格式:$(origin 变量)
功能:获取变量来源。来源:命令行,文件定义,环境变量,未定义,自动变量,重定义等
返回:返回变量来源
详细参考:makefile之origin函数 - suonikeyinsu - 博客园
 

示例:

all:
	@echo $(origin vv)

结果:

[root@localhost makefile]# make vv="hello"
command line
[root@localhost makefile]# make
undefined

6- call  --函数调用

格式:$(call VARIABLE,PARAM1,PARAM2,..)
功能:类似函数调用。VARIABLE可以为变量也可以为函数,PARAM为入参值
返回:返回执行结果


示例:

reverse = $(2) $(1)

define func_rev
$(2) $(1)
endef

ret_var = $(call reverse,a,b)
ret_func = $(call func_rev,a,b)

all:
	@echo "ret_var=$(ret_var)"
	@echo "ret_func=$(ret_func)"

结果:

ret_var=b a
ret_func=b a

注意:如果使用变量方式,需要注意变量为reverse = $(2) $(1) reverse := $(2) $(1) 间差别;

传入参数间的空格也会照样认为是入参。


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值