GNU मेकफाइल वेरिएबल असाइनमेंट =;? =:: = और + = के बीच क्या अंतर है?


763

क्या कोई भी स्पष्ट विवरण दे सकता है कि वास्तव में मेकफाइल्स में चर असाइनमेंट कैसे काम करता है।

के बीच क्या अंतर है :

 VARIABLE = value
 VARIABLE ?= value
 VARIABLE := value
 VARIABLE += value

मैंने GNU मेक के मैनुअल में सेक्शन को पढ़ा है , लेकिन यह अभी भी मेरे लिए मायने नहीं रखता है।

जवाबों:


1027

आलसी सेट

VARIABLE = value

एक चर की सामान्य सेटिंग, लेकिन valueफ़ील्ड के साथ उल्लेख किए गए किसी भी अन्य चर का पुनरावृत्ति रूप से उनके मूल्य के साथ विस्तार किया जाता है, जिस पर चर का उपयोग किया जाता है, न कि जब इसे घोषित किया गया था

तत्काल सेट करें

VARIABLE := value

मूल्यों के सरल विस्तार के साथ एक चर की स्थापना - इसके भीतर मूल्यों को घोषणा के समय में विस्तारित किया जाता है।

आलसी सेट अगर अनुपस्थित

VARIABLE ?= value

वैरिएबल की सेटिंग तभी है जब उसका कोई मूल्य नहीं है। valueजब हमेशा VARIABLEएक्सेस किया जाता है तो उसका मूल्यांकन किया जाता है। के बराबर है

ifeq ($(origin FOO), undefined)
  FOO = bar
endif

देखें प्रलेखन अधिक जानकारी के लिए।

संलग्न

VARIABLE += value

मौजूदा मान में आपूर्ति की गई वैल्यू को लागू करना (या वैरिएबल मौजूद नहीं होने पर उस मान पर सेट करना)


25
क्या A + = B का विस्तार B है? अगर मैं A + = B, और फिर B + = C करता हूं, तो क्या A $ {B} और $ {C} के संघटन का मूल्यांकन करेगा?
एंटोन डेनेको

15
जैसा कि मैनुअल से जुड़ा हुआ भाग कहता है। मूल कार्य के लिए जो भी सरल या पुनरावर्ती शब्दार्थ है, उसके अनुसार = = संचालित होता है। तो हां, यह आरएचएस का विस्तार करेगा लेकिन क्या यह तुरंत या स्थगित तरीके से एलएचएस पर चर के प्रकार पर निर्भर करता है।
इतन रीसनर

6
जब आप कहते हैं कि चर मान का विस्तार किया गया है तो आपका क्या मतलब है?
साश्को ल्यखेंको

2
@ СашкоЛихенко के विस्तार gnu.org/software/make/manual/make.html#Flavors
Umair R

7
"अनुपस्थित है तो सेट" आलसी या तत्काल? क्या मैं "अनुपस्थित हो तो आलसी सेट" और "तत्काल सेट यदि अनुपस्थित हो"?
वुड्रो बारलो

268

=वैरिएबल का उपयोग करने से मान को असाइन किया जा सकता है। यदि चर में पहले से ही एक मूल्य था, तो इसे बदल दिया गया है। इसका उपयोग होने पर इस मूल्य का विस्तार किया जाएगा। उदाहरण के लिए:

HELLO = world
HELLO_WORLD = $(HELLO) world!

# This echoes "world world!"
echo $(HELLO_WORLD)

HELLO = hello

# This echoes "hello world!"
echo $(HELLO_WORLD)

का उपयोग करना :=समान है =। हालांकि, जब इसका उपयोग किया जाता है तो मूल्य का विस्तार होने के बजाय, असाइनमेंट के दौरान इसका विस्तार किया जाता है। उदाहरण के लिए:

HELLO = world
HELLO_WORLD := $(HELLO) world!

# This echoes "world world!"
echo $(HELLO_WORLD)

HELLO = hello

# Still echoes "world world!"
echo $(HELLO_WORLD)

HELLO_WORLD := $(HELLO) world!

# This echoes "hello world!"
echo $(HELLO_WORLD)

?=वैरिएबल के उपयोग से वैरिएबल का मान होता है यदि वैरिएबल को पहले से असाइन नहीं किया गया था। यदि चर को पहले एक रिक्त मान ( VAR=) सौंपा गया था , तो यह अभी भी सेट माना जाता है कि मुझे लगता है । अन्यथा, कार्य बिल्कुल पसंद हैं =

उपयोग करना उपयोग करने +=जैसा है =, लेकिन मूल्य को प्रतिस्थापित करने के बजाय, मान को वर्तमान में जोड़ा जाता है, बीच में एक जगह के साथ। यदि चर पहले से सेट किया गया था :=, तो मुझे लगता है कि इसका विस्तार किया गया है । परिणामी मूल्य का विस्तार तब किया जाता है जब इसका उपयोग मुझे लगता है । उदाहरण के लिए:

HELLO_WORLD = hello
HELLO_WORLD += world!

# This echoes "hello world!"
echo $(HELLO_WORLD)

यदि ऐसा कुछ HELLO_WORLD = $(HELLO_WORLD) world!उपयोग किया गया था, तो पुनरावृत्ति का परिणाम होगा, जो संभवतः आपके मेकफाइल के निष्पादन को समाप्त कर देगा। यदि A := $(A) $(B)उपयोग किए गए थे, तो परिणाम सटीक नहीं होगा +=क्योंकि उपयोग Bकरना विस्तारित है, :=जबकि विस्तारित होने का +=कारण नहीं होगा B


3
कि का एक परिणाम इसलिए है VARIABLE = literalऔर VARIABLE := literalहमेशा बराबर हैं। क्या मैने इसे सही समझा?
ऐयाओ

1
@aiao, हां शाब्दिक के रूप में उनके उपयोग के लिए अपरिवर्तनीय हैं
सेबस्टियन

एक सूक्ष्म अंतर यह है: -?: पुनरावर्ती कहा जाता है मेकफाइल्स में प्रदर्शन में सुधार कर सकते हैं। उदाहरण के लिए यदि $? = $ (शेल some_command_that_runs_long_time)। पुनरावर्ती कॉल में यह केवल एक बार मूल्यांकन किया जाएगा। निर्माण प्रदर्शन में लाभ के कारण। : = धीमी हो जाएगी क्योंकि कमांड अनावश्यक रूप से कई बार चल रही है
केशव

61

मेरा सुझाव है कि आप "मेक" का उपयोग करके कुछ प्रयोग करें। यहाँ एक सरल डेमो है, जो =और के बीच का अंतर दिखाता है :=

/* Filename: Makefile*/
x := foo
y := $(x) bar
x := later

a = foo
b = $(a) bar
a = later

test:
    @echo x - $(x)
    @echo y - $(y)
    @echo a - $(a)
    @echo b - $(b)

make test प्रिंट:

x - later
y - foo bar
a - later
b - later bar

अधिक विस्तृत विवरण यहां देखें


5
@परिणामों की इस भ्रामक पुनरावृत्ति से बचने के लिए प्रत्येक नुस्खा के सामने एक का उपयोग करना बेहतर होगा ।
अलेक्जेंड्रो डी ओलिवेरा

2
बनाओ /* ... */ब्लॉक टिप्पणी का समर्थन नहीं करता है
yoonghm

31

जब आप उपयोग करते हैं VARIABLE = value, यदि valueवास्तव में किसी अन्य चर का संदर्भ है, तो मूल्य केवल तब निर्धारित VARIABLEकिया जाता है जब उपयोग किया जाता है। यह एक उदाहरण के साथ सबसे अच्छा सचित्र है:

VAL = foo
VARIABLE = $(VAL)
VAL = bar

# VARIABLE and VAL will both evaluate to "bar"

जब आप उपयोग करते हैं VARIABLE := value, तो आपको value वैसा ही मूल्य मिलता है जैसा अभी है । उदाहरण के लिए:

VAL = foo
VARIABLE := $(VAL)
VAL = bar

# VAL will evaluate to "bar", but VARIABLE will evaluate to "foo"

उपयोग करने का VARIABLE ?= valअर्थ है कि यदि आप पहले से सेट नहीं हैं , VARIABLE तो आप केवल मान सेट करते हैं VARIABLE। यदि यह पहले से सेट नहीं है, तो मूल्य की सेटिंग का VARIABLEउपयोग किए जाने तक स्थगित कर दिया जाता है (उदाहरण 1 में)।

VARIABLE += value बस जोड़ता है value करता है VARIABLE। का वास्तविक मूल्य valueनिर्धारित किया जाता है क्योंकि यह शुरू में सेट किया गया था, =या तो का उपयोग करके :=


दरअसल, आपके पहले उदाहरण में, VARIABLE $ (VAL) है और VAL बार है। जब इसका उपयोग किया जाता है तो VARIABLE का विस्तार होता है।
प्रात:

1
हां, टिप्पणियां बता रही हैं कि जब उनका उपयोग किया जाएगा तो क्या होगा।
मियादी

आह; मुझे लगता है कि आपने इसे ठीक कर दिया है, या मैंने "के रूप में" मूल्यांकन "गलत किया है।"
स्ट्रैजर

7

उपरोक्त उत्तरों में, यह समझना महत्वपूर्ण है कि "घोषणा / उपयोग समय में मूल्यों का विस्तार किया गया" से क्या मतलब है। जैसे मान देने से *.cकोई विस्तार नहीं होता है। यह केवल तब होता है जब इस स्ट्रिंग का उपयोग एक कमांड द्वारा किया जाता है कि यह कुछ ग्लोबिंग को ट्रिगर करेगा। इसी तरह, कोई मान किसी विस्तार को पसंद नहीं करता है $(wildcard *.c)या $(shell ls *.c)नहीं करता है और पूरी तरह से परिभाषा के समय पर मूल्यांकन किया जाता :=है, भले ही हमने चर परिभाषा में उपयोग किया हो।

निम्नलिखित सीफ़ाइल को उस निर्देशिका में आज़माएँ जहाँ आपके पास कुछ C फ़ाइलें हैं:

VAR1 = *.c
VAR2 := *.c
VAR3 = $(wildcard *.c)
VAR4 := $(wildcard *.c)
VAR5 = $(shell ls *.c)
VAR6 := $(shell ls *.c)

all :
    touch foo.c
    @echo "now VAR1 = \"$(VAR1)\"" ; ls $(VAR1)
    @echo "now VAR2 = \"$(VAR2)\"" ; ls $(VAR2)
    @echo "now VAR3 = \"$(VAR3)\"" ; ls $(VAR3)
    @echo "now VAR4 = \"$(VAR4)\"" ; ls $(VAR4)
    @echo "now VAR5 = \"$(VAR5)\"" ; ls $(VAR5)
    @echo "now VAR6 = \"$(VAR6)\"" ; ls $(VAR6)
    rm -v foo.c

रनिंग makeएक नियम को ट्रिगर करेगा जो अतिरिक्त (खाली) सी फ़ाइल बनाता है, जिसे कहा जाता है, foo.cलेकिन 6 में से कोई भी चर foo.cइसके मूल्य में नहीं है।


यह एक शानदार कॉल है और घोषणा के समय विस्तार के लिए बहुत सारे उदाहरण हैं, यह एक उदाहरण के साथ उत्तर का विस्तार करने के लिए उपयोगी होगा और उपयोग समय पर विस्तार के लिए कुछ शब्द
रॉबर्ट मॉन्फेरा
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.