Is it possible to create a multi-line string variable in a Makefile

后端 未结 19 1930
借酒劲吻你
借酒劲吻你 2020-11-28 20:27

I want to create a makefile variable that is a multi-line string (e.g. the body of an email release announcement). something like

ANNOUNCE_BODY=\"
Version $         


        
相关标签:
19条回答
  • 2020-11-28 20:39

    Yes. You escape the newlines with \:

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

    update

    Ah, you want the newlines? Then no, I don't think there's any way in vanilla Make. However, you can always use a here-document in the command part

    [This does not work, see comment from MadScientist]

    foo:
        echo <<EOF
        Here is a multiple line text
        with embedded newlines.
        EOF
    
    0 讨论(0)
  • 2020-11-28 20:39

    It worked for me:

    ANNOUNCE_BODY="first line\\nsecond line"
    
    all:
        @echo -e $(ANNOUNCE_BODY)
    
    0 讨论(0)
  • 2020-11-28 20:42

    Another approach to 'getting your multi-line variable back out of the makefile' (noted by Eric Melski as 'the tricky part'), is to plan to use the subst function to replace the newlines introduced with define in your multi-line string with \n. Then use -e with echo to interpret them. You may need to set the .SHELL=bash to get an echo that does this.

    An advantage of this approach is that you also put other such escape characters into your text and have them respected.

    This sort of synthesizes all the approaches mentioned so far...

    You wind up with:

    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})'
    

    Note the single quotes on the final echo are crucial.

    0 讨论(0)
  • 2020-11-28 20:43

    Yes, you can use the define keyword to declare a multi-line variable, like this:

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

    The tricky part is getting your multi-line variable back out of the makefile. If you just do the obvious thing of using "echo $(ANNOUNCE_BODY)", you'll see the result that others have posted here -- the shell tries to handle the second and subsequent lines of the variable as commands themselves.

    However, you can export the variable value as-is to the shell as an environment variable, and then reference it from the shell as an environment variable (NOT a make variable). For example:

    export ANNOUNCE_BODY
    all:
        @echo "$$ANNOUNCE_BODY"
    

    Note the use of $$ANNOUNCE_BODY, indicating a shell environment variable reference, rather than $(ANNOUNCE_BODY), which would be a regular make variable reference. Also be sure to use quotes around your variable reference, to make sure that the newlines aren't interpreted by the shell itself.

    Of course, this particular trick may be platform and shell sensitive. I tested it on Ubuntu Linux with GNU bash 3.2.13; YMMV.

    0 讨论(0)
  • 2020-11-28 20:43

    This doesn't give a here document, but it does display a multi-line message in a way that's suitable for pipes.

    =====

    MSG = this is a\\n\
    multi-line\\n\
    message
    
    method1:
         @$(SHELL) -c "echo '$(MSG)'" | sed -e 's/^ //'
    

    =====

    You can also use Gnu's callable macros:

    =====

    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 "---"
    

    =====

    Here's the output:

    =====

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

    =====

    0 讨论(0)
  • 2020-11-28 20:43

    Why don't you make use of the \n character in your string to define the end-of-line? Also add the extra backslash to add it over multiple lines.

    ANNOUNCE_BODY=" \n\
    Version $(VERSION) of $(PACKAGE_NAME) has been released \n\
    \n\
    It can be downloaded from $(DOWNLOAD_URL) \n\
    \n\
    etc, etc"
    
    0 讨论(0)
提交回复
热议问题