मेकफाइल में एक चर को कैसे प्रिंट करें


247

मेरे मेकफाइल में, मेरे पास एक चर 'NDK_PROJECT_PATH' है, मेरा सवाल यह है कि जब मैं यह संकलन करता हूं तो मैं इसे कैसे प्रिंट कर सकता हूं?

मैंने "$ पथ" स्ट्रिंग प्रदर्शित करते हुए फ़ाइल बनाओ गूंज पढ़ें और मैंने कोशिश की:

@echo $(NDK_PROJECT_PATH)
@echo $(value NDK_PROJECT_PATH)

दोनों मुझे देता है

"build-local.mk:102: *** missing separator.  Stop."

कोई भी जानता है कि यह मेरे लिए काम क्यों नहीं कर रहा है?

जवाबों:


223

आप वेरिएबल्स को प्रिंटआउट कर सकते हैं क्योंकि मेकफाइल पढ़ा जाता है (यह मानते हुए GNU बनाते हैं कि आपने इस प्रश्न को उचित रूप से टैग किया है) इस विधि का उपयोग करके ("var" नामक वैरिएबल के साथ):

$(info $$var is [${var}])

आप इस निर्माण को किसी भी रेसिपी में जोड़कर देख सकते हैं कि शेल किस चीज़ से बनेगा:

.PHONY: all
all: ; $(info $$var is [${var}])echo Hello world

अब, यहाँ क्या होता है कि दुकानों को पूरी रेसिपी ( $(info $$var is [${var}])echo Hello world) एकल पुनरावर्ती विस्तारित चर के रूप में बनाते हैं । जब आप नुस्खा को चलाने का निर्णय लेते हैं (उदाहरण के लिए जब आप इसे बनाने के लिए कहते हैं all), तो यह चर का विस्तार करता है, और फिर प्रत्येक परिणामी लाइन को शेल में अलग से पास करता है।

तो, दर्दनाक विस्तार से:

  • इसका विस्तार होता है $(info $$var is [${var}])echo Hello world
  • ऐसा करने के लिए यह पहले फैलता है $(info $$var is [${var}])
    • $$ शाब्दिक हो जाता है $
    • ${var}बन जाता है :-)(कहते हैं)
    • साइड इफेक्ट वह है जो $var is [:-)]स्टैंडर्ड आउट पर दिखाई देता है
    • $(info...)हालांकि इसका विस्तार खाली है
  • मेक को छोड़ दिया जाता है echo Hello world
    • echo Hello worldपहले स्टडआउट पर प्रिंट करें , आपको यह बताने के लिए कि यह शेल को क्या करने के लिए कहने जा रहा है
  • शेल स्टडआउट Hello worldपर प्रिंट करता है।

2
यह (डॉट) होना चाहिए। PHONY के बजाय।
हैमेडियन

172

के अनुसार जीएनयू बनाओ मैनुअल और यह भी इस सवाल का जवाब नीचे में 'bobbogo' से कहा, आप उपयोग कर सकते हैं की जानकारी / चेतावनी / त्रुटि प्रदर्शन पाठ करने के लिए।

$(error   text…)
$(warning text…)
$(info    text…)

चर मुद्रित करने के लिए,

$(error   VAR is $(VAR))
$(warning VAR is $(VAR))
$(info    VAR is $(VAR))

'एरर' एरर स्ट्रिंग दिखाने के बाद मेक एक्जेक्यूशन को रोक देगा


वाह, यह नहीं पता था। इको से बेहतर तरीका है, जो लॉग में कमांड को डुप्लिकेट करता है।
गढ़ २ deep ’

148

"मिस्टर मेक पोस्ट" से https://www.cmcrossroads.com/article/printing-value-makefile-aviable

निम्नलिखित नियम को अपने Makefile में जोड़ें:

print-%  : ; @echo $* = $($*)

फिर, यदि आप मेकफाइल वैरिएबल का मान ज्ञात करना चाहते हैं, तो:

make print-VARIABLE

और यह वापस आ जाएगी:

VARIABLE = the_value_of_the_variable

आपने इसे लेखक से बेहतर बताया। थम्स अप!
fnnie

44

यदि आप बस कुछ आउटपुट चाहते हैं, तो आप $(info)स्वयं ही उपयोग करना चाहते हैं । आप एक Makefile में कहीं भी कर सकते हैं, और यह दिखाएगा कि उस लाइन का मूल्यांकन कब किया गया है:

$(info VAR="$(VAR)")

VAR="<value of VAR>"जब भी उत्पादन होगा उस लाइन को प्रोसेस करेंगे। यह व्यवहार बहुत ही स्थिति पर निर्भर है, इसलिए आपको यह सुनिश्चित करना होगा कि $(info)विस्तार सब कुछ के बाद होता है जो संशोधित हो सकता है $(VAR)!

एक अधिक सामान्य विकल्प एक चर के मूल्य को मुद्रित करने के लिए एक विशेष नियम बनाना है। सामान्यतया, नियमों को चरों के असाइन किए जाने के बाद निष्पादित किया जाता है, इसलिए यह आपको वह मूल्य दिखाएगा जो वास्तव में उपयोग किया जा रहा है। (हालांकि, एक नियम के लिए एक चर को बदलना संभव है ।) अच्छा स्वरूपण यह स्पष्ट करने में मदद करेगा कि एक चर क्या निर्धारित किया गया है, और $(flavor)फ़ंक्शन आपको बताएगा कि चर किस तरह का है। तो इस नियम में:

print-% : ; $(info $* is a $(flavor $*) variable set to [$($*)]) @true
  • $*तने का विस्तार होता है कि % पैटर्न नियम में मेल खाता है।
  • $($*)उस चर के मान का विस्तार करता है जिसका नाम इसके द्वारा दिया गया है $*
  • [और ]स्पष्ट रूप से चर विस्तार चित्रित। आप भी "और "इसी तरह का उपयोग कर सकते हैं ।
  • $(flavor $*)आपको बताता है कि यह किस प्रकार का चर है। नोट: $(flavor) एक चर नाम लेता है , और इसका विस्तार नहीं। इसलिए यदि आप कहते हैं make print-LDFLAGS, तो आप प्राप्त करते हैं $(flavor LDFLAGS), जो आप चाहते हैं।
  • $(info text)आउटपुट प्रदान करता है। विस्तार के साइड-इफेक्ट के रूप में इसके स्टडआउट पर प्रिंट बनाएंtext । का विस्तार $(info)हालांकि खाली है। आप इसके बारे में सोच सकते हैं @echo, लेकिन महत्वपूर्ण रूप से यह शेल का उपयोग नहीं करता है, इसलिए आपको शेल कोटािंग नियमों के बारे में चिंता करने की आवश्यकता नहीं है।
  • @trueवहाँ केवल नियम के लिए एक आदेश प्रदान करने के लिए है। इसके बिना, उत्पादन भी कर देगा print-blah is up to date। मुझे लगता है @trueकि यह और अधिक स्पष्ट करता है कि इसका मतलब नो-ऑप होना है।

इसे चलाना, आपको मिलता है

$ make print-LDFLAGS
LDFLAGS is a recursive variable set to [-L/Users/...]

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

समीक्षा के लिए धन्यवाद। मैं समझता हूं कि मैं एक बार पर्याप्त प्रतिष्ठा पा सकता हूं, लेकिन इस बीच मुझे क्या करना चाहिए? मेरा मानना ​​है कि मेरा जवाब अतिरिक्त मूल्य प्रदान करता है, तो क्या मुझे इसे नहीं जोड़ना चाहिए?
जिम नैस्बी

1
मेरा सुझाव है कि यह एक स्वसंपूर्ण उत्तर होगा जो आप उस पर टिप्पणी कर रहे हैं, बल्कि उस उत्तर के लिए एक आउट-ऑफ-प्लेस टिप्पणी के रूप में इसे प्रकाशित करने के बजाय जिस पर आप टिप्पणी कर रहे हैं।
चार्ल्स डफी

@JimNasby हाँ, चार्ल्स ने क्या सुझाव दिया। वास्तव में यह एक शुरुआत के रूप में मदद कर सकता है ताकि केवल "टिप्पणी करने के लिए पर्याप्त खेद नहीं" को हटा दें, क्योंकि यह लाल ध्वज की तरह है। यदि आप इसे एक पूर्ण उत्तर में बदल देते हैं (इसे आप सभी की तरह संपादित कर सकते हैं), यह काफी अच्छी तरह से करना चाहिए। चीयर्स।
ड्रैगन एनर्जी

बहुत बढ़िया - यह अब बेहतर जवाब है। :)
चार्ल्स डफी

6

@echo $ (NDK_PROJECT_PATH) इसे करने का अच्छा तरीका है। मुझे नहीं लगता कि त्रुटि वहाँ से आती है। आम तौर पर यह त्रुटि तब दिखाई देती है जब आपने इरादा गलत किया था: मुझे लगता है कि आपके पास ऐसे स्थान हैं जहां आपके पास एक टैब होना चाहिए।


2
मैंने '@echo $ (NDK_PROJECT_PATH)' की कोशिश की, मुझे अभी भी एक त्रुटि "build-local.mk:102: *** लापता विभाजक। बंद करो।" मेरे पास 'इको' के बाद सिर्फ 1 जगह है, '@echo' से पहले कोई स्पेस या टैब नहीं है।
माइकल

क्या आप सुनिश्चित हैं कि त्रुटि इस लाइन से आती है? क्या यह रेखा एक नियम में है? वह शायद

6

makeकमांड लाइन की आवश्यकता के सभी संस्करणों को लाइन में पहले चरित्र के रूप में TAB (स्पेस नहीं) के साथ इंडेंट किया जाना चाहिए। यदि आपने हमें केवल दो पंक्तियों के बजाय पूरा नियम दिखाया तो हम स्पष्ट उत्तर दे सकते हैं, लेकिन यह कुछ इस तरह होना चाहिए:

myTarget: myDependencies
        @echo hi

जहाँ दूसरी पंक्ति में पहला वर्ण TAB होना चाहिए।


4

भागो make -n; यह आपको चर का मान दिखाता है।

Makefile ...

all:
        @echo $(NDK_PROJECT_PATH)

कमान:

export NDK_PROJECT_PATH=/opt/ndk/project
make -n 

आउटपुट:

echo /opt/ndk/project

हालांकि यह बहुत उपयोगी है और मैं निष्पादन के बजाय--just-print एक ही उपयोग करता हूं
फ्रेड्रिक गॉस

3

यह makefile'लापता विभाजक' त्रुटि संदेश उत्पन्न करेगा:

all
    @echo NDK_PROJECT_PATH=$(NDK_PROJECT_PATH)

done:
        @echo "All done"

इससे पहले एक टैब है @echo "All done"(हालांकि done:नियम और कार्रवाई काफी हद तक शानदार है), लेकिन इससे पहले नहीं @echo PATH=$(PATH)

परेशानी यह है कि शुरू होने वाली रेखा में allया तो एक कॉलन :या बराबर होना चाहिए =जिससे यह पता चले कि यह एक लक्ष्य रेखा या एक स्थूल रेखा है, और इसमें न तो है, इसलिए विभाजक गायब है।

एक चर के मूल्य को ग्रहण करने वाली क्रिया को एक लक्ष्य के साथ जुड़ा होना चाहिए, संभवतः एक डमी या PHONEY लक्ष्य। और उस लक्ष्य रेखा पर एक बृहदान्त्र होना चाहिए। यदि आप उदाहरण में एक के :बाद एक जोड़ते हैं और एक टैब द्वारा प्रमुख रेखाओं को अगली पंक्ति में प्रतिस्थापित करते हैं, तो यह पूरी तरह से काम करेगा।allmakefile

आपको मूल रूप से लाइन 102 के पास एक अनुरूप समस्या है makefile। यदि आपने प्रतिध्वनि संचालन से पहले 5 गैर-रिक्त, गैर-टिप्पणी लाइनें दिखाईं जो विफल हो रही हैं, तो संभवतः निदान को समाप्त करना संभव होगा। हालाँकि, मई 2013 में सवाल पूछे जाने के बाद, यह संभावना नहीं है कि टूट makefileअभी भी उपलब्ध है (अगस्त 2014), इसलिए इस उत्तर को औपचारिक रूप से मान्य नहीं किया जा सकता है। इसका उपयोग केवल उस समस्या को हल करने के लिए किया जा सकता है जिसमें समस्या उत्पन्न हुई है।


3

Makefile को संशोधित करने की आवश्यकता नहीं है।

$ cat printvars.mak
print-%:
        @echo '$*=$($*)'

$ cd /to/Makefile/dir
$ make -f ~/printvars.mak -f Makefile print-VARIABLE

2

समस्या यह है कि गूंज केवल एक निष्पादन ब्लॉक के तहत काम करती है। "xx:" के बाद कुछ भी

तो पहले एक्ज़ीक्यूशन ब्लॉक के ऊपर कुछ भी सिर्फ इनिशियलाइज़ेशन है इसलिए कोई एक्ज़ीक्यूट कमांड का उपयोग नहीं किया जा सकता।

इसलिए एक निष्पादन ब्लाक बनाएं


1

यह एक सामान्य तरीके से किया जा सकता है और जटिल मेकफाइल को डीबग करते समय बहुत उपयोगी हो सकता है। अन्य उत्तर में वर्णित उसी तकनीक का अनुसरण करते हुए , आप निम्नलिखित को किसी भी मेकफाइल में सम्मिलित कर सकते हैं:

# if the first command line argument is "print"
ifeq ($(firstword $(MAKECMDGOALS)),print)

  # take the rest of the arguments as variable names
  VAR_NAMES := $(wordlist 2,$(words $(MAKECMDGOALS)),$(MAKECMDGOALS))

  # turn them into do-nothing targets
  $(eval $(VAR_NAMES):;@:))

  # then print them
  .PHONY: print
  print:
          @$(foreach var,$(VAR_NAMES),\
            echo '$(var) = $($(var))';)
endif

तब आप किसी भी वैरिएबल की वैल्यू डंप करने के लिए सिर्फ "प्रिंट बना सकते हैं":

$ make print CXXFLAGS
CXXFLAGS = -g -Wall

1

आप अपनी फ़ाइल में एक vars नियम बना सकते हैं, जैसे:

dispvar = echo $(1)=$($(1)) ; echo

.PHONY: vars
vars:
    @$(call dispvar,SOMEVAR1)
    @$(call dispvar,SOMEVAR2)

सभी चर को यहां डंप करने के कुछ और मजबूत तरीके हैं: ग्नू मेक: एक विशेष रन में सभी चर (या "मैक्रोज़") के मूल्यों की सूची बनाएं


0

यदि आप खुद मेकफाइल को संशोधित नहीं करना चाहते हैं, तो आप --evalएक नया लक्ष्य जोड़ने के लिए उपयोग कर सकते हैं , और फिर नए लक्ष्य को निष्पादित कर सकते हैं , जैसे;

make --eval='print-tests: @echo TESTS $(TESTS) ' print-tests

आप कमांड लाइन का उपयोग करके आवश्यक TAB वर्ण सम्मिलित कर सकते हैं CTRL-V, TAB

उदाहरण मेकफाइल ऊपर से:

all: do-something

TESTS=
TESTS+='a'
TESTS+='b'
TESTS+='c'

do-something:
        @echo "doing something"
        @echo "running tests $(TESTS)"
        @exit 1

मैं आपकी स्क्रिप्ट चलाने की कोशिश कर रहा हूं, लेकिन मुझे त्रुटि हो रही हैmake: *** missing separator. Stop.
रिनाल्डी सेगसीन

आह, क्षमा करें, निश्चित। "प्रिंट-परीक्षण" लक्ष्य के अंत में गुम बृहदान्त्र।
वेड

वास्तव में आपको नई make --eval='print-tests: ; @echo TESTS $(TESTS)' print-tests
कड़ियों

0

अगर आप android मेक (mka) @echo $(NDK_PROJECT_PATH)का *** missing separator. Stop." उपयोग करते हैं, तो काम नहीं करेगा और आपको इस उत्तर का उपयोग करने में त्रुटि देता है, यदि आप android मेक में वैरिएबल को प्रिंट करने का प्रयास कर रहे हैं

NDK_PROJECT_PATH := some_value
$(warning $(NDK_PROJECT_PATH))

मेरे लिए काम किया


0

मैं आमतौर पर एक त्रुटि के साथ गूँजता हूं यदि मैं चर मान देखना चाहता था। (केवल यदि आप मूल्य देखना चाहते थे। यह निष्पादन को रोक देगा।)

@echo $ (त्रुटि NDK_PROJECT_PATH = $ (NDK_PROJECT_PATH)

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.