Makefile隐式规则,包含依赖项中的函数调用

时间:2015-08-17 18:07:08

标签: makefile

我使用Make来组织我的数据分析,并且我有多个输入数据集,每个输入数据集都可以根据参考数据集进行分析。当然,每个数据集都需要自己特殊的预处理位。我想要的是有一个隐式规则可以解析相对简单的目录结构,并使用它来了解要做的先决条件,例如,如果我想运行:

make ref1/sample1_processed ref1/sample2_processed ref2/sample1_processed #...etc

我可以有一个隐含的规则,看起来像:

%_processed: $(dir %)/preprocessed samples/$(notdir %)_preprocessed
     process_data --reference $(dir $*)/preprocessed --sample samples/$(notdir $*)_preprocessed
理想情况下,

可以解释为:

ref1/sample1_processed -> (ref1/preprocessed, samples/sample1_preprocessed)
ref1/sample2_processed -> (ref1/preprocessed, samples/sample2_preprocessed)
ref2/sample1_processed -> (ref2/preprocessed, samples/sample1_preprocessed)

(其中 - >意味着取决于)。

然而,似乎正在发生的事情是,函数调用在依赖行中失败(它们似乎在配方本身中做得很好)。

这里是一个极少的非工作样本,我认为它传达了我想要发生的事情:

%_processed: $(dir %)/preprocessed samples/$(notdir %)_preprocessed
    echo $(dir $*)
    echo $(notdir $*)
    echo "Done"

samples/%_preprocessed: samples/%
    touch $@

%/preprocessed: | %
    touch $@


ref%:
    mkdir $@

并从命令行:

$ mkdir samples/
$ touch samples/sample1 samples/sample2
$ make ref1/sample1_processed
make: *** No rule to make target `ref1/sample1_processed'.  Stop.

但是如果你注释掉%_processed的依赖关系,它确实运行正常(尽管没有检查所说的依赖关系):

$ make ref1/sample1_processed
echo ref1/
ref1/
echo sample1
sample1
echo "Done"
Done

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:2)

你遇到了Make的一个重要弱点:它对通配符的原始处理。在一个规则中使用两个通配符将是合乎逻辑的解决方案,但这是不可能的......好吧,很难。

解决这个问题的方法不止一种,但我会使用Secondary Expansion并从目标名称中提取所需的变量:

.SECONDEXPANSION:

sample%_processed: samples/$$(subst processed,preprocessed,$$(notdir $$@)) $$(dir $$@)preprocessed
    process_data --reference $(dir $@)preprocessed --sample $<

(请注意,构建命令的方法不止一种;使用$<获取第一个先决条件要比获得第二个先行条件容易得多,所以我将丑陋的第一个做成了第一个。)

相关问题