2009-12-19 72 views
14

我的应用程序主目录中有一个“lib”目录,其中包含任意数量的子目录,每个子目录都有自己的Makefile。使通配符子目录的目标

我想在主目录中有一个Makefile,它调用每个子目录的Makefile。我知道这是可能的,如果我手动列出subdirs,但我想自动完成它。

我在想像下面这样的东西,但它显然不起作用。请注意,我也有清洁,测试等目标,所以%可能不是一个好主意。

LIBS=lib/* 

all: $(LIBS) 

%: 
    (cd [email protected]; $(MAKE)) 

任何帮助表示赞赏!

回答

23

下面将与GNU make工作:

LIBS=$(wildcard lib/*) 
all: $(LIBS) 
.PHONY: force 
$(LIBS): force 
    cd [email protected] && pwd 

如果有可能比目录以外的东西在lib,你可以选择使用:

LIBS=$(shell find lib -type d) 

为了解决多个目标的问题,你可以为每个目录建立特殊目标,然后去掉子构建的前缀:

LIBS=$(wildcard lib/*) 
clean_LIBS=$(addprefix clean_,$(LIBS)) 
all: $(LIBS) 
clean: $(clean_LIBS) 
.PHONY: force 
$(LIBS): force 
    echo make -C [email protected] 
$(clean_LIBS): force 
    echo make -C $(patsubst clean_%,%,[email protected]) clean 
+0

哇,谢谢。奇迹般有效! – Zed 2009-12-19 15:04:47

+1

为什么你没有定义'$(clean_LIBS)'为虚假?例如。 '.PHONY:$(LIBS)$(clean_LIBS)',那么我认为你不需要'force'。 – 2010-06-22 15:51:01

+0

@dma_k:你说得很好。我没有测试过你的建议,但你的推理听起来对我来说很合适。实际上,这听起来很像GNU Make手册在这里所建议的内容(请参阅关于subdirs的内容):http://www.gnu.org/software/make/manual/make.html#Phony-Targets – mrkj 2010-06-24 15:04:34

2

也有上市的子目录用gmake命令的方式只有命令,而无需使用任何shell命令:

test: 
    @echo $(filter %/, $(wildcard lib/*/)) 

这将列出所有子目录尾随'/'。要删除它,你可以使用替代模式:

subdirs = $(filter %/, $(wildcard lib/*/)) 
test: 
    @echo $(subdirs:%/=%) 

然后到实际创建你可以使用一个小窍门每个子目录执行的makefile规则 - 假目标在一个不存在的目录。我认为,在这种情况下的例子告诉比任何解释更多:

FULL_DIRS =$(filter %/, $(wildcard lib/*/)) 
LIB_DIRS =$(FULL_DIRS:%/=%) 
DIRS_CMD =$(foreach subdir, $(LIB_DIRS), make-rule/$(subdir)) 

make-rule/%: 
    cd $* && $(MAKE) 

all: DIRS_CMD 

基本上,目标'all'列出了所有的子目录作为先决条件。例如,如果LIB_DIRS包含lib/folder1 lib/folder2,则扩张应该是这样的:

all: make-rule/lib/folder1 make-rule/lib/folder2 

然后“制作”,为了执行规则'all',尝试将每个前提与现有的目标相匹配。在这种情况下,目标是'make-rule/%:',它使用'$*''make-rule/'之后提取字符串,并将其用作配方中的参数。例如,第一个先决条件将被匹配,这样的扩展:

make-rule/lib/folder1: 
    cd lib/folder1 && $(MAKE) 
+0

我相信所有:DIRS_CMD'应该是'all:$ DIRS_CMD',因为当前的迭代没有正确地扩展。我正在按照'make:***没有规则制定目标'DIRS_CMD',这是'all'所需要的。停止.' – jnt30 2017-05-20 18:02:54

+0

这是可能的。我认为对我来说它没有工作,但我没有资源,也无法验证。 – Amiramix 2017-05-20 20:02:31

0

,如果你想打电话给比所有不同的目标,在一个未知的一些子目录是什么?

下的Makefile使用宏,以便创建一个转发虚拟目标的一些子目录在命令行应用给定的目标他们每个人:

# all direct directories of this dir. uses "-printf" to get rid of the "./" 
DIRS=$(shell find . -maxdepth 1 -mindepth 1 -type d -not -name ".*" -printf '%P\n') 
# "all" target is there by default, same logic as via the macro 
all: $(DIRS) 

$(DIRS): 
    $(MAKE) -C [email protected] 
.PHONY: $(DIRS) 

# if explcit targets where given: use them in the macro down below. each target will be delivered to each subdirectory contained in $(DIRS). 
EXTRA_TARGETS=$(MAKECMDGOALS) 

define RECURSIVE_MAKE_WITH_TARGET 
# create new variable, with the name of the target as prefix. it holds all 
# subdirectories with the target as suffix 
$(1)_DIRS=$$(addprefix $(1)_,$$(DIRS)) 

# create new target with the variable holding all the subdirectories+suffix as 
# prerequisite 
$(1): $$($1_DIRS) 

# use list to create target to fullfill prerequisite. the rule is to call 
# recursive make into the subdir with the target 
$$($(1)_DIRS): 
     $$(MAKE) -C $$(patsubst $(1)_%,%,[email protected]) $(1) 

# and make all targets .PHONY 
.PHONY: $$($(1)_DIRS) 
endef 

# evaluate the macro for all given list of targets 
$(foreach t,$(EXTRA_TARGETS),$(eval $(call RECURSIVE_MAKE_WITH_TARGET,$(t)))) 

希望这有助于。真正有用的时候处理paralelism:make -j12清理所有的makefiles有这些目标的树...一如既往:玩make是危险的,不同的元层次的编程太靠近在一起, - )