मल्टीफिल बैश कमांड इन मेकफाइल


120

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

for i in `find`
do
    all="$all $i"
done
gcc $all

इसके अलावा, क्या कोई समझा सकता है कि bash -c 'a=3; echo $a > file'टर्मिनल में सिंगल-लाइन कमांड भी सही क्यों काम करता है, लेकिन मेकफाइल मामले में खाली फाइल बनाएं?


4
दूसरा भाग एक अलग प्रश्न होना चाहिए। एक और सवाल जोड़ने से सिर्फ शोर पैदा होता है।
l0b0

जवाबों:


136

आप लाइन निरंतरता के लिए बैकस्लैश का उपयोग कर सकते हैं। हालाँकि, ध्यान दें कि शेल पूरे कमांड को एक ही लाइन में समाप्‍त करता है, इसलिए आपको कुछ लाइनों को अर्धविराम के साथ समाप्‍त करने की आवश्‍यकता है:

foo:
    for i in `find`;     \
    do                   \
        all="$$all $$i"; \
    done;                \
    gcc $$all

लेकिन अगर आप बस पूरी सूची को findआह्वान द्वारा वापस ले जाना चाहते हैं और इसे पास करना चाहते हैं gcc, तो आपको वास्तव में एक बहुस्तरीय आदेश की आवश्यकता नहीं है:

foo:
    gcc `find`

या, अधिक शेल-पारंपरिक $(command)दृष्टिकोण ( $हालांकि भागने की सूचना ) का उपयोग करना:

foo:
    gcc $$(find)

2
मल्टीलाइन के लिए, आपको अभी भी डॉलर के संकेतों से बचने की आवश्यकता है, जैसा कि कहीं और टिप्पणियों में संकेत दिया गया है।
15-30

1
हां, एक संक्षिप्त उत्तर 1. $: = $ $ 2. बहु बीट को \ BTW बैश लोगों के साथ जोड़ते हैं, आमतौर पर $$ (खोजें) के साथ `find` कॉल को बदलने की सलाह देते हैं
Yauhen Yakimovich

89

जैसा कि प्रश्न में संकेत दिया गया है, प्रत्येक उप-कमान अपने शेल में चलाया जाता है । यह गैर-तुच्छ शैल लिपियों को थोड़ा गड़बड़ लिख देता है - लेकिन यह संभव है! इसका हल यह है कि आप अपनी स्क्रिप्ट को एक उप-कमांड (एक लाइन) पर विचार करेंगे।

Makefiles के भीतर शेल स्क्रिप्ट लिखने के लिए सुझाव:

  1. के $साथ बदलकर स्क्रिप्ट के उपयोग से बच$$
  2. ;आदेशों के बीच सम्मिलित करके स्क्रिप्ट को एकल पंक्ति के रूप में कार्य करने के लिए परिवर्तित करें
  3. यदि आप स्क्रिप्ट को कई लाइनों पर लिखना चाहते हैं, तो एंड-ऑफ-लाइन से बचें \
  4. वैकल्पिक रूप से set -eउप-कमांड विफलता पर गर्भपात करने के प्रावधान से मेल खाने के लिए शुरू करें
  5. यह पूरी तरह से वैकल्पिक है, लेकिन आप स्क्रिप्ट को कई लाइन अनुक्रम के सामंजस्य के साथ ()या {}जोर दे सकते हैं - कि यह एक सामान्य मेकफाइल कमांड अनुक्रम नहीं है

यहाँ एक उदाहरण ओपी से प्रेरित है:

mytarget:
    { \
    set -e ;\
    msg="header:" ;\
    for i in $$(seq 1 3) ; do msg="$$msg pre_$${i}_post" ; done ;\
    msg="$$msg :footer" ;\
    echo msg=$$msg ;\
    }

4
आप SHELL := /bin/bashअपने मेकफाइल में BASH- विशिष्ट सुविधाओं जैसे कि प्रक्रिया प्रतिस्थापन को सक्षम करना चाहते हैं ।
ब्रेंट ब्रैडबर्न

8
सूक्ष्म बिंदु: अज्ञात कमांड {के {setरूप में व्याख्या को रोकने के लिए अंतरिक्ष के बाद महत्वपूर्ण है ।
ब्रेंट बर्नबर्न

3
सूक्ष्म बिंदु # 2: मेकफाइल में यह संभवत: कोई फर्क नहीं पड़ता, लेकिन यदि आप कभी-कभी स्क्रिप्ट की प्रतिलिपि बनाना चाहते हैं और इसे सीधे शेल प्रॉम्प्ट से चलाना चाहते हैं, तो इससे जुड़ने के बीच का अंतर {}और ()एक बड़ा अंतर पड़ता है। आप अपने शेल उदाहरण पर चर घोषित कर सकते हैं, और विशेष रूप से setअंदर के साथ राज्य को संशोधित कर सकते हैं {}()स्क्रिप्ट को आपके वातावरण को संशोधित करने से रोकता है, जिसे संभवतः पसंद किया जाता है। उदाहरण ( यह आपके शेल सत्र को समाप्त कर देगा ) { set -e ; } ; false:।
ब्रेंट बर्नबर्न

आप निम्न फ़ॉर्म का उपयोग करके टिप्पणियां शामिल कर सकते हैं: command ; ## my comment \` (the comment is between `और` \ `)। यह ठीक काम करता है, सिवाय इसके कि यदि आप कमांड को मैन्युअल रूप से (कॉपी-एंड-पेस्ट द्वारा) चलाते हैं, तो कमांड इतिहास कमांड को तोड़ने वाले तरीके से टिप्पणी को सम्मिलित करेगा (यदि आप इसे पुन: उपयोग करने का प्रयास करते हैं)। [नोट: इस टिप्पणी के लिए वाक्य रचना हाइलाइटिंग टूटी हुई है, बैकटिक के अंदर बैकस्लैश के उपयोग के कारण।]
ब्रेंट ब्रैडबर्न

यदि आप मेकफाइल के अंदर बैश / पर्ल / स्क्रिप्ट में एक स्ट्रिंग को तोड़ना चाहते हैं, तो स्ट्रिंग को बंद करें, बैकस्लैश, न्यूलाइन, (कोई इंडेंटेशन) ओपन स्ट्रिंग उद्धरण नहीं। उदाहरण; perl -e QUOTE print 1; QUOTE BACKSLASH NEWLINE QUOTE प्रिंट 2 QUOTE
mosh

2

केवल आदेशों को लागू करने में क्या गलत है?

foo:
       echo line1
       echo line2
       ....

और अपने दूसरे प्रश्न के लिए, आपको इसके बजाय, यानी $का उपयोग करके बच निकलने की आवश्यकता है ।$$bash -c '... echo $$a ...'

संपादित करें: आपका उदाहरण इस तरह से एक एकल पंक्ति स्क्रिप्ट में फिर से लिखा जा सकता है:

gcc $(for i in `find`; do echo $i; done)

5
कारण "प्रत्येक कमांड अपने स्वयं के शेल में चलाया जाता है", जबकि मुझे कमांड 2 में कमांड 1 के परिणाम का उपयोग करने की आवश्यकता होती है। जैसे उदाहरण में।
जोफसी

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

+1, विशेष रूप से सरलीकृत संस्करण के लिए। और क्या यह सिर्फ `` जीसीसी `` `` करने के समान नहीं है?
एल्डर अबुलिसिमोव

1
हाँ यही है। लेकिन आप निश्चित रूप से सिर्फ 'गूंज' की तुलना में अधिक जटिल चीजें कर सकते हैं।
जेसप्रे

2

बेशक, मेकफिल लिखने का उचित तरीका वास्तव में दस्तावेज़ है जो लक्ष्य उन स्रोतों पर निर्भर करता है। तुच्छ मामले में, प्रस्तावित समाधान fooस्वयं पर निर्भर करेगा , लेकिन निश्चित रूप से, makeएक परिपत्र निर्भरता को छोड़ने के लिए पर्याप्त स्मार्ट है। लेकिन अगर आप अपनी निर्देशिका में एक अस्थायी फ़ाइल जोड़ते हैं, तो यह "जादुई" निर्भरता श्रृंखला का हिस्सा बन जाएगा। निर्भरता की एक स्पष्ट सूची बनाने के लिए बेहतर है एक बार और सभी के लिए, शायद एक स्क्रिप्ट के माध्यम से।

जीएनयू को पता है कि gccएक निष्पादन योग्य फ़ाइल .cऔर .hफ़ाइलों के सेट का उत्पादन करने के लिए कैसे चलाना है , इसलिए हो सकता है कि आपको वास्तव में मात्राओं की आवश्यकता हो

foo: $(wildcard *.h) $(wildcard *.c)

1

ONESHELL निर्देश एक ही शेल आह्वान में निष्पादित होने के लिए कई लाइन व्यंजनों को लिखने की अनुमति देता है।

SOURCE_FILES = $(shell find . -name '*.c')

.ONESHELL:
foo: ${SOURCE_FILES}
    for F in $^; do
        gcc -c $$F
    done

हालांकि एक खामी है: विशेष उपसर्ग वर्ण ('@', '-', और '+') की अलग-अलग व्याख्या की जाती है।

https://www.gnu.org/software/make/manual/html_node/One-Shell.html

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