नियम निष्पादन समय पर परिवर्तनशील बनायें


208

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

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

जैसा कि लिखा गया है, उपरोक्त नियम उस समय अस्थायी निर्देशिका बनाता है, जब नियम पार्स किया जाता है । इसका मतलब है कि, यहां तक ​​कि मैं हर समय नहीं बनाता हूं। कई अस्थायी निर्देशिकाएं बनाई जाती हैं। मैं अपने अप्रयुक्त अस्थायी निर्देशिकाओं से अटे पड़े होने से बचना चाहूंगा।

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

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

जवाबों:


321

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

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

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

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

एक अद्वितीय चर बनाने के लिए, आप निम्न कार्य कर सकते हैं:

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

यह लक्ष्य के नाम को प्रस्तुत करेगा (out.tar, इस मामले में) चर के लिए, नाम के साथ एक चर का उत्पादन out.tar_TMP। उम्मीद है, संघर्षों को रोकने के लिए यह पर्याप्त है।


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

3
लगता है चाल करने के लिए (हालांकि औसत गैर बनाने के लिए थोड़ा अपारदर्शी गुरु :-) धन्यवाद!
एमिल सीट

29
इस उपाय से सावधान रहें! $(eval $@_TMP := $(shell mktemp -d))क्या होगा जब मेकफाइल का मूल्यांकन पहली बार किया जाता है, नियम प्रक्रियाओं के क्रम में नहीं । दूसरे शब्दों में, $(eval ...)जितना आप सोचते हैं उतनी ही जल्दी होता है। हालांकि इस उदाहरण के लिए यह ठीक हो सकता है, यह विधि कुछ अनुक्रमिक संचालन के लिए समस्याएं पैदा करेगी।
जेम्सटॉमसून

1
@ JamesThomasMoon1979 क्या आप जानते हैं कि उन सीमाओं को कैसे पार किया जाता है, उदाहरण के लिए कुछ चर निकाले जाते हैं जो नियम में पहले से निष्पादित चरणों का परिणाम होना चाहिए?
वादिम कोटोव

2
मेरे स्वयं के प्रश्न का उत्तर देना: मेरे लिए वर्कअराउंड 1 नियम के निष्पादन के दौरान फाइलें बना रहा था, और उन्हें दूसरे नियम के पहले चरण में निकालने की कोशिश कर रहा था।
वादिम कोटोव

63

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

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

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


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

यह है कि यह आम तौर पर कैसे किया जाता है; मुझे उम्मीद है कि लोग इस जवाब को देखेंगे क्योंकि व्यवहार में कोई भी स्वीकृत के सभी प्रयासों से नहीं गुजरता है।
PMOS

क्या होगा यदि आप शेल विशिष्ट कमांड का उपयोग कर रहे हैं? उस मामले में शेल कमांड एक ही कॉलिंग मेक, राइट की तुलना में एक ही शेल लैंग्वेज में होगा? मैंने शेबंग के साथ कुछ मेकअप देखा था।
ptitpion

@ptitpion: BASH- SHELL := /bin/bashविशिष्ट सुविधाओं को सक्षम करने के लिए आप अपने मेकफाइल में भी चाहें ।
नोबार

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}

कोड चलाना अपेक्षित परिणाम देता है:

$ ls
Makefile
$ make ruleB
echo testruleB_Y4Ow
testruleB_Y4Ow
$ ls
Makefile  testruleB_Y4Ow

एक अनुस्मारक के रूप में, जीएनयू मेक में केवल-केवल आवश्यक शर्तें के लिए एक सिंटैक्स है जो इस दृष्टिकोण को पूरक करने के लिए आवश्यक हो सकता है।
अनिल

11
इस उपाय से सावधान रहें! ruleA: TMP = $(shell mktemp -d testruleA_XXXX)और ruleB: TMP = $(shell mktemp -d testruleB_XXXX)तब होगा जब मेकफाइल का पहले मूल्यांकन किया जाएगा। दूसरे शब्दों में, ruleA: TMP = $(shell ...जितना आप सोचते हैं उतनी ही जल्दी होता है। हालांकि यह इस विशेष मामले के लिए काम कर सकता है, यह विधि कुछ अनुक्रमिक संचालन के लिए समस्याएं पैदा करेगा।
जेम्सथोमसून 1979

1

मैं "जवाब नहीं" नापसंद करता हूं, लेकिन ... नहीं।

make's वैरिएबल वैश्विक हैं और माना जाता है कि इसका मूल्यांकन मेकफाइल के "पार्सिंग" चरण के दौरान किया जाता है, निष्पादन के चरण के दौरान नहीं।

इस मामले में, जब तक एक एकल लक्ष्य के लिए चर स्थानीय, @ nobar के उत्तर का पालन ​​करें और इसे एक शेल चर बना दें।

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

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