patsubst函数
$(clean-dirs):
make -f ./scripts/Makefile.clean obj=$(patsubst _clean_%,%,$@)
$(clean-dirs) = $(addprefix _clean_, $(u-boot-alldirs)) $(libs-) $(u-boot-dirs) $(libs-y) tools dts/ drivers/net/fm/ lib/ fs/ disk/ drivers/ drivers/dma/ drivers/ddr/fsl/ drivers/ddr/fsl/ drivers/gpio/ drivers/i2c/ drivers/net/ drivers/net/phy/ drivers/power/ drivers/ddr/altera/ drivers/usb/gadget/ drivers/power/domain/ drivers/power/fuel_gauge/ drivers/power/mfd/ drivers/power/pmic/ drivers/power/battery/ drivers/usb/gadget/ drivers/usb/gadget/udc/ drivers/power/regulator/ drivers/spi/ drivers/serial/ drivers/usb/cdns3/ drivers/usb/dwc3/ examples api/ test/ drivers/usb/common/ drivers/usb/emul/ drivers/usb/eth/ drivers/usb/host/ drivers/usb/mtu3/ test/env/ test/optee/ drivers/usb/musb/ drivers/usb/musb-new/ drivers/usb/phy/ drivers/usb/ulpi/ cmd/ test/overlay/ common/ env/ net/
# scripts/Makefile.clean 8 PHONY := __clean 9 __clean: ...... 74 __clean: $(subdir-ymn) 75 ifneq ($(strip $(__clean-files)),) 76 +$(call cmd,clean) 77 endif 78 ifneq ($(strip $(__clean-dirs)),) 79 +$(call cmd,cleandir) 80 endif 81 @: 82 91 PHONY += $(subdir-ymn) 92 $(subdir-ymn): 93 $(Q)$(MAKE) $(clean)=$@ 94 95 .PHONY: $(PHONY)
使用
make -f
命令来直接调用和执行scripts/Makefile.clean
,伪目标为__clean
和$(subdir-ymn)
,由于输入命令没有指定创建的目标,所以默认第一个目标__clean
为终极目标,只需创建终极目标__clean
即可。由上可知,依赖关系如下:
- 创建
__clean
,见《2. 创建 __clean》,删除符合 《__clean-files 变量表格》 和 《clean-dirs 列表》中定义的指定目录,打印和执行;
1.1 创建$(subdir-ymn)
,见《1. 创建 $(subdir-ymn)》,查询 《clean-dirs列表》中的目录及指定子目录中包含Makefile
的目录,打印和执行;
最终:
- 打印和执行 《clean-dirs 列表》中的目录及其指定子目录下所有包含
Makefile
的路径名。【子目录名在$(obj-y) $(obj-m) $(obj-) $(subdir-y) $(subdir-m) $(subdir-) $(subdir-ym)
这些变量中定义,这些变量在列出目录中的Makefile
中定义】- 打印和执行,删除步骤1列出的目录下所有符合下列变量列出的文件或目录。【这些变量在列出的目录或其子目录下的
Makefile
中定义】
$(extra-y) $(extra-m) $(extra-) $(always) $(targets) $(clean-files) $(hostprogs-y) $(hostprogs-m) $(hostprogs-) $(hostlibs-y) $(hostlibs-m) $(hostlibs-) $(hostcxxlibs-y) $(hostcxxlibs-m) $(clean-dirs)
1. 创建 $(subdir-ymn)
# scripts/Makefile.clean 6 src := $(obj) 14 kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) 15 include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) ...... 20 __subdir-y := $(patsubst %/,%,$(filter %/, $(obj-y))) 21 subdir-y += $(__subdir-y) 22 __subdir-m := $(patsubst %/,%,$(filter %/, $(obj-m))) 23 subdir-m += $(__subdir-m) 24 __subdir- := $(patsubst %/,%,$(filter %/, $(obj-))) 25 subdir- += $(__subdir-) 29 subdir-ym := $(sort $(subdir-y) $(subdir-m)) 30 subdir-ymn := $(sort $(subdir-ym) $(subdir-)) 34 subdir-ymn := $(addprefix $(obj)/,$(subdir-ymn)) ...... 38 subdir-ymn := $(foreach f, $(subdir-ymn), $(if $(wildcard $(srctree)/$f/Makefile),$f)) 92 $(subdir-ymn): 93 $(Q)$(MAKE) $(clean)=$@
- 6行:
$(obj)
在命令行make -f ./scripts/Makefile.clean obj=$(patsubst _clean_%,%,$@)
中被定义,所以:
src = $(clean-dirs)列表中的所有值- 14行:由 <6行> 可知,
src = $(clean-dirs)列表中的所有值
,所以:
如果$(clean-dirs)列表中的值 = /%, kbuild-dir = $(clean-dirs)列表中的原值
如果$(clean-dirs)列表中的值 != /%, kbuild-dir =./ $(clean-dirs)列表中的原值- 15行:判断 <14行> 中
kbuild-dir
【即$(clean-dirs)列表中的所有值 】下是否存在Kbuild
文件,
如果存在, 引用该目录下的 Kbuild
如果不存在, 引用该目录下的 Makefile- 20-30行:
subdir-ymn = $(obj-y) $(obj-m) $(obj-) $(subdir-y) $(subdir-m) $(subdir-) $(subdir-ym)
【这些变量在第15行中所引用的文件中定义】,即查询当前目录下的子目录。sort函数、patsubst函数、filter函数- 34行:将查询到的子目录名加上绝对路径。
- 38行:轮询查找所有当前目录和当前目录下的子目录中存在
Makefile
文件的路径名。foreach函数、wildcard函数
目标$(subdir-ymn)
没有依赖,所以只需执行目标的创建语句即可。
最终:打印和执行:make -f ./scripts/Makefile.clean obj=所有存在Makefile文件的目录名
层层查询 《$(clean-dirs)列表》中列出的目录及其子目录中包含Makefile
文件的目录名。【子目录名在$(obj-y) $(obj-m) $(obj-) $(subdir-y) $(subdir-m) $(subdir-) $(subdir-ym)
这些变量中定义,这些变量在主目录中的Makefile
中定义】
2. 创建 __clean
编译前后相应目录下文件对比如下:
目录 编译后 编译前 dts dts/dt.dtb
dts/dt.dtb.S不存在 dts/…/arch/arm/dts dts/…/arch/arm/dts/bcm2837-rpi-3-b.dtb
dts/…/arch/arm/dts/bcm2835-rpi-b-plus.dtb
dts/…/arch/arm/dts/bcm2835-rpi-a-plus.dtb
dts/…/arch/arm/dts/bcm2835-rpi-b.dtb
dts/…/arch/arm/dts/bcm2835-rpi-a.dtb
dts/…/arch/arm/dts/bcm2835-rpi-cm1-io1.dtb
dts/…/arch/arm/dts/bcm2837-rpi-3-b-plus.dtb
dts/…/arch/arm/dts/bcm2835-rpi-zero-w.dtb
dts/…/arch/arm/dts/bcm2835-rpi-b-rev2.dtb
dts/…/arch/arm/dts/bcm2836-rpi-2-b.dtb
dts/…/arch/arm/dts/bcm2837-rpi-3-a-plus.dtb
dts/…/arch/arm/dts/bcm2837-rpi-cm3-io3.dtb
dts/…/arch/arm/dts/bcm2835-rpi-zero.dtb不存在 tools tools/mkenvimage
tools/dumpimage
tools/mkimage
tools/proftool
tools/fdtgrep
tools/spl_size_limit
tools/mkenvimage
tools/dumpimage
tools/mkimage
tools/proftool
tools/fdtgrep
tools/spl_size_limit
tools/gen_eth_addr
tools/gen_ethaddr_crc
tools/img2srec不存在 scripts/basic scripts/basic/fixdep
scripts/basic/fixdep不存在 scripts/dtc scripts/dtc/dtc
scripts/dtc/dtc不存在 scripts/kconfig scripts/kconfig/conf 不存在 其他 不存在 不存在
__clean-files 变量表格 $(extra-y) $(extra-m) $(extra-) $(always) $(targets) $(clean-files) $(hostprogs-y) $(hostprogs-m) $(hostprogs-) $(hostlibs-y) $(hostlibs-m) $(hostlibs-) $(hostcxxlibs-y) $(hostcxxlibs-m)
# scripts/Makefile.clean 6 src := $(obj) 14 kbuild-dir := $(if $(filter /%,$(src)),$(src),$(srctree)/$(src)) 15 include $(if $(wildcard $(kbuild-dir)/Kbuild), $(kbuild-dir)/Kbuild, $(kbuild-dir)/Makefile) ...... 44 __clean-files := $(extra-y) $(extra-m) $(extra-) \ 45 $(always) $(targets) $(clean-files) \ 46 $(hostprogs-y) $(hostprogs-m) $(hostprogs-) \ 47 $(hostlibs-y) $(hostlibs-m) $(hostlibs-) \ 48 $(hostcxxlibs-y) $(hostcxxlibs-m) 50 __clean-files := $(filter-out $(no-clean-files), $(__clean-files)) 56 __clean-files := $(wildcard \ 57 $(addprefix $(obj)/, $(filter-out $(objtree)/%, $(__clean-files))) \ 58 $(filter $(objtree)/%, $(__clean-files))) 62 __clean-dirs := $(wildcard \ 63 $(addprefix $(obj)/, $(filter-out $(objtree)/%, $(clean-dirs))) \ 64 $(filter $(objtree)/%, $(clean-dirs))) ...... 69 cmd_clean = rm -f $(__clean-files) 71 cmd_cleandir = rm -rf $(__clean-dirs) ...... 74 __clean: $(subdir-ymn) 75 ifneq ($(strip $(__clean-files)),) 76 +$(call cmd,clean) 77 endif 78 ifneq ($(strip $(__clean-dirs)),) 79 +$(call cmd,cleandir) 80 endif 81 @:
由上面 《1. 生成目标 $(subdir-ymn)》可知,目标
__clean
的依赖已经生成,接下来执行目标__clean
的生成语句。
wildcard函数、addprefix函数、filter-out函数、filter函数、strip函数、call函数、cmd函数
- 6-15行:由《1. 创建 $(subdir-ymn)》可知,这里会引用相应目录下的
Kbuild
或Makefile
- 44行: 《__clean-files 变量表格》 中的变量都在 <6-15行> 引用的
Kbuild
或Makefile
文件中定义。- 50行:
$(no-clean-files)
为空,所有这里是将第44行中变量为空的部分过滤掉。- 56行:查找 《__clean-files 变量表格》 中不符合
./%
模式的单词,将其添加$(obj)/
前缀,并查找符合./%
模式的单词,最后通过wildcard函数
去相应目录下匹配指定模式的所有文件名列表,如果相应目录下没有指定文件名则匹配失败返回空字符串。【即列出当前目录下符合 《__clean-files 变量表格》 定义的指定文件,不存在不列出】- 62行:列出
$(clean-dirs)
<在15行引用的Kbuild或Makefile文件中定义>中定义的指定目录,不存在不列出。- 75-77行:删除并回显 <56行> 中列出的文件
- 78-80行:删除并回显 <62行> 中列出的目录
- 81行:
@
表示不显示源命令,:
是bash的内建命令,效果就是就是什么都不做, 并且总是返回状态0,所以总体来说@:
就是什么都不做,如果后面有参数,等同于注释掉。
最终:
- 删除当前目录下符合 《__clean-files 变量表格》 定义的指定文件。
- 打印和执行,删除 《clean-dirs 列表》中定义的指定目录<在15行引用的
Kbuild
或Makefile
中定义>。