2009-12-19 109 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是危險的,不同的元層次的編程太靠近在一起, - )