makefile:先决条件 $(变量)中的 % 模式
makefile: % pattern in prerequisite $(variable)
我有这样的东西可以用:
target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
$(myDir)target1.sfx : $(target1.PREREQUISITES)
<same recipe here>
$(myDir)target2.sfx : $(target2.PREREQUISITES)
<same recipe here>
这就是我想做的,但它不起作用:
target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
$(myDir)%.sfx : $(%.PREREQUISITES)
<commun recipe here>
它总是说没有什么可做的,因为目标是最新的。
我感觉问题可能出在每个 make 阶段做了什么,我的意思是,% 或 $ 首先做了什么。它应该工作正常吗?
你需要像 secondary expansion 这样的东西才能工作,否则先决条件中的变量扩展发生 在 模式被替换之前,你还没有未定义名为 %.PREREQUISITES
.
的变量
.SECONDEXPANSION:
$(mydir)%.sfx: $$($$*.PREREQUISITES)
echo $^
user657267提出的第二个扩展效果很好。 GNU make 还支持一种循环机制,您可以使用该机制以非常相似的形式实例化多个规则:
target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
TARGETS = target1 target2
# $(1) is a parameter to substitute. The $$ will expand as $.
define MY_rule
$$(myDir)$(1).sfx : $$($(1).PREREQUISITES)
<same recipe here>
endef
$(foreach target,$(TARGETS),$(eval $(call MY_rule,$(target))))
foreach
遍历 $(TARGETS)
中的所有单词并将当前单词分配给 $(target)
.
call
执行 MY_rule
的扩展,它将 $(1)
替换为 $(target)
的当前值,将 $$
替换为 $
。
eval
将 call
扩展的结果实例化为常规规则。
例如,foreach
的第一次迭代的结果将是:
$(eval $(call MY_rule,target1))
call
的计算结果为:
$(myDir)target1.sfx : $(target1.PREREQUISITES)
<same recipe here>
和 eval
将实例化为规则。 重要:不要忘记 call
执行第一次扩展。因此,如果您的 <same recipe here>
包含 $
符号,请不要忘记将它们加倍,除非它们扩展 call
没问题。如果您的食谱使用了 shell 变量,您甚至可能会得到 $$$$var
.
之类的结果
此机制比第二个扩展包更强大和通用。它甚至可以使用多个参数来替换和嵌套循环:
target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
TARGETS = target1 target2
DIRS = myDir
# $(1): target
# $(2): directory
define MY_rule
$(2)$(1).sfx : $$($(1).PREREQUISITES)
<same recipe here>
endef
$(foreach target,$(TARGETS),$(foreach dir,$(DIRS),$(eval $(call MY_rule,$(target),$(dir)))))
你甚至可以在 define-endef
中嵌入 foreach-eval-call
:
target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
TARGETS = target1 target2
DIRS = myDir
# $(1): target
# $(2): directory
define MY_rule_1
$(2)$(1).sfx : $$($(1).PREREQUISITES)
<same recipe here>
endef
# $(1): directory
define MY_rule_2
$$(foreach target,$$(TARGETS),$$(eval $$(call MY_rule_1,$$(target),$(1))))
endef
$(foreach dir,$(DIRS),$(eval $(call MY_rule_2,$(dir))))
感谢 user657267 的回答,它确实有效并且给了我很好的引导。对于不太熟悉的人,请注意双美元符号。但是,我在这里包含我的答案,因为它仍然使用 %
符号,这是我原来问题的一部分,并且和你的一样有效。我正在使用以下解决方案。
.SECONDEXPANSION:
$(mydir)%.sfx: $$(%.PREREQUISITES)
echo $^
我刚刚注意到并意识到这一点,当使用辅助扩展时,make 不会告诉您 缺少先决条件 没有规则,而是显示误导性消息说没有规则可以使 target.
我有这样的东西可以用:
target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
$(myDir)target1.sfx : $(target1.PREREQUISITES)
<same recipe here>
$(myDir)target2.sfx : $(target2.PREREQUISITES)
<same recipe here>
这就是我想做的,但它不起作用:
target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
$(myDir)%.sfx : $(%.PREREQUISITES)
<commun recipe here>
它总是说没有什么可做的,因为目标是最新的。
我感觉问题可能出在每个 make 阶段做了什么,我的意思是,% 或 $ 首先做了什么。它应该工作正常吗?
你需要像 secondary expansion 这样的东西才能工作,否则先决条件中的变量扩展发生 在 模式被替换之前,你还没有未定义名为 %.PREREQUISITES
.
.SECONDEXPANSION:
$(mydir)%.sfx: $$($$*.PREREQUISITES)
echo $^
user657267提出的第二个扩展效果很好。 GNU make 还支持一种循环机制,您可以使用该机制以非常相似的形式实例化多个规则:
target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
TARGETS = target1 target2
# $(1) is a parameter to substitute. The $$ will expand as $.
define MY_rule
$$(myDir)$(1).sfx : $$($(1).PREREQUISITES)
<same recipe here>
endef
$(foreach target,$(TARGETS),$(eval $(call MY_rule,$(target))))
foreach
遍历$(TARGETS)
中的所有单词并将当前单词分配给$(target)
.call
执行MY_rule
的扩展,它将$(1)
替换为$(target)
的当前值,将$$
替换为$
。eval
将call
扩展的结果实例化为常规规则。
例如,foreach
的第一次迭代的结果将是:
$(eval $(call MY_rule,target1))
call
的计算结果为:
$(myDir)target1.sfx : $(target1.PREREQUISITES)
<same recipe here>
和 eval
将实例化为规则。 重要:不要忘记 call
执行第一次扩展。因此,如果您的 <same recipe here>
包含 $
符号,请不要忘记将它们加倍,除非它们扩展 call
没问题。如果您的食谱使用了 shell 变量,您甚至可能会得到 $$$$var
.
此机制比第二个扩展包更强大和通用。它甚至可以使用多个参数来替换和嵌套循环:
target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
TARGETS = target1 target2
DIRS = myDir
# $(1): target
# $(2): directory
define MY_rule
$(2)$(1).sfx : $$($(1).PREREQUISITES)
<same recipe here>
endef
$(foreach target,$(TARGETS),$(foreach dir,$(DIRS),$(eval $(call MY_rule,$(target),$(dir)))))
你甚至可以在 define-endef
中嵌入 foreach-eval-call
:
target1.PREREQUISITES = file11 file12 file13
target2.PREREQUISITES = file21 file22 file23
TARGETS = target1 target2
DIRS = myDir
# $(1): target
# $(2): directory
define MY_rule_1
$(2)$(1).sfx : $$($(1).PREREQUISITES)
<same recipe here>
endef
# $(1): directory
define MY_rule_2
$$(foreach target,$$(TARGETS),$$(eval $$(call MY_rule_1,$$(target),$(1))))
endef
$(foreach dir,$(DIRS),$(eval $(call MY_rule_2,$(dir))))
感谢 user657267 的回答,它确实有效并且给了我很好的引导。对于不太熟悉的人,请注意双美元符号。但是,我在这里包含我的答案,因为它仍然使用 %
符号,这是我原来问题的一部分,并且和你的一样有效。我正在使用以下解决方案。
.SECONDEXPANSION:
$(mydir)%.sfx: $$(%.PREREQUISITES)
echo $^
我刚刚注意到并意识到这一点,当使用辅助扩展时,make 不会告诉您 缺少先决条件 没有规则,而是显示误导性消息说没有规则可以使 target.