make/Makefile学习之三Makefile文件中各类函数的使用


说明
本小节所有实例主要采用Linux-Kernel-4.13中的首Makefie源码片断,未采用部分,在案例中备注了源码出处
实现中Makefile文件路径为:/opt/linux-kernel/linux-kernel-4.13/linux-4.13

一、文件名操作函数

1.1、dir取目录函数

1、语法:$(dir <'string>)
2、功能:根据字符串(或变量)返回对应的目录名
3、举例:

#   $(wildcard <path/*.*>)
#                  功能:
                        匹配路径path下所有的某类文件,如path/*_defconfig,表示匹配所以_defconfig结尾的文件
#    $(dir <pathname>)
#                  功能:
#                      根据函数wildcard返回值,取目录名
board-dirs := $(dir $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*/*_defconfig))
# board-dirs 值为:$(srctree)/arch/$(SRCARCH)/configs/*/  注:变量srctree和SRCARCH为之前定义好的,*为通配文件夹名 

1.2、notdir取文件名函数

1、语法:$(notdir <'string>)
2、功能:根据字符串(或变量)返回文件名
3、举例:

#     $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*_defconfig) 
#             功能:返回$(srctree)/arch/$(SRCARCH)/configs/目录下所有以_deconfig结尾的文件名及路径
#                   并将返回值赋值组boards变量
#     $(notdir $(boards))
#             功能:根据boards变量的,得到对应的文件名
#     $(sort ...)
#             功能:对获取到的文件名排序,并将排序后的文件名做为值赋值给boards变量
boards := $(wildcard $(srctree)/arch/$(SRCARCH)/configs/*_defconfig)
boards := $(sort $(notdir $(boards)))

1.3、suffix取后缀函数

1、语法:$(suffix<'string>)
2、功能:根据字符串(或变量)返回一个后缀(扩展名)
3、举例:

#因linux kernel 4.13中没有使用到当前函数,故自行举例
#    FILEPATH 变量值保存了4个文件名
#    $(suffix ...)
#             功能:对FILEPATH变量值取后缀,并返回组变量file_suffix
FILEPATH ?= /usr/src/linux-headers-5.4.0-45/Kconfig drivers/i2c/i2c-core.h Makefile.bak Makefile
file_suffix :=$(suffix $(FILEPATH))
all :
        @echo $(file_suffix)

1.4、basename取前缀函数

1、语法:$(basename <'string>)
2、功能:根据字符串(或变量)返回前缀
3、举例:

#    源码位置:arch/powerpc/boot/Makefile
#    src-wlib变量和src-plat变量值保存了更多源文件,没有一一列出,可通过源码查看
#    $(addprefix argv1 , argv2)
#              功能:为变量argv2增加前缀argv1,即在这里是为:文件名加路径前将值返回给变量src-boot
#    $(basename ...)
#              功能:返回变量src-boot值中各元素的前缀
#    $(addsuffix argv1, argv2)
#              功能:为变量argv2添加后缀argv1,即:在这里是将$(basename ...)的返回值中各元素加一个后缀,得到的新值,返回给obj-boot变量
#........省略更多....................
src-boot := $(src-wlib) $(src-plat) empty.c

src-boot := $(addprefix $(obj)/, $(src-boot))
obj-boot := $(addsuffix .o, $(basename $(src-boot)))

1.5、addsuffix加后缀函数

1、语法:$(addsuffix <'argv1> , <'string>)
2、功能:为变量string各元素增加后缀argv1,将增加后缀后的值返回
3、举例:

    见 1.4举例

1.6、addprefix加后缀函数

1、语法:$(addprefix <'argv1> , <'string>)
2、功能:为变量string各元素增加前缀argv1,将增加前缀后的值返回
3、举例:

    见 1.4举例

1.7、join加后缀函数

1、语法:$(join <'argv1> , )
2、功能:为变量string各元素增加前缀argv1,将增加前缀后的值返回
3、举例:

#  因linux kernel 4.13中Makefile文件没有使用到此函数,以下代码为自行编写
#  $(join argv1,argv2)
#          功能:将argv1和argv2中各元素一一连接组成新的值并返回
#               注:如argv1和argv2数量不匹配,用空匹配  
#  Makefile start
FILE_a := pstored.conf pstore sda
PATH_a := /etc/systemd/ /ect/systemd/  /dev/
FILE_b := pstored.conf pstore
PATH_b := /etc/systemd/
FILE_c := pstored.conf pstore
PATH_c := /etc/systemd/ /ect/systemd/  /dev/
all :
        @echo $(join $(PATH_a),$(FILE_a))
        @echo $(join $(PATH_b),$(FILE_b))
        @echo $(join $(PATH_c),$(FILE_c))
#  Makefile end
#执行结果如下:
$ make
/etc/systemd/pstored.conf /ect/systemd/pstore /dev/sda
/etc/systemd/pstored.conf pstore
/etc/systemd/pstored.conf /ect/systemd/pstore /dev/

二、foreach遍历函数

1、语法:$(foreach <'tmp_var> , <'list> , <'text>)
                参数说明:
                        tmp_var :临时变量,生命周期仅到foreach函数运行结束,
                                  主要用于存储每次遍历list变量的得到的值。
                        list    : 一个变量的列表
                        text    : 一个用于保存tmp_var值的列表                                                                                  
2、功能:遍历列表list中的每一个值,一一存入tmp_var临时变量中,
         text变量保存对tmp_var变量的操作方法
3、举例:
        见 三、if函数举例

三、if条件判断函数

1、语法:$(if <条件> , <执行语句1>) 或
$(if <条件> , <执行语句1> , <执行语句2>)
2、功能:如果条件成立,执行条件1,否则执行条件2
3、举例:

#    $(if $(boards) ... , ...)
#           判断变量boards是否有值,如果有值执行$(foreach ... , ...)语句
#                                  如果没有值,执行: echo ''
#     $(foreach ... , ...)
#          当board变量有值是,foreach函数依次遍历board变量中的元素,并保存于临时变量b中,
#                             printf()函数格式化变量b后,进行打印
#     printf()函数 :
#                  %-24s   < --- >  $(b)                     将临时变量b左对齐,24字符输出
#                  %s      < --- >  $(subst _defconfig,,$(b) 将变量b中的_defconfig替换为空,并返回,格式化为字符串输出

@$(if $(boards), \
                $(foreach b, $(boards), \
                printf "  %-24s - Build for %s\\n" $(b) $(subst _defconfig,,$(b));) \
                echo '')

四、call自定义函数

1、语法:$(call <用户自定义表达式> , , , …)
2、功能 : 用户事先定义一个表达,当调用call函数时,会自动执行用户自定义的表达式,
并将参数argv1 … … 传递给用户自定义的表达式。
3、举例:

#   $(call cmd,rmdirs)函数分析
#      cmd
#          cmd自定义表达式的定义在源文件scripts/Kbuild.include ,源码通过include导入
#      cmd = @$(echo-cmd) $(cmd_$(1)) 
#          变量echo-cmd在scripts/Kbuild.include有定义,详见下源码。
#          变量cmd_$(1) 展开后为:cmd_rmdirs
#      通过以下分析,自定义表达式$(call cmd,rmdirs)函数等同于:
#                cmd_rmdirs = rm -rf $(rm-dirs)
#                $(if $($(quiet)cmd_$(1)),\  #这里展开应为:if(cmd_rmdir , 或if( quiet_cmd_rmdir,
#                         echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)
#                
include scripts/Kbuild.include
#..........省略更多...............
#以下为变量相关的定义源码
ifeq ($(KBUILD_VERBOSE),1)
  quiet =
  Q =
else
  quiet=quiet_
  Q = @
endif
quiet_cmd_rmdirs = $(if $(wildcard $(rm-dirs)),CLEAN   $(wildcard $(rm-dirs)))
      cmd_rmdirs = rm -rf $(rm-dirs)
quiet_cmd_rmfiles = $(if $(wildcard $(rm-files)),CLEAN   $(wildcard $(rm-files)))
      cmd_rmfiles = rm -f $(rm-files)
#.........省略更多,以下为call函数使用的源码.......................
clean: $(clean-dirs) #
        $(call cmd,rmdirs)
        $(call cmd,rmfiles)

#源码位置 :scripts/Kbuild.include
echo-cmd = $(if $($(quiet)cmd_$(1)),\
        echo '  $(call escsq,$($(quiet)cmd_$(1)))$(echo-why)';)

cmd = @$(echo-cmd) $(cmd_$(1))

五、origin变量定义信息函数

1、语法:$(origin )
2、功能 : 返回变量的状态

             undefined : 如果变量var没有定义,origini函数返回 undefined;
             default      : 如果变量var的值是一个make工具默认的值,返回default
             environment : 如果变量var的值是一个环境变量,返回environment
             file: 如果变量var的值定义在makefile文件中,返回file
             command line :  如果变量var的值在命令行中定义,返回command line
             override :  如果变量var的值被override指示符重新定义,则返回override
             automatic :  如果变量var的值是一个命令运行中的自动化变量,则返回automatic

3、举例:

#    $(origin M) 
#             返回变量M的定义类型
#   当M为命令行定义值的时候,向下执行
ifeq ("$(origin M)", "command line")
  KBUILD_EXTMOD := $(M)
endif

六、shell函数

1、语法:$(shell <shell_cmd> , …)
2、功能 : 执行一个shell命令
3、举例

#    ifneq(...)
#         当变量KBUILD_OUTPUT值不为空时,向下执行
#     $(shell ...)
#           执行mkdir -p $(KBUILD_OUTPUT) 命令
#           执行cd $(KBUILD_OUTPUT)       命令
#           执行 /bin/pwd                 命令
ifneq ($(KBUILD_OUTPUT),)
# check that the output directory actually exists
saved-output := $(KBUILD_OUTPUT)
KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \
                                                                && /bin/pwd)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值