2009-12-19 27 views
14

मेरे पास मेरे अनुप्रयोगों में मुख्य निर्देशिका में "lib" निर्देशिका है, जिसमें उपनिर्देशिका की मनमानी संख्या है, प्रत्येक में अपना स्वयं का मेकफ़ाइल है।वाइल्डकार्ड उपनिर्देशिका लक्ष्य

मैं मुख्य निर्देशिका में एक मेकफ़ाइल रखना चाहता हूं, जो प्रत्येक उपनिर्देशिका के मेकफ़ाइल को कॉल करता है। मुझे पता है कि अगर मैं मैन्युअल रूप से subdirs सूचीबद्ध करता हूं, तो यह संभव है, लेकिन मैं इसे स्वचालित रूप से करना चाहता हूं।

मैं निम्नलिखित की तरह कुछ सोच रहा था, लेकिन यह स्पष्ट रूप से काम नहीं करता है। ध्यान दें कि मेरे पास स्वच्छ, परीक्षण, आदि लक्ष्य भी हैं, इसलिए% शायद एक अच्छा विचार नहीं है।

LIBS=lib/* 

all: $(LIBS) 

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

किसी भी मदद की सराहना की जाती है!

उत्तर

23

निम्नलिखित जीएनयू make के साथ काम करेंगे:,

LIBS=$(shell find lib -type d) 

कई लक्ष्यों मुद्दे के समाधान के लिए आप:

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

अगर वहाँ lib में निर्देशिका के अलावा कुछ हो सकता है, आप वैकल्पिक रूप से इस्तेमाल कर सकते हैं प्रत्येक निर्देशिका के लिए विशेष लक्ष्य बना सकते हैं, फिर उप-निर्माण के लिए उपसर्ग को बंद कर सकते हैं:

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

+1

आपने '$ (clean_LIBS)' को नकली के रूप में क्यों परिभाषित नहीं किया है? जैसे '.PHONY: $ (LIBS) $ (clean_LIBS)', तो मुझे लगता है कि आपको 'बल' की आवश्यकता नहीं है। –

+0

@dma_k: आप एक उत्कृष्ट बिंदु बनाते हैं। मैंने आपके सुझाव का परीक्षण नहीं किया है, लेकिन आपका तर्क मेरे लिए सही लगता है। वास्तव में, यह बहुत कुछ लगता है कि जीएनयू मैनुअल क्या सुझाव दे रहा है (subdirs पर बिट देखें): http://www.gnu.org/software/make/manual/make.html#Phony- लक्ष्य – mrkj

2

वहाँ भी है gmake साथ लिस्टिंग उप-निर्देशिका का एक तरीका ही आज्ञा देता है, किसी भी खोल आदेशों का उपयोग किए बिना:

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

यह '/' पूर्ण विराम वाले सभी उप-निर्देशिका सूची जाएगा। इसे निकालने के लिए आप विकल्प के पैटर्न का उपयोग कर सकते हैं:

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

तो वास्तव में एक उप-निर्देशिका यदि आप एक छोटे चाल का उपयोग कर सकते में makefiles क्रियान्वित नियम बनाने के लिए - एक न के बराबर निर्देशिका में जाली लक्ष्य। मैं इस मामले में लगता है कि एक उदाहरण किसी भी स्पष्टीकरण की तुलना में अधिक बता देंगे:

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' को' सभी: $ DIRS_CMD' होना चाहिए क्योंकि वर्तमान पुनरावृत्ति ठीक से विस्तार नहीं करती है। मुझे 'बनाने' के आधार पर कुछ मिल रहा था: *** 'सभी' द्वारा आवश्यक 'DIRS_CMD' लक्ष्य बनाने का कोई नियम नहीं है। रोकें। – jnt30

+0

यह संभव है। मुझे लगता है कि यह मेरे लिए $ बिना काम करता है लेकिन मेरे पास स्रोत नहीं हैं और सत्यापित नहीं कर सकते हैं। – Amiramix

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 से निपटने के दौरान वास्तव में सहायक: मेकफाइल इन सभी लक्ष्यों के साथ एक पेड़ में साफ करें ... हमेशा के रूप में: बनाने के साथ खेल खतरनाक है, प्रोग्रामिंग के विभिन्न मेटा-स्तर एक साथ बहुत करीब हैं, -