Oli*_*han 2 ubuntu makefile gnu-make
这是我的makefile的一部分:
PATH := $(shell pwd)
EDIR := impl
EFFECTS := $(filter-out $(EDIR), $(shell find $(EDIR) -maxdepth 1 -type d))
ALLMAKES := $(patsubst %, $(PATH)/%, $(EFFECTS))
all:
$(foreach c,$(ALLMAKES),$(MAKE) -C $(c))
Run Code Online (Sandbox Code Playgroud)
基本上,我想为"impl"目录中的所有目录调用make而不使用"impl"本身.我知道make会记住上次使用-C参数调用时的最后一个目录,这就是我每次都给出绝对路径的原因.是什么让回声看起来像我想要的:
make -C <projectdir>/impl/thing1 make -C <projectdir>/impl/thing2 make -C <projectdir>/impl/thing3
Run Code Online (Sandbox Code Playgroud)
问题是make不能完成命令并只是打印:
make: make: Command not found.
Run Code Online (Sandbox Code Playgroud)
我可以在makefile之外单独调用每个目录的"make -C <path>",但它在foreach调用中不起作用.我试过这个,但它也不起作用:
$(foreach c,$(ALLMAKES),$(shell make -C $(c)))
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
那是因为你正在调用一个make包含后续make命令的大量参数.您需要在make的调用之间添加一个shell命令分隔符.这样的东西会起作用:
all:
$(foreach c,$(ALLMAKES),$(MAKE) -C $(c) && ) true
Run Code Online (Sandbox Code Playgroud)
第二,你的makefile还有其他问题.您不应该设置一个名为make的变量PATH,因为这将覆盖subshell的$PATH变量.您可以使用make内置变量$(CURDIR)而不是运行$(shell pwd).实际上你根本不需要在目录前面添加路径,因为运行$(MAKE) -C ...不会改变shell的工作目录,只是make,而当make退出时它会被设置回来,所以你可以使用相对路径.
在循环中调用子make也有一些问题.首先,您可以减少可以获得的并行化数量.其次,-k无法正确支持该选项(没有很多不愉快的努力).处理此问题的更好方法是利用make已经知道如何构建大量目标的事实:
all: $(EFFECTS)
$(EFFECTS):
$(MAKE) -C $@
.PHONY: all $(EFFECTS)
Run Code Online (Sandbox Code Playgroud)
如果不同子目录之间存在特定的排序问题,您也可以定义它们:
impl/thing2: impl/thing1
Run Code Online (Sandbox Code Playgroud)
这确保了最大的并行化机会,同时仍然保留了重要的排序.
要添加替代规则,比方说clean,您可以执行以下操作:
CLEAN_EFFECTS := $(addsuffix .clean,$(EFFECTS))
clean: $(CLEAN_EFFECTS)
$(CLEAN_EFFECTS):
$(MAKE) -C $(basename $@) clean
.PHONY: clean $(CLEAN_EFFECTS)
Run Code Online (Sandbox Code Playgroud)
这很好,因为您还可以通过运行make impl/thing1来构建单个子目录(及其所有先决条件).或者通过跑步清洁它们make impl/thing1.clean
如果您有更多这些,您也可以使用模式规则等,以避免对每种类型的目标重复此操作.它变得更加繁琐.
| 归档时间: |
|
| 查看次数: |
8374 次 |
| 最近记录: |