在makefile食谱中的foreach模板

时间:2014-06-16 08:03:09

标签: linux foreach makefile gnu-make

给出以下Makefile片段:

TOOLS=foo bar

define TOOL_install
install -c $(1) $$(prefix)/bin/$(1)
endef

.PHONY: install
install: all
        $(foreach tool,$(TOOLS),$(eval $(call TOOL_install,$(tool))))

为什么make install打印"没有什么可以为'install'。"而不是执行foreach指定的命令? (在foreach之前有一个标签,我尝试在TOOL_install定义中添加一个标签;它没有帮助。)

根据make -p,安装目标没有命令,这显然不是预期的。

在同一个makefile的其他地方,我成功地使用相同的技术来创建包括命令配方在内的整个规则;如何在现有规则中完成此工作?

(如果我用eval替换info,那么它会打印出我期望它运行的命令。)

在这个简单的例子中,我可以通过内联命令来实现它:

install: all
        @$(foreach tool,$(TOOLS),install -c $(tool) $(prefix)/bin/$(tool) ; )

但我想知道如何让第一个表格按预期工作,以防我将来需要更复杂的东西。

2 个答案:

答案 0 :(得分:2)

您不应在此处使用eval,因为您不想创建dynamic constructs常量规则。因此,只需删除eval并在;定义的末尾添加TOOL_install

TOOLS := foo bar

define TOOL_install
echo $(1);
endef

.PHONY: install
install:
    $(foreach tool,$(TOOLS),$(call TOOL_install,$(tool)))

扩展后,您的Makefile将如下所示:

.PHONY: install
install:
    echo foo; echo bar;

另一个答案:

我们正在使用一些临时目标install_fooinstall_bar。这两个目标被添加到install依赖项中,并在之后声明。此外,在每个临时目标中,我们添加有关要安装的文件的依赖项(foobar)。这样您就可以根据需要添加规则,加上“并行兼容”。

prefix := foobar
TOOLS := foo bar

install: $(addprefix install_,$(TOOLS))

$(addprefix install_,$(TOOLS)): install_%: %
    install -c $< $(prefix)/bin/$<

.PHONY: install $(addprefix install_,$(TOOLS))

修改

对于卸载目标(没有依赖项),您可以使用patsubst函数,如下所示:

prefix := foobar
TOOLS := foo bar

uninstall: $(addprefix uninstall_,$(TOOLS))

$(addprefix uninstall_,$(TOOLS)):
    install -c $(patsubst uninstall_%,%,$@) $(prefix)/bin/$(patsubst uninstall_%,%,$@)

.PHONY: uninstall $(addprefix uninstall_,$(TOOLS))

答案 1 :(得分:1)

我最终采用了原始问题和jml's answer的混合方式(感谢灵感!)。

TOOLS:=foo bar

.PHONY: all
all : $(TOOLS)

.PHONY: install $(addprefix install_,$(TOOLS))
install : $(addprefix install_,$(TOOLS))

.PHONY: uninstall $(addprefix uninstall_,$(TOOLS))
uninstall : $(addprefix uninstall_,$(TOOLS))

define TOOL_template
$(1): $$($(1)_OBJS)
        #commands to build it

install_$(1): $(1)
        install -c $(1) $$(prefix)/bin/$(1)

uninstall_$(1):
        rm $$(prefix)/bin/$(1)
endef

$(foreach tool,$(TOOLS),$(eval $(call TOOL_template,$(tool))))

似乎可以做到这一点。