带有foreach循环的Makefile - ***缺少分隔符

时间:2015-07-30 19:58:30

标签: foreach makefile eval separator

我是makefiles的新手。

我有大量相当类似的目录,每个目录都包含一个makefile和一些源代码,所有这些都是我想从上面的目录中使用一个总体makefile来解决的。目录中的makefile工作。子目录的数量将来会增长,所以我设计的任何东西都应该能够无限增长。

如果我直接调用子目录makefile,我没有问题,

mytarget:
    cd a && $(MAKE) mytarget
    cd b && $(MAKE) mytarget
    cd c && $(MAKE) mytarget

但是当我尝试以下附件时,我确实收到**** missing separator错误。我使用了标签,没有空格,所以我不理解我的错误。

LIST = a b c d e

mytarget:
    $(foreach var,$(LIST),$(eval cd $(var) && $(MAKE) mytarget))

2 个答案:

答案 0 :(得分:0)

你不希望$(eval)在那里。这是错误的。传递给它的内容不是makefile内容,而是shell内容。

你想:

LIST = a b c d e

mytarget:
        $(foreach var,$(LIST),cd $(var) && $(MAKE) mytarget; cd ..;)

因为您希望$(foreach)调用的结果是食谱主体。

答案 1 :(得分:0)

可能更容易理解(或者可能不是......)的另一个选项是使用shell循环,而不是makefile循环。此外,如果您获得足够的子目录并且您希望在命令行长度限制更有限的系统上工作,这会导致更短的脚本,这可能很重要:

LIST = a b c d e

mytarget:
        for var in $(LIST); do $(MAKE) -C $$var $@; done

或者,如果您更愿意使用cd而不是GNU make -C选项,请执行以下操作:

LIST = a b c d e

mytarget:
        for var in $(LIST); do (cd $$var && $(MAKE) $@); done

请注意,我们在这里使用括号在子shell中启动make,因此我们不必使用cd ..之类的内容(如果LIST中的某些元素是路径,则无法使用而不是一个简单的目录,例如f/g/h或类似的目录。)

这些解决方案的最大问题是错误处理都被打破了。如果a目标的子制作失败怎么办?这些makefile不会注意到这一点。此外,并行性并不理想:在所有情况下,这里一次只会调用一个子make。

在makefile中编写循环的最佳方法是使用多个先决条件,而不是在配方中循环。像这样:

LIST = a b c d e

mytarget: $(addprefix mytarget-,$(LIST))

mytarget-%:
        $(MAKE) -C $* mytarget

(或,cd $* && $(MAKE) mytarget