TL; DR ऐसा करने की कोशिश नहीं करते
$ make run arg
इसके बजाय स्क्रिप्ट बनाएँ:
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
और यह करो:
$ ./buildandrunprog.sh arg
उक्त प्रश्न का उत्तर:
आप नुस्खा में एक चर का उपयोग कर सकते हैं
run: prog
./prog $(var)
फिर बनाने के लिए एक तर्क के रूप में एक चर असाइनमेंट पास करें
$ make run var=arg
यह निष्पादित करेगा ./prog arg
।
लेकिन नुकसान से सावधान रहें। मैं इस विधि के नुकसान और अन्य तरीकों के बारे में विस्तार से बताऊंगा।
सवाल के पीछे की मंशा का जवाब:
धारणा: आप prog
कुछ तर्कों के साथ चलना चाहते हैं, लेकिन यदि आवश्यक हो तो चलने से पहले इसका पुनर्निर्माण करें।
उत्तर: एक स्क्रिप्ट बनाएं जो यदि आवश्यक हो तो फिर से आर्ग से चलाता है
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
यह स्क्रिप्ट बहुत स्पष्ट है। इसका उपयोग यह करने के लिए करता है कि यह किसके लिए अच्छा है: भवन। यह एक शेल स्क्रिप्ट का उपयोग करता है जो कि इसके लिए अच्छा है: बैच प्रोसेसिंग।
इसके अलावा आप एक और स्क्रिप्ट के सभी लचीलेपन के बिना एक और स्क्रिप्ट के पूर्ण लचीलेपन और स्पष्टता के साथ जो कुछ भी आप की आवश्यकता हो सकती है।
कॉलिंग सिंटैक्स भी अब व्यावहारिक रूप से समान है:
$ ./buildandrunprog.sh foo "bar baz"
से तुलना:
$ ./prog foo "bar baz"
इसके विपरीत
$ make run var="foo bar\ baz"
पृष्ठभूमि:
लक्ष्य के लिए तर्क पारित करने के लिए डिज़ाइन नहीं किया गया है। कमांड लाइन पर सभी तर्कों को एक लक्ष्य (उर्फ लक्ष्य), एक विकल्प के रूप में, या एक चर असाइनमेंट के रूप में व्याख्या की जाती है।
इसलिए यदि आप इसे चलाते हैं:
$ make run foo --wat var=arg
मेकअप की व्याख्या करेगा run
और foo
उनके व्यंजनों के अनुसार लक्ष्यों (लक्ष्य) अद्यतन करने के लिए के रूप में। --wat
बनाने के लिए एक विकल्प के रूप में। और var=arg
एक चर असाइनमेंट के रूप में।
अधिक जानकारी के लिए देखें: https://www.gnu.org/software/make/manual/html_node/Goals.html#Goals
शब्दावली के लिए देखें: https://www.gnu.org/software/make/manual/html_node/Rule-Introduction.html#Rule-Introduction
चर असाइनमेंट विधि के बारे में और मैं इसके खिलाफ क्यों सलाह देता हूं
$ make run var=arg
और नुस्खा में चर
run: prog
./prog $(var)
यह एक नुस्खा के लिए तर्कों को पारित करने का सबसे "सही" और सीधा तरीका है। लेकिन जब इसका उपयोग तर्कों के साथ एक कार्यक्रम चलाने के लिए किया जा सकता है तो निश्चित रूप से इसे इस तरह से उपयोग करने के लिए डिज़ाइन नहीं किया गया है। देख https://www.gnu.org/software/make/manual/html_node/Overriding.html#Overriding
मेरी राय में इसका एक बड़ा नुकसान है: आप जो करना चाहते हैं वह prog
तर्क से चलाया जाता है arg
। लेकिन लिखने के बजाय:
$ ./prog arg
आप लिख रहे हैं:
$ make run var=arg
रिक्त स्थान वाले कई तर्कों या तर्कों को पारित करने का प्रयास करते समय यह और भी अजीब हो जाता है:
$ make run var="foo bar\ baz"
./prog foo bar\ baz
argcount: 2
arg: foo
arg: bar baz
से तुलना:
$ ./prog foo "bar baz"
argcount: 2
arg: foo
arg: bar baz
इस रिकॉर्ड के लिए मेरे prog
जैसा दिखता है:
#! /bin/sh
echo "argcount: $#"
for arg in "$@"; do
echo "arg: $arg"
done
यह भी ध्यान दें कि आपको $(var)
मेकफाइल में उद्धरण नहीं देना चाहिए :
run: prog
./prog "$(var)"
क्योंकि तब prog
हमेशा सिर्फ एक तर्क मिलेगा:
$ make run var="foo bar\ baz"
./prog "foo bar\ baz"
argcount: 1
arg: foo bar\ baz
यह सब इसलिए है क्योंकि मैं इस मार्ग के खिलाफ सलाह देता हूं।
पूर्णता के लिए यहां "रन बनाने के लिए तर्क पास करें" कुछ अन्य तरीके हैं।
विधि 1:
run: prog
./prog $(filter-out $@, $(MAKECMDGOALS))
%:
@true
सुपर शॉर्ट स्पष्टीकरण: लक्ष्यों की सूची से वर्तमान लक्ष्य को फ़िल्टर करें। कैच %
टू ऑल टारगेट ( ) जो अन्य लक्ष्यों को चुपचाप अनदेखा करने के लिए कुछ भी नहीं करता है।
विधि 2:
ifeq (run, $(firstword $(MAKECMDGOALS)))
runargs := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
$(eval $(runargs):;@true)
endif
run:
./prog $(runargs)
सुपर शॉर्ट स्पष्टीकरण: यदि लक्ष्य run
तो पहले लक्ष्य को हटा दें और शेष लक्ष्यों का उपयोग करने के लिए कुछ भी लक्ष्य न बनाएं eval
।
दोनों आपको कुछ इस तरह लिखने की अनुमति देंगे
$ make run arg1 arg2
विवरण के लिए गहन अध्ययन करें: https://www.gnu.org/software/make/manual/html_node/ind.net.html
विधि 1 की समस्याएं:
एक डैश के साथ शुरू होने वाले तर्कों की व्याख्या एक लक्ष्य के रूप में की जाती है और इसे पारित नहीं किया जाता है।
$ make run --foo --bar
वैकल्पिक हल
$ make run -- --foo --bar
समान चिन्ह वाले तर्क की व्याख्या मेक द्वारा की जाएगी और पारित नहीं की जाएगी
$ make run foo=bar
कोई वर्कअराउंड नहीं
रिक्त स्थान के साथ तर्क अजीब है
$ make run foo "bar\ baz"
कोई वर्कअराउंड नहीं
यदि कोई तर्क होता है run
(लक्ष्य के बराबर) तो उसे भी हटा दिया जाएगा
$ make run foo bar run
के ./prog foo bar
बजाय चलेगा./prog foo bar run
विधि 2 के साथ संभव समाधान
यदि एक तर्क एक वैध लक्ष्य है तो इसे भी चलाया जाएगा।
$ make run foo bar clean
चलेगा, ./prog foo bar clean
लेकिन लक्ष्य के लिए नुस्खा clean
(यह मौजूद है)।
विधि 2 के साथ संभव समाधान
जब आप एक वैध लक्ष्य को गलत करते हैं तो इसे पकड़ के कारण चुपचाप नजरअंदाज कर दिया जाएगा।
$ make celan
बस चुपचाप उपेक्षा करेंगे celan
।
वर्कअराउंड सब कुछ क्रिया करना है। तो आप देखिए क्या होता है। लेकिन यह वैध उत्पादन के लिए बहुत शोर पैदा करता है।
विधि 2 की समस्याएं:
यदि किसी तर्क में एक मौजूदा लक्ष्य के समान नाम है, तो मेक एक चेतावनी को मुद्रित करेगा कि यह ओवरराइट किया जा रहा है।
कोई वर्कअराउंड जिसे मैं जानता हूं
समान चिह्न वाले तर्क अभी भी मेक द्वारा पारित किए जाएंगे और पारित नहीं किए जाएंगे
कोई वर्कअराउंड नहीं
रिक्त स्थान के साथ तर्क अभी भी अजीब है
कोई वर्कअराउंड नहीं
स्पेस ब्रेक के साथ तर्क eval
कुछ भी लक्ष्य नहीं बनाने की कोशिश कर रहा है।
वर्कअराउंड: उपरोक्त सभी कुछ भी न करते हुए ग्लोबल कैच को बनाएं। ऊपर के रूप में इस समस्या के साथ कि यह फिर से चुपचाप गलत लक्ष्यों को नजरअंदाज कर देगा।
यह eval
रनटाइम पर मेकफाइल को संशोधित करने के लिए उपयोग करता है। पठनीयता और दुर्बलता और कम से कम विस्मय के सिद्धांत के संदर्भ में आप कितना बदतर हो सकते हैं ।
वर्कअराउंड: ऐसा न करें !! 1 के बजाय एक शेल स्क्रिप्ट लिखें जो रन बनाती है और फिर चलती है prog
।
मैंने केवल ग्नू मेक का उपयोग करके परीक्षण किया है। अन्य तरीकों से अलग व्यवहार हो सकता है।
TL; DR ऐसा करने की कोशिश नहीं करते
$ make run arg
इसके बजाय स्क्रिप्ट बनाएँ:
#! /bin/sh
# rebuild prog if necessary
make prog
# run prog with some arguments
./prog "$@"
और यह करो:
$ ./buildandrunprog.sh arg