带有模式和通配符的 Makefile:没有规则来创建目标
Makefile with pattern and wildcards: No rule to make target
我有为我创建平台的工具。我有一个依赖于这些生成源的目标。这个目标必须是通用的(通用的意思是,它使用一种模式:.build_bsp_%
)——所以我不能使用 $(shell find...)
.
所以当提前创建平台时,一切正常:
$ make platform
mkdir -p platform/a53/AFS/bsp/
touch platform/a53/AFS/bsp/generated.c
mkdir -p platform/r5/MMO/bsp/
touch platform/r5/MMO/bsp/generated.c
$ make .build_bsp_AFS
-> make -C platform/a53/AFS/bsp
$
但是当源不存在时 - 因为平台不存在 - 它不起作用:
$ make .build_bsp_AFS
make: *** No rule to make target '.build_bsp_AFS'. Stop.
$
这是我的问题的精简版:
GENERATE_PLATFORM=platform/a53/AFS/bsp/generated.c platform/r5/MMO/bsp/generated.c
platform: $(GENERATE_PLATFORM)
$(GENERATE_PLATFORM):
mkdir -p $(dir $@)
touch $@
.build_bsp_%: platform/*/%/bsp/*.[chS] $(GENERATE_PLATFORM)
@echo " -> $(MAKE) -C $(dir $^)"
@touch $@
恐怕我必须走一条完全不同的路...
这不是一个很好的解决方案 - 但在提问时,我发现了一个可能的 "workaround":不要在先决条件中使用正则表达式并对(尚未)生成的源文件使用空规则:
GENERATE_PLATFORM=platform/a53/AFS/bsp/generated.c platform/r5/MMO/bsp/generated.c
%.c: ;
%.h: ;
%.S: ;
platform: $(GENERATE_PLATFORM)
$(GENERATE_PLATFORM):
mkdir -p $(dir $@)
touch $@
.build_bsp_%: platform/*/%/bsp/*.c platform/*/%/bsp/*.h platform/*/%/bsp/*.S $(GENERATE_PLATFORM)
@echo " -> $(MAKE) $(dir $<)"
@touch $@
遗憾的是,您不能将此 'last-resort for sources' 限制为例如只有 bsp 文件夹...但它正在工作:
$ make .build_bsp_MMO
mkdir -p platform/a53/AFS/bsp/
touch platform/a53/AFS/bsp/generated.c
mkdir -p platform/r5/MMO/bsp/
touch platform/r5/MMO/bsp/generated.c
-> make platform/*/MMO/bsp/
$
您可能想尝试以下方法:
PLATFORM_TUPLES := a53/AFS r5/MNO
GENERATE_PLATFORMS:=$(PLATFORM_TUPLES:%=platform/%/bsp/generated.c)
$(GENERATE_PLATFORMS):
mkdir -p $@
touch $@
platform: $(GENERATE_PLATFORMS)
# - platform tuple
define platform_rule
.build_bsp_$(notdir ): \
platform//bsp/generated.c \
$(wildcard platform//bsp/*.[chS])
@echo " -> $(MAKE) $$@"
@touch $$@
endef
$(foreach pt,$(PLATFORM_TUPLES),$(info $(call platform_rule,$(pt))))
$(foreach pt,$(PLATFORM_TUPLES),$(eval $(call platform_rule,$(pt))))
我有为我创建平台的工具。我有一个依赖于这些生成源的目标。这个目标必须是通用的(通用的意思是,它使用一种模式:.build_bsp_%
)——所以我不能使用 $(shell find...)
.
所以当提前创建平台时,一切正常:
$ make platform
mkdir -p platform/a53/AFS/bsp/
touch platform/a53/AFS/bsp/generated.c
mkdir -p platform/r5/MMO/bsp/
touch platform/r5/MMO/bsp/generated.c
$ make .build_bsp_AFS
-> make -C platform/a53/AFS/bsp
$
但是当源不存在时 - 因为平台不存在 - 它不起作用:
$ make .build_bsp_AFS
make: *** No rule to make target '.build_bsp_AFS'. Stop.
$
这是我的问题的精简版:
GENERATE_PLATFORM=platform/a53/AFS/bsp/generated.c platform/r5/MMO/bsp/generated.c
platform: $(GENERATE_PLATFORM)
$(GENERATE_PLATFORM):
mkdir -p $(dir $@)
touch $@
.build_bsp_%: platform/*/%/bsp/*.[chS] $(GENERATE_PLATFORM)
@echo " -> $(MAKE) -C $(dir $^)"
@touch $@
恐怕我必须走一条完全不同的路...
这不是一个很好的解决方案 - 但在提问时,我发现了一个可能的 "workaround":不要在先决条件中使用正则表达式并对(尚未)生成的源文件使用空规则:
GENERATE_PLATFORM=platform/a53/AFS/bsp/generated.c platform/r5/MMO/bsp/generated.c
%.c: ;
%.h: ;
%.S: ;
platform: $(GENERATE_PLATFORM)
$(GENERATE_PLATFORM):
mkdir -p $(dir $@)
touch $@
.build_bsp_%: platform/*/%/bsp/*.c platform/*/%/bsp/*.h platform/*/%/bsp/*.S $(GENERATE_PLATFORM)
@echo " -> $(MAKE) $(dir $<)"
@touch $@
遗憾的是,您不能将此 'last-resort for sources' 限制为例如只有 bsp 文件夹...但它正在工作:
$ make .build_bsp_MMO
mkdir -p platform/a53/AFS/bsp/
touch platform/a53/AFS/bsp/generated.c
mkdir -p platform/r5/MMO/bsp/
touch platform/r5/MMO/bsp/generated.c
-> make platform/*/MMO/bsp/
$
您可能想尝试以下方法:
PLATFORM_TUPLES := a53/AFS r5/MNO
GENERATE_PLATFORMS:=$(PLATFORM_TUPLES:%=platform/%/bsp/generated.c)
$(GENERATE_PLATFORMS):
mkdir -p $@
touch $@
platform: $(GENERATE_PLATFORMS)
# - platform tuple
define platform_rule
.build_bsp_$(notdir ): \
platform//bsp/generated.c \
$(wildcard platform//bsp/*.[chS])
@echo " -> $(MAKE) $$@"
@touch $$@
endef
$(foreach pt,$(PLATFORM_TUPLES),$(info $(call platform_rule,$(pt))))
$(foreach pt,$(PLATFORM_TUPLES),$(eval $(call platform_rule,$(pt))))