关于Linux Makefile的一些函数知识foreach、if、call、origin、shell、error和warning

1.foreach函数-遍历

在Makefile中如果想做一些循环或遍历操作时,可以使用foreach函数:

$(foreach VAR,LIST,TEXT)

foreach函数的工作过程是:把LIST中使用空格分割的单词依次取出并赋值给变量VAR,然后执行TEXT表达式。重复这个过程,直到遍历完LIST中的最后一个单词。函数的返回值是TEXT多次计算的结果。

使用示例:假设一个项目,MP3播放器,分别有lcd、keyboad、usb、media目录,分别存放不同的源文件:

# tree.├── keyboard│   └── key.c├── lcd│   └── lcd.c├── makefile├── media│   └── decode.c└── usb    └── usb.c

现在编写一个Makefile,自动搜索各个目录下的C源文件。Makefile的写法如下:

.PHONY: alldirs = lcd usb media keyboardsrcs = $(foreach dir, $(dirs), $(wildcard $(dir)/*))all:    @echo "srcs = $(srcs)"

执行make命令,运行结果如下:

# makesrcs =  lcd/lcd.c  usb/usb.c  media/decode.c  keyboard/key.c

当然,我们也可以根据搜索到的这些C源文件名,生成对应的目标文件名,对应的Makefile如下:

.PHONY: alldirs = lcd usb media keyboardsrcs = $(foreach dir, $(dirs), $(wildcard $(dir)/*.c))objs = $(foreach src, $(srcs), $(subst .c,.o,$(src)))all:    @echo "srcs = $(srcs)"    @echo "objs = $(objs)"

执行make命令,运行结果如下:

# makesrcs =  lcd/lcd.c  usb/usb.c  media/decode.c  keyboard/key.cobjs =  lcd/lcd.o  usb/usb.o  media/decode.o  keyboard/key.o

2.if函数-判断

Makefile中的 if 函数提供了在一个函数上下文中实现条件判断的功能,类似于ifeq关键字,if函数的使用格式如下:

$(if CONDITION,THEN-PART)$(if CONDITION,THEN-PART[,ELSE-PART])

if 函数的第一个参数 CONDITION表示条件判断,展开后如果非空,则条件为真,执行 THEN-PART部分;否则,如果有ELSE-PART部分,则执行ELSE-PART部分。

if函数的返回值即执行分支(THEN-PART或ELSE-PART)的表达式值。如果没有ELSE-PART,则返回一个空字符串。

if 函数使用示例:

.PHONY: allinstall_path = $(if $(install__path), $(install__path), /usr/local)all:    @echo "install_path = $(install_path)"

当我们使用make编译安装一个软件时,通常会指定一个安装路径,如果没有指定的话,则会默认安装在/usr/local目录下。在上面这个Makefile中,我们定义了一个install_path变量,通过if函数来判断这个变量是否为空,来决定最终的安装路径。执行make命令,可以看到运行结果如下:

# makeinstall_path =  /usr/local# make install_path=/optinstall_path = /opt

3.call函数

通过前面的学习我们已经知道:如果想在Makefile中调用GNU make的内置函数,我们使用下面的形式调用:

$(function arguments)${function arguments}

如果想调用用户自定义的函数,则只能使用call函数来间接调用了:

PHONY: alldefine func    @echo "pram1 = $(0)"    @echo "pram2 = $(1)"endefall:    $(call func, hello zixue.com)

我们给函数传递的参数,在函数内部可以使用(0)、(1)...直接使用。call函数是唯一一个可以用来创建新的参数化的函数。call函数不仅可以用来调用一个用户自定义函数并传参,还可以向一个表达式传参:

$(call <expression>,<parm1>,<parm2>,<parm3>...)

当 make 执行这个函数时,expression表达式中的参数变量,如(1),(2),$(3)等,会被参数parm1,parm2,parm3依次取代。而expression的返回值就是 call 函数的返回值。

.PHONY: allparam = $(1) $(2)reverse_param = $(2) $(1)str1 = $(call param, hello, zixue.com)str2 = $(call reverse_param, hello, zixue.com)all:    @echo "str1 = $(str1)"    @echo "str2 = $(str2)"

执行make命令,运行结果为:

# makestr1 =  hello  zixue.comstr2 =  zixue.com hello

4.origin函数

顾名思义,origin函数的作用就是告诉你,你所关注的一个变量是从哪里来的。函数的使用格式为:

$(origin <variable>)

如果变量没有定义,origin函数的返回值为:undefined,不同的返回值代表变量的类型不同。常见的返回值如下;

  • default:变量是一个默认的定义,比如 CC 这个变量
  • file:这个变量被定义在Makefile中
  • command line:这个变量是被命令行定义的
  • override:这个变量是被override指示符重新定义过的
  • automatic:一个命令运行中的自动化变量

使用示例:

.PHONY: allWEB = www.zixue.comweb_type = $(origin WEB)all:    @echo "web_type = $(web_type)"    @echo "cc_type  = $(origin CC)"    @echo "cmd_type = $(origin CMD)"

执行make命令,运行结果为:

# makeweb_type = filecc_type = defaultcmd_type = undefined# make CMD=pwdweb_type = filecc_type = defaultcmd_type = command line

5.shell函数

如果你想在Makefile中运行shell命令,可以使用shell 函数来完成这个功能。shell 函数的参数是shell命令,它和反引号 `` 具有相同的功能。shell命令的运行结果即为shell函数的返回值。

.PHONY: allcurrent_path = $(shell pwd)all:    @echo "current_path = $(current_path)"

执行make命令,可以看到运行结果:

root@ubuntu:/home/makefile/demo# makecurrent_path = /home/makefile/demo

make提供了两个可以控制make运行方式的函数:error和warning。如果这两个函数在Makefile中使用,当make执行过程中检测到某些错误,就可以给用户提供一些信息,并且可以控制make的是否继续执行下去。

6.error 函数

$(error TEXT...)

使用示例:

.PHONY: allall:    @echo "make command start..."    $(error find a error)    @echo "make command end..."

当执行make命令时,make会执行默认目标all下的命令,当遇到error函数时,就会给用户一个错误提示信息,并终止make的继续执行:

# makemakefile:5: *** find a error.  Stop.

需要注意的是:error函数是在函数被调用时才会提示信息并终止make的继续执行。如果函数出现在命令中,或者出现在一个递归变量的定义里,在读取Makefile时不会出现错误。而只有包含error函数引用的命令执行时,或者包含这个函数的定义变量被展开时,才会提示错误信息TEXT,并终止make的运行。

7.warning 函数

warning函数跟error函数类似,也会给用户提示信息,唯一的区别是:warning函数不会终止make的运行,make会继续运行下去。

$(warning TEXT...)

使用示例:

.PHONY: allall:    @echo "make command start..."    $(warning find a error)    @echo "make command end..."

执行make命令,运行结果为:

# makemakefile:5: find a errormake command start...make command end...

通过运行结果对比可以看到:warning函数和error函数一样,也会产生一个错误提示信息,但是不会终止make的运行。

相关推荐
sun00770040 分钟前
ubuntu dpkg 删除安装包
运维·服务器·ubuntu
海岛日记42 分钟前
centos一键卸载docker脚本
linux·docker·centos
oi771 小时前
使用itextpdf进行pdf模版填充中文文本时部分字不显示问题
java·服务器
AttackingLin1 小时前
2024强网杯--babyheap house of apple2解法
linux·开发语言·python
吃肉不能购2 小时前
Label-studio-ml-backend 和YOLOV8 YOLO11自动化标注,目标检测,实例分割,图像分类,关键点估计,视频跟踪
运维·yolo·自动化
学Linux的语莫3 小时前
Ansible使用简介和基础使用
linux·运维·服务器·nginx·云计算·ansible
qq_312920113 小时前
docker 部署 kvm 图形化管理工具 WebVirtMgr
运维·docker·容器
踏雪Vernon3 小时前
[OpenHarmony5.0][Docker][环境]OpenHarmony5.0 Docker编译环境镜像下载以及使用方式
linux·docker·容器·harmonyos