जवाबों:
डिफ़ॉल्ट रूप से, मेकफाइल लक्ष्य "फ़ाइल लक्ष्य" हैं - उनका उपयोग अन्य फ़ाइलों से फ़ाइलें बनाने के लिए किया जाता है। बनाओ मान लें कि इसका लक्ष्य एक फ़ाइल है, और इससे मेकफाइल्स लिखना अपेक्षाकृत आसान हो गया है:
foo: bar
create_one_from_the_other foo bar
हालांकि, कभी-कभी आप चाहते हैं कि आपका मेकफाइल कमांड चलाए जो फ़ाइल सिस्टम में भौतिक फ़ाइलों का प्रतिनिधित्व नहीं करता है। इसके लिए अच्छे उदाहरण सामान्य लक्ष्य "साफ" और "सभी" हैं। संभावना है कि यह मामला नहीं है, लेकिन आपके पास संभवतः आपके मुख्य निर्देशिका में एक फ़ाइल का नाम हो सकता हैclean । ऐसे मामले में मेक भ्रमित हो जाएगा क्योंकि डिफ़ॉल्ट रूप से cleanलक्ष्य इस फ़ाइल के साथ जुड़ा होगा और मेक इसे केवल तभी चलाएगा जब फ़ाइल निर्भरता के संबंध में अप-टू-डेट प्रतीत नहीं होगी।
इन विशेष लक्ष्य कहा जाता है जाली और आप स्पष्ट रूप से वे फ़ाइलें, जैसे के साथ जुड़े नहीं कर रहे हैं बता सकते हैं:
.PHONY: clean
clean:
rm -rf *.o
अब make cleanउम्मीद के मुताबिक चलेगा, भले ही आपके पास कोई फाइल हो clean।
मेक के संदर्भ में, एक टारगेट टारगेट बस एक लक्ष्य होता है जो हमेशा आउट-ऑफ-डेट होता है, इसलिए जब भी आप पूछेंगे make <phony_target>, तो यह चलेगा, फ़ाइल सिस्टम की स्थिति से स्वतंत्र। कुछ आम makeलक्ष्य है कि अक्सर जाली हैं: all, install, clean, distclean, TAGS, info, check।
मान लेते हैं कि आपके पास installलक्ष्य है, जो मेकफाइल्स में बहुत आम है। यदि आप उपयोग नहीं करते हैं .PHONY, और एक फ़ाइल नाम installमेकफाइल के समान निर्देशिका में मौजूद है, तो कुछ भी नहींmake install करेगा । ऐसा इसलिए है क्योंकि मेक ने नियम का अर्थ है "फ़ाइल का नाम बनाने के लिए इस तरह के और इस तरह के नुस्खा को निष्पादित करें "। चूंकि फ़ाइल पहले से ही है, और इसकी निर्भरता नहीं बदली है, कुछ भी नहीं किया जाएगा।install
हालाँकि यदि आप installलक्ष्य PHONY बनाते हैं, तो यह मेक टूल को बताएगा कि लक्ष्य काल्पनिक है, और इससे वास्तविक फ़ाइल बनाने की अपेक्षा नहीं करनी चाहिए। इसलिए यह जाँच नहीं करेगा कि installफ़ाइल मौजूद है या नहीं , इसका अर्थ: क) इसके व्यवहार में परिवर्तन नहीं किया जाएगा यदि फ़ाइल मौजूद है और ख) अतिरिक्त stat()नहीं कहा जाएगा।
आपके Makefile में आम तौर पर सभी लक्ष्य जो आउटपुट नाम के समान नाम के साथ आउटपुट फ़ाइल नहीं बनाते हैं, उन्हें PHONY होना चाहिए। यह आमतौर पर शामिल all, install, clean, distclean, और इतने पर।
.shया .bashएक्सटेंशन को छोड़ने के लिए कहते हैं, जैसे कि वे एक मुख्य कार्य करते हैं और आपके द्वारा शामिल किए गए पुस्तकालयों के लिए एक्सटेंशन जोड़ते हुए आरक्षित होते हैं ( source mylib.sh)। वास्तव में, मैं यह तो सवाल करने के लिए मिला है, क्योंकि मैं एक ही निर्देशिका में एक स्क्रिप्ट था के रूप में मेरे Makefile बुलायाinstall
.PHONYहर समय का उपयोग करता हूँ ...
.PHONYसंस्करण हैं।
ध्यान दें : मेक टूल मेकफाइल को पढ़ता है और एक नियम में ':' प्रतीक के दोनों ओर फाइलों के संशोधन समय-टिकटों की जांच करता है।
एक निर्देशिका 'परीक्षण' में निम्नलिखित फाइलें मौजूद हैं:
prerit@vvdn105:~/test$ ls
hello hello.c makefile
मेकफाइल में एक नियम निम्नानुसार परिभाषित किया गया है:
hello:hello.c
cc hello.c -o hello
अब मान लें कि फ़ाइल 'हैलो' एक पाठ फ़ाइल है जिसमें कुछ डेटा होते हैं, जो 'hello.c' फ़ाइल के बाद बनाया गया था। अतः 'हैलो' का संशोधन (या निर्माण) टाइम-स्टैंप 'हैलो' की तुलना में नया होगा। इसलिए जब हम कमांड लाइन से 'हेलो हेलो' लागू करेंगे, तो यह निम्नानुसार प्रिंट होगा:
make: `hello' is up to date.
अब 'hello.c' फ़ाइल तक पहुँचें और इसमें कुछ सफ़ेद स्थान डालें, जो कोड सिंटैक्स या लॉजिक को प्रभावित नहीं करता है और फिर सेव करें और छोड़ दें। अब hello.c का संशोधन समय-मोहर 'हैलो' की तुलना में नया है। अब यदि आप 'हेलो' बनाते हैं, तो यह कमांड को निष्पादित करेगा:
cc hello.c -o hello
और फाइल over हैलो ’(टेक्स्ट फाइल) एक नई बाइनरी फाइल 'हैलो’ (उपरोक्त कंप्लीट कमांड का परिणाम) के साथ लिखी जाएगी।
अगर हम निम्नलिखित के रूप में मेकफाइल में .PHONY का उपयोग करते हैं:
.PHONY:hello
hello:hello.c
cc hello.c -o hello
और फिर 'मेक हेलो' का आह्वान करें, यह pwd 'परीक्षण' में मौजूद किसी भी फाइल को अनदेखा कर देगा और हर बार कमांड को निष्पादित करेगा।
अब मान लीजिए, 'हैलो' लक्ष्य की कोई निर्भरता घोषित नहीं की गई है:
hello:
cc hello.c -o hello
और 'हैलो' फ़ाइल पहले से ही pwd 'टेस्ट' में मौजूद है, फिर 'हेलो' हमेशा की तरह दिखाई देगा:
make: `hello' is up to date.
makeहै, यह सभी फाइलों के बारे में है! इस उत्तर के लिए धन्यवाद।
.PHONY: install
सबसे अच्छा स्पष्टीकरण GNU मेनुअल मेनुअल है: 4.6 फोनी टार्गेट्स सेक्शन ।
.PHONYएक मेक इन स्पेशल बिल्ट-इन टार्गेट नेम्स है । ऐसे अन्य लक्ष्य हैं जिन्हें आप में रुचि हो सकती है, इसलिए इन संदर्भों के माध्यम से इसे संक्षिप्त करने लायक है।
जब यह एक .PHONY लक्ष्य पर विचार करने का समय होता है, तो यह बताए बिना कि उसका कोई फ़ाइल मौजूद है या उसका अंतिम-संशोधन समय क्या है, इसकी परवाह किए बिना, अपना नुस्खा बिना शर्त चलाएगा।
आप भी इस तरह के और के रूप में मानक लक्ष्य बनाने में रुचि हो सकती है ।allclean
".PHONY" का एक महत्वपूर्ण मुश्किल इलाज भी है - जब एक भौतिक लक्ष्य, फॉनी लक्ष्य पर निर्भर करता है जो दूसरे भौतिक लक्ष्य पर निर्भर करता है:
TARGET1 -> PHONY_FORWARDER1 -> PHONY_FORWARDER2 -> TARGET2
आप बस उम्मीद करेंगे कि यदि आपने TARGET2 को अपडेट किया है, तो TARGET1 को TARGET1 के खिलाफ बासी माना जाना चाहिए, इसलिए TARGET1 का पुनर्निर्माण किया जाना चाहिए। और यह वास्तव में इस तरह से काम करता है ।
मुश्किल हिस्सा तब है जब TARGET1 TARGET1 के खिलाफ बासी नहीं है - जिस स्थिति में आपको उम्मीद करनी चाहिए कि TARGET1 का पुनर्निर्माण नहीं होना चाहिए।
यह आश्चर्यजनक रूप से काम नहीं करता क्योंकि: फ़ॉनी लक्ष्य को वैसे भी चलाया जाता था (जैसा कि फ़ॉनी लक्ष्य सामान्य रूप से करते हैं) , जिसका अर्थ है कि फ़ॉनी लक्ष्य को अद्यतन माना गया था । और उस कारण से TARGET1 को फोनी लक्ष्य के खिलाफ बासी माना जाता है ।
विचार करें:
all: fileall
fileall: file2 filefwd
echo file2 file1 >fileall
file2: file2.src
echo file2.src >file2
file1: file1.src
echo file1.src >file1
echo file1.src >>file1
.PHONY: filefwd
.PHONY: filefwd2
filefwd: filefwd2
filefwd2: file1
@echo "Produced target file1"
prepare:
echo "Some text 1" >> file1.src
echo "Some text 2" >> file2.src
आप इसके साथ खेल सकते हैं:
आप देख सकते हैं कि फ़ाइलल अप्रत्यक्ष रूप से एक फोनी लक्ष्य के माध्यम से फ़ाइल 1 पर निर्भर करता है - लेकिन यह हमेशा इस निर्भरता के कारण पुनर्निर्माण करता है। आप में निर्भरता को बदलते हैं fileallसे filefwdकरने के लिए file, अब fileallहर बार फिर से बनाया नहीं मिलता है, लेकिन केवल निर्भर लक्ष्यों की जब किसी भी एक फ़ाइल के रूप में के खिलाफ पुराना है।
विशेष लक्ष्य .PHONY:फॉनी लक्ष्यों को घोषित करने की अनुमति देता है, ताकि makeउन्हें वास्तविक फ़ाइल नामों के रूप में जांच न करें: यह हर समय काम करेगा भले ही ऐसी फाइलें अभी भी मौजूद हों।
आप .PHONY:अपने में कई डाल सकते हैं Makefile:
.PHONY: all
all : prog1 prog2
...
.PHONY: clean distclean
clean :
...
distclean :
...
फोनी लक्ष्य घोषित करने का एक और तरीका है: बस '::'
all :: prog1 prog2
...
clean ::
...
distclean ::
...
'::' का एक विशेष अर्थ है: लक्ष्य फोनी हैं और वे कई बार दिखाई दे सकते हैं:
clean ::
rm file1
...
clean ::
rm file2
कमांड ब्लॉक को एक के बाद एक कहा जाएगा।
मैं अक्सर आग न लगाने के लिए डिफ़ॉल्ट लक्ष्य बताने के लिए उनका उपयोग करता हूं।
superclean: clean andsomethingelse
blah: superclean
clean:
@echo clean
%:
@echo catcher $@
.PHONY: superclean
जाली के बिना, make supercleanसे निकाल देते थे clean, andsomethingelseऔर catcher superclean; लेकिन फोन के साथ, make supercleanआग नहीं होगा catcher superclean।
हमें यह बताने की चिंता करने की जरूरत नहीं है कि cleanलक्ष्य PHONY है, क्योंकि यह पूरी तरह से नहीं है। हालाँकि यह कभी भी साफ फ़ाइल नहीं बनाता है, लेकिन इसमें आग लगने की आज्ञा है इसलिए यह अंतिम लक्ष्य होगा।
हालाँकि, supercleanलक्ष्य वास्तव में बहुत ही कम है, इसलिए इसे supercleanलक्ष्य के लिए डिप्स प्रदान करने वाली किसी भी चीज़ के साथ ढेर करने की कोशिश करेंगे - इसमें अन्य supercleanलक्ष्य और %लक्ष्य शामिल हैं।
ध्यान दें कि हम andsomethingelseया के बारे में कुछ भी नहीं कहते हैं blah, इसलिए वे स्पष्ट रूप से पकड़ने वाले के पास जाते हैं।
आउटपुट कुछ इस तरह दिखता है:
$ make clean
clean
$ make superclean
clean
catcher andsomethingelse
$ make blah
clean
catcher andsomethingelse
catcher blah