2012-12-27 16 views
6

Makefile एस में पुन: प्रयोज्य कोड लिखने का सबसे अच्छा अभ्यास क्या है? मैं कार्यों (task03) के नए परिवार जोड़ना चाहते हैंपुन: प्रयोज्य कोड लिखने का सर्वोत्तम अभ्यास

.PHONY: all task01-all task01-clean task01-run task02-all task02-clean task02-run 

all: task01-all task02-all 

############################################################################### 
task01-all: task01-clean task01 task01-run 

task01-clean: 
    rm task01 task01.{exi,o} -f 

task01: 
    compiler task01.ext -O2 --make 

task01-run: 
    ./task01 

############################################################################### 
task02-all: task02-clean task02 task02-run 

task02-clean: 
    rm task02 task02.{exi,o} -f 

task02: 
    compiler task02.ext -O2 --make 

task02-run: 
    ./task02 

अब, और मैं पूरी अनुभाग copypaste, इसके लिए s/02/03/ और उन्हें .PHONY अनुभाग के लिए जोड़ने की जरूरत है - यह है:

मान लीजिए मैं एक Makefile है शोर, घृणित और बस सही नहीं है।

मैं इससे कैसे बच सकता हूं? क्या मैं एक ही पंक्ति में नए कार्य समूह को जोड़ने के लिए किसी भी तरह से टेम्पलेट्स के साथ सभी कार्यों को फिर से परिभाषित कर सकता हूं?

उत्तर

9

सवाल के बाद से Makefiles में फिर से प्रयोग करने योग्य कोड लिखने के बारे में है, मैं कैसे जीएनयू में पैटर्न नियमों का उपयोग करने बनाओ का एक उदाहरण दे देंगे (यह लग रहा है जैसा कि आप .PHONY लक्ष्य का उल्लेख करते हैं, वैसे ही आप इसका उपयोग कर रहे हैं)। हालांकि, अगर आप मेक की निर्भरता की जाँच के किसी भी उपयोग नहीं कर रहे हैं, यह आसान एक खोल स्क्रिप्ट के साथ ऐसा करना हो सकता है - जैसे कुछ:

#!/bin/sh 
TASKS="task01 task02 task03" 

for i in $TASKS; do 
    rm $i $i.ext $i.o -f; 
    compiler $i.ext -O2 --make; 
    ./$i; 
done 

लेकिन, सिद्धांत का विस्तार करने के बनाने के लिए, हम कोई अन्य समस्या है से निपटने के लिए। फार्म की पंक्तियाँ:

task01-all: task01-clean task01 task01-run 

क्या ज़रूरी का निर्माण करने के क्रम में बनाने नहीं बताया - वे सभी पहले task01-all बनाया जाता है किया जा करने की जरूरत है सिर्फ इतना है कि। इसके बजाए, चलाने के लिए प्रत्येक चरण को इससे पहले चरण पर निर्भर होना चाहिए। कुछ इस तरह:

TASKS=task01-run task02-run task03-run 

.PHONY: all $(TASKS) $(TASKS:run=clean) 

all: $(TASKS) 

$(TASKS:run=clean): %-clean: 
    rm $* $*.ext $*.o -f 

%: %.ext | %-clean 
    compiler $< -O2 --make 

$(TASKS): %-run: % 
    ./$< 

% साथ नियम "पैटर्न नियम" कहा जाता है, और वे विभिन्न लक्ष्यों के लिए फिर से लिख यही नियम कई बार से बचने के लिए एक महान उपकरण कर रहे हैं। एक चेतावनी यह है कि मेक आमतौर पर .PHONY लक्ष्य के लिए पैटर्न नियमों की जांच नहीं करता है; हम बताते हैं कि उन नियमों को लक्ष्य की सूची और दूसरे कॉलन (उदाहरण के लिए, $(TASKS):) के साथ उपसर्ग करके इसे स्पष्ट रूप से करें।

task01-run के बाद task01 काम करने के लिए %-run लक्ष्य % पर निर्भर करते हैं। साथ ही, आपके मेकफ़ाइल से पता चलता है कि आप हर बार साफ करना चाहते हैं, इसलिए हम %%-clean पर निर्भर करते हैं। चूंकि %-clean वास्तव में कोई आउटपुट उत्पन्न नहीं करता है, इसलिए हम इसे "ऑर्डर केवल" निर्भरता बनाते हैं - मेक टाइम-स्टैंप या कुछ भी नहीं ढूंढेंगे, यह %-clean नियम को पहले ही चलाएगा जब भी इसे % चलाने की आवश्यकता होगी राज करते हैं। "आदेश केवल" निर्भरता के बाद रखा जाता है एक |:

%: %.ext | %-clean 

यह उल्लेख के मेक की सबसे बड़ी ताकत में से एक है कि यह काम है कि बार-बार किए जाने की जरूरत नहीं है दोहरा नहीं करके समय की बचत कर सकते हैं कि लायक है - यानी, यह यदि निर्भरता लक्ष्य से नई हैं तो केवल नियम चलाता है।इसलिए, जब आप बंद छोड़ सकता %-clean पर निर्भरता है, जो केवल चलाने के लिए compiler $< -O2 --make%.ext अगर है % से नए बनाने का कारण होगा:

%: %.ext 
    compiler $< -O2 --make 

फिर आप एक नियम जोड़ सकता है सिर्फ %-clean लक्ष्यों को चलाने के लिए:

.PHONY: all $(TASKS) $(TASKS:run=clean) clean 

clean: $(TASKS:run=clean) 

अंतिम बात: मैं व्यंजनों में कुछ विशेष चर का उपयोग करता हूं। [email protected] लक्ष्य बनने के लिए खड़ा है। $< पहली निर्भरता के लिए खड़ा है। $* पैटर्न पैटर्न के "स्टेम" के लिए खड़ा है (यानी, % द्वारा मिलान किया गया हिस्सा)।

+0

अच्छी व्याख्याएं। धन्यवाद! –

+0

"|" के लिए एक उदाहरण प्रदान करना अच्छा था, धन्यवाद। –

2

है कि मैं क्या देख रहा हूँ की तरह लग रहा:

ALLS=task01-all task02-all 
BUILDS=${ALLS:-all=-build} 
CLEANS=${ALLS:-all=-clean} 
RUNS=${ALLS:-all=-run} 

.PHONY: all $(ALLS) $(CLEANS) $(BUILDS) $(RUNS) 

all: $(ALLS) 

############################################################################### 
$(ALLS): $(CLEANS) $(BUILDS) $(RUNS) 

$(CLEANS): 
     rm ${@:-clean=} ${@:-clean=}.{ext,o} -f 

$(BUILDS): 
     compiler ${@:-build=}.ext -O2 --make 

$(RUNS): 
     ./${@:-run=}