给出以下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) ; )
但我想知道如何让第一个表格按预期工作,以防我将来需要更复杂的东西。
答案 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_foo
和install_bar
。这两个目标被添加到install
依赖项中,并在之后声明。此外,在每个临时目标中,我们添加有关要安装的文件的依赖项(foo
或bar
)。这样您就可以根据需要添加规则,加上“并行兼容”。
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))))
似乎可以做到这一点。