如何在目标先决条件中使用用户定义的宏
how to use user defined macro in target prerequisites
我有一个这样的 Makefile
year = $(shell echo $(1) | cut -c 1-4)
month = $(shell echo $(1) | cut -c 5-6)
day = $(shell echo $(1) | cut -c 7-8)
.SECONDARY.
%/foo.md : /data/%/FOO_PATTERN.*
./foo_input_reader $^ | ./foo_processor > $@ 2> $(dir $@)/foo.log
当我打电话
make 20220310/foo.md,目标先决条件扩展为
/data/20220310/FOO_PATTERN.*
我的规则使用以下命令创建 20220310/foo.md 文件
./foo_input_reader /data/20220310/FOO_PATTERN.* | ./foo_processor > 20220310/foo.md 2> 20220310/foo.log
我现在想要实现的是更改规则的先决条件部分,使其扩展到此
/data/YYYY/MM/DD/FOO_PATTERN.*
而不是
/data/YYYYMMDD/FOO_PATTERN.*
我希望通过调用我在规则的先决条件部分定义的年、月和日宏来实现这一点(请参阅我的 Makefile 的开头),所以有类似
%/foo.md : /data/$(call year,$@)/$(call month,$@)/$(call day,$@)/FOO_PATTERN.*
./foo_input_reader $^ | ./foo_processor > $@ 2> $(dir $@)/foo.log
但这行不通,我认为是因为先决条件列表中的变量和函数引用在读取阶段会立即展开 (http://www.gnu.org/software/make/manual/make.html#Reading-Makefiles)。
不过我确定这应该是可能的?
如果可行,请您指点一下,如果可行,正确的做法是什么?
谢谢
(我认为您误解了“*”在 makefile 中的工作方式,但现在这无关紧要。)
首先,我建议您使用一个 sed
命令,而不是三个 cut
命令。这不是必需的,但我认为它使事情更整洁。
DATA_PATH = $(shell echo $(1) | sed "s|\(....\)\(..\)\(..\)|data////FOO_PATTERN.*|")
其次,不是.SECONDARY.
,是.SECONDEXPANSION:
。
第三,二级扩张并不意味着没有一级扩张。在 first 扩展中,先决条件列表中的自动变量(如 $@
)没有值并且扩展为空,因此在第二次扩展中所做的任何事情都为时已晚。我们可以通过使用 $
:
转义变量来防止这种情况
%/foo.md: $$(call DATA_PATH,$$*)
@echo building $@ from $^
./foo_input_reader $^ ...
我有一个这样的 Makefile
year = $(shell echo $(1) | cut -c 1-4)
month = $(shell echo $(1) | cut -c 5-6)
day = $(shell echo $(1) | cut -c 7-8)
.SECONDARY.
%/foo.md : /data/%/FOO_PATTERN.*
./foo_input_reader $^ | ./foo_processor > $@ 2> $(dir $@)/foo.log
当我打电话 make 20220310/foo.md,目标先决条件扩展为
/data/20220310/FOO_PATTERN.*
我的规则使用以下命令创建 20220310/foo.md 文件
./foo_input_reader /data/20220310/FOO_PATTERN.* | ./foo_processor > 20220310/foo.md 2> 20220310/foo.log
我现在想要实现的是更改规则的先决条件部分,使其扩展到此
/data/YYYY/MM/DD/FOO_PATTERN.*
而不是
/data/YYYYMMDD/FOO_PATTERN.*
我希望通过调用我在规则的先决条件部分定义的年、月和日宏来实现这一点(请参阅我的 Makefile 的开头),所以有类似
%/foo.md : /data/$(call year,$@)/$(call month,$@)/$(call day,$@)/FOO_PATTERN.*
./foo_input_reader $^ | ./foo_processor > $@ 2> $(dir $@)/foo.log
但这行不通,我认为是因为先决条件列表中的变量和函数引用在读取阶段会立即展开 (http://www.gnu.org/software/make/manual/make.html#Reading-Makefiles)。
不过我确定这应该是可能的? 如果可行,请您指点一下,如果可行,正确的做法是什么?
谢谢
(我认为您误解了“*”在 makefile 中的工作方式,但现在这无关紧要。)
首先,我建议您使用一个 sed
命令,而不是三个 cut
命令。这不是必需的,但我认为它使事情更整洁。
DATA_PATH = $(shell echo $(1) | sed "s|\(....\)\(..\)\(..\)|data////FOO_PATTERN.*|")
其次,不是.SECONDARY.
,是.SECONDEXPANSION:
。
第三,二级扩张并不意味着没有一级扩张。在 first 扩展中,先决条件列表中的自动变量(如 $@
)没有值并且扩展为空,因此在第二次扩展中所做的任何事情都为时已晚。我们可以通过使用 $
:
%/foo.md: $$(call DATA_PATH,$$*)
@echo building $@ from $^
./foo_input_reader $^ ...