2009-12-15 33 views
132

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

out.tar: TMP := $(shell mktemp -d) 
     echo hi $(TMP)/hi.txt 
     tar -C $(TMP) cf [email protected] . 
     rm -rf $(TMP) 

लिखा के रूप में, इसके बाद के संस्करण नियम समय है कि शासन पार्स है पर अस्थायी निर्देशिका बनाता है। इसका मतलब है कि, मैं भी हर समय बाहर नहीं निकलता हूं, कई अस्थायी निर्देशिकाएं बनती हैं। मैं अप्रयुक्त अस्थायी निर्देशिकाओं से भरे हुए/tmp से बचना चाहता हूं।

क्या वैरिएबल को केवल तब परिभाषित किया जा सकता है जब नियम निकाल दिया जाता है, जब भी इसे परिभाषित किया जाता है?

मेरा मुख्य विचार mktemp को डंप करना और शेल स्क्रिप्ट में टार करना है, लेकिन यह कुछ हद तक अस्पष्ट लगता है।

उत्तर

206

अपने उदाहरण में, TMP चर सेट किया गया है (और अस्थायी निर्देशिका बनाई गई) जब भी नियमout.tar के लिए मूल्यांकन किया जाता है।

out.tar : 
    $(eval TMP := $(shell mktemp -d)) 
    @echo hi $(TMP)/hi.txt 
    tar -C $(TMP) cf [email protected] . 
    rm -rf $(TMP) 

eval समारोह एक स्ट्रिंग का मूल्यांकन करता है जैसे कि यह makefile में मैन्युअल रूप से लिखी गई थी: आदेश केवल जब out.tar वास्तव में निकाल दिया जाता है निर्देशिका बनाने के लिए, आप निर्देशिका निर्माण चरणों में नीचे ले जाने की जरूरत है। इस मामले में, यह shell फ़ंक्शन कॉल के परिणामस्वरूप TMP चर सेट करता है।

संपादित (टिप्पणियों के जवाब में):,

out.tar : 
    $(eval [email protected]_TMP := $(shell mktemp -d)) 
    @echo hi $([email protected]_TMP)/hi.txt 
    tar -C $([email protected]_TMP) cf [email protected] . 
    rm -rf $([email protected]_TMP) 

इस लक्ष्य का नाम पहले जोड़ें होगा (out.tar:

एक अनूठा चर बनाने के लिए, आप निम्न कार्य कर सकता है इस मामले में) चर के लिए, out.tar_TMP नाम के साथ एक चर का उत्पादन। उम्मीद है कि संघर्षों को रोकने के लिए पर्याप्त है।

+2

में कुछ स्पष्टीकरण कूल ... इस नहीं होगा गुंजाइश TMP इस लक्ष्य को, यह? तो यदि ऐसे अन्य नियम हैं जिनके पास अपना स्वयं का $ (टीएमपी) उपयोग है (संभवतः समानांतर में -जे में), तो संघर्ष हो सकते हैं? इसके अलावा, @echo भी आवश्यक है? ऐसा लगता है कि आप इसे छोड़ सकते हैं। –

+0

मुझे नहीं लगता था कि आप इसे '@ echo' के बिना कर सकते हैं, लेकिन मैंने इसका परीक्षण किया, और यह काम करता है। अच्छी पकड़! मैं इसे अपने जवाब में बदल दूंगा। –

+0

जहां तक ​​स्कोपिंग जाता है, टीएमपी वैरिएबल उस विशेष नियम के लिए विशिष्ट नहीं होगा।यह वैश्विक नामांकन में मौजूद होगा और उसी नाम के साथ अन्य चर के साथ संघर्ष कर सकता है। क्या वांछित व्यवहार है? यदि आवश्यकता हो तो इसके आसपास काम करने के शायद तरीके हैं। –

20

एक और संभावना अलग-अलग लाइनों का उपयोग करने के लिए अलग-अलग लाइनों का उपयोग करना है जब एक नियम आग लगती है।

उदाहरण के लिए, यहां दो नियमों के साथ एक मेकफ़ाइल है। यदि कोई नियम आग लग जाता है, तो यह एक temp dir बनाता है और temp dir नाम पर TMP सेट करता है।

$ ls 
Makefile 
$ make ruleB 
echo testruleB_Y4Ow 
testruleB_Y4Ow 
$ ls 
Makefile testruleB_Y4Ow 
+0

बस एक अनुस्मारक के रूप में, जीएनयू बनाने के लिए [ऑर्डर-केवल पूर्वापेक्षाएँ] (http://www.gnu.org/software/make/manual/make.html#Prerequisite-Types) के लिए एक वाक्यविन्यास है जो इसे पूरक करने के लिए आवश्यक हो सकता है दृष्टिकोण। – anol

+3

इस समाधान से सावधान रहें! 'नियम ए: टीएमपी = $ (खोल mktemp -d testruleA_XXXX)' और 'नियम बी: टीएमपी = $ (खोल mktemp -d testruleB_XXXX) 'जब मेकफ़ाइल का पहला मूल्यांकन किया जाएगा तब होगा। दूसरे शब्दों में, 'नियम ए: टीएमपी = $ (खोल ...' आपके विचार से जल्द ही होता है। हालांकि यह इस विशेष मामले के लिए काम कर सकता है, यह विधि कुछ अनुक्रमिक संचालन के लिए समस्याएं पैदा करेगी। – JamesThomasMoon1979

31

ऐसा करने का एक अपेक्षाकृत आसान तरीका एक खोल स्क्रिप्ट के रूप में पूरे अनुक्रम लिखने के लिए:

PHONY = ruleA ruleB display 

all: ruleA 

ruleA: TMP = $(shell mktemp -d testruleA_XXXX) 
ruleA: display 

ruleB: TMP = $(shell mktemp -d testruleB_XXXX) 
ruleB: display 

display: 
    echo ${TMP} 

कोड चल रहा है उम्मीद परिणाम पैदा करता है।

out.tar: 
    set -e ;\ 
    TMP=$$(mktemp -d) ;\ 
    echo hi $$TMP/hi.txt ;\ 
    tar -C $$TMP cf [email protected] . ;\ 
    rm -rf $$TMP ;\ 

मैं कुछ संबंधित सुझावों यहां समेकित है https://stackoverflow.com/a/29085684/86967

+2

यह निश्चित रूप से सबसे सरल और इसलिए सबसे अच्छा है उत्तर ('@' और 'eval' से परहेज करना और एक ही नौकरी करना)। ध्यान दें कि आपके आउटपुट में आपको' $ TMP' (जैसे 'tar -C $ TMP ... ') दिखाई देता है हालांकि मान सही है –

+0

इस तरह यह सामान्य रूप से किया जाता है; मुझे उम्मीद है कि लोग यह जवाब देखें क्योंकि अभ्यास में कोई भी स्वीकार किए गए प्रयास के माध्यम से नहीं जाता है। – pmos

संबंधित मुद्दे