मैं Makefile लक्ष्यों में बैश सिंटैक्स का उपयोग कैसे कर सकता हूं?


208

मुझे अक्सर बैश सिंटैक्स बहुत उपयोगी लगते हैं, जैसे प्रक्रिया प्रतिस्थापन diff <(sort file1) <(sort file2)

क्या मेकफाइल में ऐसे बैश कमांड का उपयोग करना संभव है? मैं कुछ इस तरह से सोच रहा हूँ:

file-differences:
    diff <(sort file1) <(sort file2) > $@

मेरे जीएनयू मेक 3.80 में यह एक त्रुटि देगा क्योंकि यह कमांड निष्पादित करने के shellबजाय इसका उपयोग करता है bash


यह वास्तव में मेरी समस्या थी, मुझे इस प्रश्न को खोजने में कम से कम एक घंटा लगा! मैं अपने त्रुटि संदेश को यहाँ छोड़ता हूँ ताकि भविष्य के पाठक इसे पा सकें: /bin/sh: -c: line 0: syntax error near unexpected token ('`
डेविड

जवाबों:


380

GNU मेक डॉक्यूमेंटेशन से,

5.3.1 Choosing the Shell
------------------------

The program used as the shell is taken from the variable `SHELL'.  If
this variable is not set in your makefile, the program `/bin/sh' is
used as the shell.

इसलिए SHELL := /bin/bashअपने मेकअप के शीर्ष पर रखें, और आपको जाने के लिए अच्छा होना चाहिए।

BTW: आप इसे एक लक्ष्य के लिए भी कर सकते हैं, कम से कम GNU मेक के लिए। प्रत्येक लक्ष्य के अपने चर कार्य हो सकते हैं, जैसे:

all: a b

a:
    @echo "a is $$0"

b: SHELL:=/bin/bash   # HERE: this is setting the shell for b only
b:
    @echo "b is $$0"

वह प्रिंट करेंगे:

a is /bin/sh
b is /bin/bash

अधिक विवरण के लिए प्रलेखन में "लक्ष्य-विशिष्ट चर मान" देखें। वह लाइन मेकफाइल में कहीं भी जा सकती है, लक्ष्य से ठीक पहले उसका होना जरूरी नहीं है।


43
से एक उद्धरण के लिए इंतजार कर रहे 500 इनाम man। समय की बात करें। : पी
सिद्धार्थआरटी

3
@inLoveWithPython खैर, infoवास्तव में, लेकिन, मुझे लगता है कि इसने वास्तव में एंडी की मदद की। मैं जानता हूँ कि मैं दिन ऐसे ही मिला है ...
derobert

3
अगर संदेह में, @derobert का शाब्दिक अर्थ था: मेकफाइल SHELL=/bin/bashकी पहली पंक्ति (या टिप्पणी के ठीक बाद)।
योहान याकिमोविच 21

1
धन्यवाद @derobert ने मेरी समस्या को stackoverflow.com/questions/26806832/…
चंदन चौधरी

2
क्या केवल एक विशेष लक्ष्य के लिए शेल परिवर्तन को बदलना संभव है लेकिन दूसरों को अछूता नहीं छोड़ना चाहिए?
एंटी

18

आप bashसीधे कॉल कर सकते हैं, -cध्वज का उपयोग कर सकते हैं :

bash -c "diff <(sort file1) <(sort file2) > $@"

बेशक, आप चर $ @ को पुनर्निर्देशित करने में सक्षम नहीं हो सकते हैं, लेकिन जब मैंने ऐसा करने की कोशिश की, तो मुझे -bash: $@: ambiguous redirectएक त्रुटि संदेश मिला , इसलिए आप इससे पहले कि आप इसमें शामिल हो सकते हैं, हालांकि आप इसे देखना चाहते हैं। बैश का उपयोग करते हुए 3.2.something, तो शायद तुम्हारा काम अलग है)।


4

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


4

आप डिफ़ॉल्ट शेल का उपयोग करने के बजाय सीधे अपने मेकफाइल के भीतर बैश कॉल कर सकते हैं:

bash -c "ls -al"

के बजाय:

ls -al

1
ध्यान दें कि makeपर्यावरण चर शेल के मूल्य को अनदेखा करता है।
चोराबा

2

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

यदि आप sudo dpkg-reconfigure dashप्रॉम्प्ट पर 'नहीं' चलाते हैं और जवाब देते हैं, तो आपका सिस्टम डिफ़ॉल्ट शेल के रूप में डैश का उपयोग नहीं करेगा। यह तो कम से कम उबंटू में (कम से कम उबंटू) को इंगित करेगा। ध्यान दें कि आपके सिस्टम शेल के रूप में डैश का उपयोग करना थोड़ा अधिक कुशल है।


1
जब नाम के तहत आह्वान किया जाता है sh, तो संगतता मोड में बैश चलता है ( set -o posix)। ओपी कार्यक्षमता का उपयोग करने की कोशिश कर रहा है, प्रक्रिया प्रतिस्थापन, इस मोड में उपलब्ध नहीं है।
चार्ल्स डफी

1

एक तरीका जो काम भी करता है वह इस तरह से आपके लक्ष्य की पहली पंक्ति में है:

your-target: $(eval SHELL:=/bin/bash)
    @echo "here shell is $$0"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.