क्या Makefile में एक बहु-पंक्ति स्ट्रिंग चर बनाना संभव है


122

मैं एक मेकफाइल वैरिएबल बनाना चाहता हूं जो एक बहु-पंक्ति स्ट्रिंग (जैसे ईमेल रिलीज़ घोषणा का निकाय) है। कुछ इस तरह

ANNOUNCE_BODY="
Version $(VERSION) of $(PACKAGE_NAME) has been released

It can be downloaded from $(DOWNLOAD_URL)

etc, etc"

लेकिन मुझे ऐसा करने का कोई तरीका नहीं मिल रहा है। क्या यह संभव है?

जवाबों:


172

हां, आप इस तरह से बहु-पंक्ति चर घोषित करने के लिए परिभाषित कीवर्ड का उपयोग कर सकते हैं:

define ANNOUNCE_BODY
Version $(VERSION) of $(PACKAGE_NAME) has been released.

It can be downloaded from $(DOWNLOAD_URL).

etc, etc.
endef

मुश्किल हिस्सा अपने बहु-लाइन चर को मेकफाइल से बाहर निकाल रहा है। यदि आप सिर्फ "गूंज $ (ANNOUNCE_BODY)" का उपयोग करने की स्पष्ट बात करते हैं, तो आप उस परिणाम को देखेंगे जो दूसरों ने यहां पोस्ट किया है - शेल चर की दूसरी और बाद की पंक्तियों को खुद को कमांड के रूप में संभालने की कोशिश करता है।

हालाँकि, आप चर मान को पर्यावरण चर के रूप में शेल में निर्यात कर सकते हैं, और फिर इसे शेल से पर्यावरण चर के रूप में संदर्भित कर सकते हैं (एक परिवर्तनशील नहीं)। उदाहरण के लिए:

export ANNOUNCE_BODY
all:
    @echo "$$ANNOUNCE_BODY"

के $$ANNOUNCE_BODYबजाय $(ANNOUNCE_BODY)एक नियमित रूप से परिवर्तनशील संदर्भ होगा जो एक शेल पर्यावरण चर संदर्भ का संकेत है, के उपयोग पर ध्यान दें । अपने वैरिएबल संदर्भ के आसपास उद्धरणों का उपयोग करना सुनिश्चित करें, यह सुनिश्चित करने के लिए कि शेल द्वारा ही नईलाइनों की व्याख्या नहीं की गई है।

बेशक, यह विशेष चाल मंच और खोल संवेदनशील हो सकती है। मैंने GNU बैश 3.2.13 के साथ उबंटू लिनक्स पर इसका परीक्षण किया; YMMV।


1
export ANNOUNCE_BODYकेवल चर को नियमों के अंदर सेट करता है - यह $ $ ANNOUNCE_BODY को अन्य चर को परिभाषित करने की अनुमति नहीं देता है।
अनातोली टेकटोनिक

@techtonik यदि आप ANNOUNCE_BODYअन्य परिवर्तनीय परिभाषाओं के मूल्य का उपयोग करना चाहते हैं , तो इसे किसी अन्य परिवर्तनशील चर की तरह ही देखें। उदाहरण के लिए, OTHER=The variable ANNOUNCE_BODY is $(ANNOUNCE_BODY)exportयदि आप OTHERएक कमांड में बाहर निकलना चाहते हैं, तो बेशक आपको अभी भी ट्रिक की आवश्यकता होगी ।
एरिक मेल्स्की

25

'आपके मल्टी-लाइन वैरिएबल को मेकफाइल से वापस लाना' (एरिक मेल्स्की द्वारा 'ट्रिकी पार्ट' के रूप में विख्यात) का एक अन्य तरीका है, अपने मल्टी-लाइन स्ट्रिंग के साथ substशुरू की गई नईलाइन्स को बदलने के लिए फ़ंक्शन का उपयोग करने की योजना बनाना । फिर -इ का उपयोग करके उनकी व्याख्या करें। ऐसा करने वाली गूंज पाने के लिए आपको .SHELL = बैश सेट करना पड़ सकता है। define\necho

इस दृष्टिकोण का एक फायदा यह है कि आप अपने पाठ में अन्य ऐसे बच पात्रों को भी रखते हैं और उनका सम्मान करते हैं।

इस प्रकार के अब तक उल्लिखित सभी दृष्टिकोणों को संश्लेषित करता है ...

आप के साथ हवा:

define newline


endef

define ANNOUNCE_BODY=
As of $(shell date), version $(VERSION) of $(PACKAGE_NAME) has been released.  

It can be downloaded from $(DOWNLOAD_URL).  

endef

someTarget:
    echo -e '$(subst $(newline),\n,${ANNOUNCE_BODY})'

ध्यान दें कि अंतिम गूंज पर एकल उद्धरण महत्वपूर्ण हैं।


4
ध्यान दें कि "इको-ई" पोर्टेबल नहीं है। आपको इसके बजाय संभवतः प्रिंटफ (1) को प्राथमिकता देना चाहिए।
मैडिसिनिस्ट

2
महान जवाब, हालांकि, मुझे इसे चलाने के लिए =बाद में निकालना पड़ा define ANNOUNCE_BODY
एमएसचिल्ली

13

मान लें कि आप केवल मानक आउटपुट पर अपने चर की सामग्री को प्रिंट करना चाहते हैं, एक और उपाय है:

do-echo:
    $(info $(YOUR_MULTILINE_VAR))

1
इस नो-ऑप नियम ने एक अवांछित संदेश का उत्पादन किया make: 'do-echo' is up to date.:। "नो ऑप" कॉमैंड का उपयोग करके मैं इसे शांत करने में सक्षम था:@: $(info $(YOUR_MULTILINE_VAR))
गिलियूम पापिन

@GuillaumePapin थोड़ा देर से, लेकिन आप .PHONYअपने मेकफाइल को बताने के लिए उपयोग कर सकते हैं कि उस नियम की जांच करने के लिए कुछ भी नहीं है। मेकफाइल्स मूल रूप से संकलक के लिए थे, अगर मैं गलत नहीं हूं, तो makeकुछ ऐसा जादू कर रहा हूं कि मैं यह अनुमान लगाने के लिए नहीं समझता हूं कि नियम कुछ भी नहीं बदलेगा, और जैसा कि यह माना जाता है कि इसे 'किया' जाता है। .PHONY do-echoअपनी फ़ाइल में जोड़ना makeइस पर ध्यान न देना और वैसे भी कोड चलाना बताएगा ।
M3D

आप $(info ...)एक नियम के बाहर रख सकते हैं । यह अभी भी आउटपुट उत्पन्न करेगा।
डैनियल स्टीवंस


3

हाँ। आप के साथ newlines बच \:

VARIABLE="\
THIS IS A VERY LONG\
TEXT STRING IN A MAKE VARIABLE"

अपडेट करें

आह, आप newlines चाहते हैं? तो नहीं, मुझे नहीं लगता कि वेनिला मेक में कोई रास्ता है। हालाँकि, आप यहाँ कमांड भाग में दस्तावेज़ का उपयोग कर सकते हैं

[यह काम नहीं करता है, MadScientist की टिप्पणी देखें]

foo:
    echo <<EOF
    Here is a multiple line text
    with embedded newlines.
    EOF

यह सच है, लेकिन यह मुझे किसी भी स्वरूपण (newlines) नहीं देता है। यह सिर्फ पाठ की एक पंक्ति बन जाती है
जोनर

मल्टी-लाइन यहाँ-दस्तावेज़ जीएनयू मेक में वर्णित अनुसार काम नहीं करते हैं।
मैट बी।

3
यहाँ बहु-व्यंजन व्यंजन विधि के अंदर डॉक्स पॉसिक्स मानक का समर्थन करने वाले मेक के किसी भी मानक संस्करण में काम नहीं करेगा: मेक मानक के लिए यह आवश्यक है कि रेसिपी की प्रत्येक अलग पंक्ति को एक अलग शेल में चलाया जाए। बनाओ यह बताने के लिए कि यह यहाँ एक दस्तावेज़ है या नहीं, और इसे अलग तरीके से संभालने के लिए कमांड पर कोई भी पार्सिंग न करें। अगर आपको कुछ ऐसे वेरिएंट के बारे में पता है जो इसका समर्थन करता है (मैंने कभी नहीं सुना है) तो आपको इसे स्पष्ट रूप से बताना चाहिए।
मैडिसिनिस्ट

2

एरिक मेल्स्की के जवाब के लिए बस एक पोस्टस्क्रिप्ट: आप पाठ में आदेशों के आउटपुट को शामिल कर सकते हैं, लेकिन आपको शेल सिंटैक्स "$ (फू)" के बजाय मेकफाइल सिंटैक्स "$ (शेल फू)" का उपयोग करना होगा। उदाहरण के लिए:

define ANNOUNCE_BODY  
As of $(shell date), version $(VERSION) of $(PACKAGE_NAME) has been released.  

It can be downloaded from $(DOWNLOAD_URL).  

endef

2

यह यहां एक दस्तावेज़ नहीं देता है, लेकिन यह एक बहु-पंक्ति संदेश को इस तरह से प्रदर्शित करता है जो पाइप के लिए उपयुक्त है।

=====

MSG = this is a\\n\
multi-line\\n\
message

method1:
     @$(SHELL) -c "echo '$(MSG)'" | sed -e 's/^ //'

=====

आप ग्नू के कॉल करने योग्य मैक्रो का भी उपयोग कर सकते हैं:

=====

MSG = this is a\\n\
multi-line\\n\
message

method1:
        @echo "Method 1:"
        @$(SHELL) -c "echo '$(MSG)'" | sed -e 's/^ //'
        @echo "---"

SHOW = $(SHELL) -c "echo '$1'" | sed -e 's/^ //'

method2:
        @echo "Method 2:"
        @$(call SHOW,$(MSG))
        @echo "---"

=====

यहाँ उत्पादन है:

=====

$ make method1 method2
Method 1:
this is a
multi-line
message
---
Method 2:
this is a
multi-line
message
---
$

=====


1

अंत-पंक्ति को परिभाषित करने के लिए आप अपने स्ट्रिंग में \ n वर्ण का उपयोग क्यों नहीं करते? अतिरिक्त लाइनों को कई लाइनों पर जोड़ने के लिए भी जोड़ें।

ANNOUNCE_BODY=" \n\
Version $(VERSION) of $(PACKAGE_NAME) has been released \n\
\n\
It can be downloaded from $(DOWNLOAD_URL) \n\
\n\
etc, etc"

मैं एरिक मेल्स्की के उत्तर को पसंद करता हूं लेकिन यह आपके आवेदन के आधार पर आपके लिए पहले से ही चाल चल सकता है।
Roalt

इस पर मुझे एक प्रश्न मिला। यह मुख्य रूप से ठीक काम करता है, सिवाय इसके कि मैं हर पंक्ति की शुरुआत में एक अतिरिक्त "स्पेस" देखता हूं (पहले को छोड़कर)। क्या आपके साथ ऐसा होता है? मैं सभी पाठ को एक पंक्ति में रख सकता हूं, जो कि मेरे द्वारा पसंद किए गए आउटपुट को प्रभावी ढंग से अलग करके \ n अलग कर देगा। समस्या यह है कि यह मेकफाइल में बहुत बदसूरत लग रहा है!
शाहबाज

मुझे एक वर्कअराउंड मिला। मैंने पाठ डाल दिया, $(subst \n ,\n,$(TEXT))हालांकि मैं चाहता हूं कि एक बेहतर तरीका था!
शहबाज 17

1

मेरा जवाब देखें कि यह काम क्यों नहीं करता है (कम से कम मेरे प्रयास से)
Roalt

1
मैनुअल आपको उचित तरीका दिखाता है जो काम करता है: उपयोग करें echo
डिंग-यी चेन

1

आपको "परिभाषित / समाप्ति" का उपयोग करना चाहिए निर्माण करें:

define ANNOUNCE_BODY
Version $(VERSION) of $(PACKAGE_NAME) has been released.

It can be downloaded from $(DOWNLOAD_URL).

etc, etc.
endef

फिर आपको शेल चर के लिए इस चर का मान पास करना चाहिए। लेकिन, यदि आप परिवर्तनशील चर का उपयोग करते हुए ऐसा करते हैं, तो यह कई में विभाजित होने का आदेश देगा:

ANNOUNCE.txt:
  echo $(ANNOUNCE_BODY) > $@               # doesn't work

Qout मदद भी नहीं करेगा।

मूल्य को पारित करने का सबसे अच्छा तरीका पर्यावरण चर के माध्यम से इसे पारित करना है:

ANNOUNCE.txt: export ANNOUNCE_BODY:=$(ANNOUNCE_BODY)
ANNOUNCE.txt:
  echo "$${ANNOUNCE_BODY}" > $@

नोटिस:

  1. इस विशेष लक्ष्य के लिए परिवर्तनीय निर्यात किया जाता है, ताकि आप पुन: उपयोग कर सकें कि पर्यावरण बहुत अधिक प्रदूषित नहीं होगा;
  2. पर्यावरण चर (डबल नाम और चर नाम के आसपास घुंघराले कोष्ठक) का उपयोग करें;
  3. चर के आसपास उद्धरणों का उपयोग। उनके बिना नई रेखाएं खो जाएंगी और सभी पाठ एक पंक्ति में दिखाई देंगे।

1

.ONESHELL की भावना में, यह संभव है कि .ONESHELL चुनौती भरे वातावरण में पास हो।

define _oneshell_newline_


endef

define oneshell
@eval "$$(printf '%s\n' '$(strip                            \
                         $(subst $(_oneshell_newline_),\n,  \
                         $(subst \,\/,                      \
                         $(subst /,//,                      \
                         $(subst ','"'"',$(1))))))' |       \
          sed -e 's,\\n,\n,g' -e 's,\\/,\\,g' -e 's,//,/,g')"
endef

उपयोग का एक उदाहरण कुछ इस तरह होगा:

define TEST
printf '>\n%s\n' "Hello
World\n/$$$$/"
endef

all:
        $(call oneshell,$(TEST))

यह आउटपुट (पीआईडी ​​27801 मानकर) दिखाता है:

>
Hello
World\n/27801/

यह दृष्टिकोण कुछ अतिरिक्त कार्यक्षमता के लिए अनुमति देता है:

define oneshell
@eval "set -eux ; $$(printf '%s\n' '$(strip                            \
                                    $(subst $(_oneshell_newline_),\n,  \
                                    $(subst \,\/,                      \
                                    $(subst /,//,                      \
                                    $(subst ','"'"',$(1))))))' |       \
                     sed -e 's,\\n,\n,g' -e 's,\\/,\\,g' -e 's,//,/,g')"
endef

ये शैल विकल्प होंगे:

  • प्रत्येक कमांड को प्रिंट करें जैसा कि इसे निष्पादित किया गया है
  • पहले विफल आदेश पर बाहर निकलें
  • एक त्रुटि के रूप में अपरिभाषित खोल चर का उपयोग करें

अन्य दिलचस्प संभावनाएं खुद को सुझाएंगी।


1

मुझे अल्हादी का जवाब सबसे अच्छा लगता है। लेकिन कॉलम स्वरूपण रखने के लिए, एक और बात जोड़ें।

SYNOPSIS := :: Synopsis: Makefile\
| ::\
| :: Usage:\
| ::    make .......... : generates this message\
| ::    make synopsis . : generates this message\
| ::    make clean .... : eliminate unwanted intermediates and targets\
| ::    make all ...... : compile entire system from ground-up\
endef

आउटपुट:

:: Synopsis: Makefile 
:: 
:: Usage: 
:: make .......... : generates this message 
:: make synopsis . : generates this message 
:: make clean .... : eliminate unwanted intermediates and targets 
:: make all ...... : compile entire system from ground-up

एक प्रोग्राम के सिनॉप्सिस का पता लगाना आसान और स्पष्ट होना चाहिए। मैं एक रीडमी और / या मैनपेज में इस स्तर की जानकारी जोड़ने की सलाह दूंगा। जब कोई उपयोगकर्ता चलता है make, तो वे आमतौर पर एक बिल्ड प्रक्रिया शुरू करने की अपेक्षा करते हैं।

1
मैं कई बार चाहता हूं कि बस लक्ष्य बनाने की एक सूची देखें। आपकी टिप्पणी का कोई मतलब नहीं है। उपयोगकर्ताओं को क्या उम्मीद है अप्रासंगिक है अगर यह जानने में उन्हें 3 सेकंड लगते हैं कि क्या करना है, जबकि इस तरह की किसी भी जानकारी के बदले में कभी-कभी घंटों लग सकते हैं।
Xennex81

1
कुछ करने के लिए एक कारण के रूप में अपेक्षाओं का उपयोग करना भी एक परिपत्र तर्क है: क्योंकि लोग इसकी अपेक्षा करते हैं, हमें यह करना चाहिए, और क्योंकि हम ऐसा करते हैं, वे इसकी अपेक्षा करते हैं।
Xennex81

1

पूरी तरह से ओपी से संबंधित नहीं है, लेकिन उम्मीद है कि यह भविष्य में किसी की मदद करेगा। (जैसा कि यह सवाल है जो Google खोजों में सबसे ऊपर आता है)।

मेरे मेकफाइल में, मैं एक फाइल बनाने की सामग्री को पारित करना चाहता था, एक डॉक बिल्ड कमांड को, बहुत अधिक अवरोध के बाद, मैंने इसका फैसला किया:

 base64 encode the contents in the Makefile (so that I could have a single line and pass them as a docker build arg...)
 base64 decode the contents in the Dockerfile (and write them to a file)

नीचे उदाहरण देखें।

nb: मेरे विशेष मामले में, मैं https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/ से उदाहरण का उपयोग करते हुए, छवि निर्माण के दौरान एक ssh कुंजी को पास करना चाहता था। ( का उपयोग करके) एक मल्टी स्टेज डॉकटर एक गिट रेपो को क्लोन करने के लिए बनाता है, फिर बिल्ड के दूसरे चरण में अंतिम छवि से ssh कुंजी छोड़ें)

makefile

...
MY_VAR_ENCODED=$(shell cat /path/to/my/file | base64)

my-build:
    @docker build \
      --build-arg MY_VAR_ENCODED="$(MY_VAR_ENCODED)" \
      --no-cache \
      -t my-docker:build .
...

Dockerfile

...
ARG MY_VAR_ENCODED

RUN mkdir /root/.ssh/  && \
    echo "${MY_VAR_ENCODED}" | base64 -d >  /path/to/my/file/in/container
... 

1

जीएनयू मेक 3.82 और उससे अधिक के साथ, .ONESHELLविकल्प आपका मित्र है जब यह बहु शैल खोल स्निपेट की बात करता है। अन्य उत्तरों से संकेत मिलाते हुए, मुझे मिलता है:

VERSION = 1.2.3
PACKAGE_NAME = foo-bar
DOWNLOAD_URL = $(PACKAGE_NAME).somewhere.net

define nwln

endef

define ANNOUNCE_BODY
Version $(VERSION) of $(PACKAGE_NAME) has been released.

It can be downloaded from $(DOWNLOAD_URL).

etc, etc.
endef

.ONESHELL:

# mind the *leading* <tab> character
version:
    @printf "$(subst $(nwln),\n,$(ANNOUNCE_BODY))"

सुनिश्चित करें, जब आपके संपादक में उपरोक्त उदाहरण को कॉपी और पेस्ट करते हैं, कि किसी भी <tab>अक्षर को संरक्षित किया जाता है, अन्यथा versionलक्ष्य टूट जाएगा!

ध्यान दें कि .ONESHELLMakefile में सभी लक्ष्यों को उनके सभी आदेशों के लिए एकल शेल का उपयोग करने का कारण होगा।


दुर्भाग्य से यह काम नहीं करता है: make version printf "Version 1.2.3 of foo-bar has been released. /bin/sh: 1: Syntax error: Unterminated quoted string make: *** [version] Error 2(GNU 3,81 बनाते हैं)
नीला पड़

@blueyed, मैंने अभी इसे GNU Make 3.82 और GNU bash 4.2.45 (1) -release के साथ परीक्षण किया: यह उम्मीद के मुताबिक काम करता है। इसके अलावा, कृपया @printf ...बयान के सामने, खाली टीएबी के बजाय प्रमुख टीएबी चरित्र की उपस्थिति की जांच करें - ऐसा लगता है कि टीएबी को हमेशा 4 रिक्त स्थान के रूप में प्रस्तुत किया जाता है ...
स्पकाका

ऐसा प्रतीत होता है कि .ONESHELLमेक 3.82 में नया है।
blueyed

btw: टैब के बजाय रिक्त स्थान का उपयोग करते समय त्रुटि होगी *** missing separator. Stop.
blueyed

0

वास्तव में एक उपयोगी उत्तर नहीं है, लेकिन यह इंगित करने के लिए कि 'डिफाइन' एक्स द्वारा दिए गए उत्तर के अनुसार काम नहीं करता है (टिप्पणी में फिट नहीं है):

VERSION=4.3.1
PACKAGE_NAME=foobar
DOWNLOAD_URL=www.foobar.com

define ANNOUNCE_BODY
    Version $(VERSION) of $(PACKAGE_NAME) has been released
    It can be downloaded from $(DOWNLOAD_URL)
    etc, etc
endef

all:
    @echo $(ANNOUNCE_BODY)

यह एक त्रुटि देता है कि कमांड 'इट' नहीं पाया जा सकता है, इसलिए यह कमांड के रूप में ANNOUNCE BODY की दूसरी पंक्ति की व्याख्या करने की कोशिश करता है।


0

इसने मेरे लिए काम किया:

ANNOUNCE_BODY="first line\\nsecond line"

all:
    @echo -e $(ANNOUNCE_BODY)

0

GNU मेकफाइल निम्नलिखित की तरह काम कर सकता है। यह बदसूरत है, और मैं यह नहीं कहूंगा कि आपको इसे करना चाहिए, लेकिन मैं कुछ स्थितियों में करता हूं।

PROFILE = \
\#!/bin/sh.exe\n\
\#\n\
\# A MinGW equivalent for .bash_profile on Linux.  In MinGW/MSYS, the file\n\
\# is actually named .profile, not .bash_profile.\n\
\#\n\
\# Get the aliases and functions\n\
\#\n\
if [ -f \$${HOME}/.bashrc ]\n\
then\n\
  . \$${HOME}/.bashrc\n\
fi\n\
\n\
export CVS_RSH="ssh"\n  
#
.profile:
        echo -e "$(PROFILE)" | sed -e 's/^[ ]//' >.profile

make .profile यदि कोई मौजूद नहीं है तो .profile फ़ाइल बनाता है।

इस समाधान का उपयोग किया गया था जहां एप्लिकेशन केवल POSIX शेल वातावरण में GNU मेकफाइल का उपयोग करेगा। प्रोजेक्ट एक ओपन सोर्स प्रोजेक्ट नहीं है जहां प्लेटफ़ॉर्म संगतता एक समस्या है।

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

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


0

मेरा मानना ​​है कि क्रॉस-प्लेटफ़ॉर्म उपयोग के लिए सबसे सुरक्षित उत्तर प्रति पंक्ति एक प्रतिध्वनि का उपयोग करना होगा:

  ANNOUNCE.txt:
    rm -f $@
    echo "Version $(VERSION) of $(PACKAGE_NAME) has been released" > $@
    echo "" >> $@
    echo "It can be downloaded from $(DOWNLOAD_URL)" >> $@
    echo >> $@
    echo etc, etc" >> $@

यह उपलब्ध प्रतिध्वनि के संस्करण पर कोई भी धारणा बनाने से बचता है।


0

स्ट्रिंग प्रतिस्थापन का उपयोग करें :

VERSION := 1.1.1
PACKAGE_NAME := Foo Bar
DOWNLOAD_URL := https://go.get/some/thing.tar.gz

ANNOUNCE_BODY := Version $(VERSION) of $(PACKAGE_NAME) has been released. \
    | \
    | It can be downloaded from $(DOWNLOAD_URL) \
    | \
    | etc, etc

फिर अपने नुस्खा में, डाल दिया

    @echo $(subst | ,$$'\n',$(ANNOUNCE_BODY))

यह काम करता है क्योंकि मेक (स्पेस पर ध्यान दें) की सभी घटनाओं को प्रतिस्थापित कर रहा है और इसे एक नए चरित्र ( $$'\n') के साथ स्वैप कर रहा है । आप समान शेल-स्क्रिप्ट इनवोकेशन के बारे में कुछ इस तरह सोच सकते हैं:

इससे पहले:

$ echo "Version 1.1.1 of Foo Bar has been released. | | It can be downloaded from https://go.get/some/thing.tar.gz | | etc, etc"

उपरांत:

$ echo "Version 1.1.1 of Foo Bar has been released.
>
> It can be downloaded from https://go.get/some/thing.tar.gz
> 
> etc, etc"

मुझे यकीन नहीं है कि अगर $'\n'यह गैर-पॉसिक्स सिस्टम पर उपलब्ध है, लेकिन अगर आप एक सिंगललाइन कैरेक्टर (यहां तक ​​कि किसी बाहरी फाइल से स्ट्रिंग पढ़कर) तक पहुंच प्राप्त कर सकते हैं, तो अंतर्निहित सिद्धांत समान है।

यदि आपके पास इस तरह के कई संदेश हैं, तो आप मैक्रो का उपयोग करके शोर को कम कर सकते हैं :

print = $(subst | ,$$'\n',$(1))

आप इसे इस तरह से कैसे आमंत्रित करेंगे:

@$(call print,$(ANNOUNCE_BODY))

आशा है कि यह किसी की मदद करता है। =)


मुझे यह सबसे अच्छा लगता है। लेकिन कॉलम स्वरूपण रखने के लिए, एक और बात जोड़ें। `SYNOPSIS: = :: सारांश: मेकफाइल \ | :: \ _ | :: उपयोग: \ | :: मेक ………: इस संदेश को उत्पन्न करता है \ | :: सिनोप्सिस करें। : यह संदेश उत्पन्न करता है \ | :: साफ करें ....: अवांछित मध्यवर्ती और लक्ष्य को खत्म करें \ | :: सभी बनाते हैं ......: ग्राउंड-अप \ एंडिफ़ से पूरी प्रणाली संकलित करें
jlettvin

टिप्पणियाँ कोड की अनुमति नहीं देती हैं। जवाब के रूप में भेजेंगे। मुझे यह सबसे अच्छा लगता है। लेकिन कॉलम स्वरूपण रखने के लिए, एक और बात जोड़ें। `SYNOPSIS: = :: सारांश: मेकफाइल` `| :: `` | :: उपयोग: `` | :: मेक ..........: यह संदेश उत्पन्न करता है `` | :: सिनोप्सिस करें। : यह संदेश उत्पन्न करता है `` | :: साफ करें ....: अवांछित मध्यवर्ती और लक्ष्यों को समाप्त करें `` | :: सभी बनाते हैं ......: ग्राउंड-अप `एंडिफ` से पूरी प्रणाली संकलित करें
jlettvin

@jlettvin आपके जवाब पर मेरी प्रतिक्रिया देखें। एक प्रोग्राम का सिनॉप्सिस निश्चित रूप से मेकफाइल के अंदर नहीं होना चाहिए , विशेष रूप से डिफ़ॉल्ट कार्य के रूप में नहीं।

0

एक विकल्प के रूप में आप प्रिंटफ कमांड का उपयोग कर सकते हैं। यह कम सुविधाओं के साथ OSX या अन्य प्लेटफार्मों पर मददगार है।

बस एक बहु-संदेश का उत्पादन करने के लिए:

all:
        @printf '%s\n' \
            'Version $(VERSION) has been released' \
            '' \
            'You can download from URL $(URL)'

यदि आप दूसरे प्रोग्राम में स्ट्रिंग को एक arg के रूप में पास करने की कोशिश कर रहे हैं, तो आप ऐसा कर सकते हैं:

all:
        /some/command "`printf '%s\n' 'Version $(VERSION) has been released' '' 'You can download from URL $(URL)'`"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.