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

后端 未结 19 1928
借酒劲吻你
借酒劲吻你 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:29

    Not completely related to the OP, but hopefully this will help someone in future. (as this question is the one that comes up most in google searches).

    In my Makefile, I wanted to pass the contents of a file, to a docker build command, after much consternation, I decided to:

     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)
    

    see example below.

    nb: In my particular case, I wanted to pass an ssh key, during the image build, using the example from https://vsupalov.com/build-docker-image-clone-private-repo-ssh-key/ (using a multi stage docker build to clone a git repo, then drop the ssh key from the final image in the 2nd stage of the build)

    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
    ... 
    
    0 讨论(0)
  • 2020-11-28 20:29

    Not really a helpful answer, but just to indicate that 'define' does not work as answered by Ax (did not fit in a comment):

    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)
    

    It gives an error that the command 'It' cannot be found, so it tries to interpret the second line of ANNOUNCE BODY as a command.

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

    Assuming you only want to print the content of your variable on standard output, there is another solution :

    do-echo:
        $(info $(YOUR_MULTILINE_VAR))
    
    0 讨论(0)
  • 2020-11-28 20:31

    As an alternative you can use the printf command. This is helpful on OSX or other platforms with less features.

    To simply output a multiline message:

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

    If you are trying to pass the string as an arg to another program, you can do so like this:

    all:
            /some/command "`printf '%s\n' 'Version $(VERSION) has been released' '' 'You can download from URL $(URL)'`"
    
    0 讨论(0)
  • 2020-11-28 20:33

    GNU Makefile can do things like the following. It is ugly, and I won't say you should do it, but I do in certain situations.

    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 creates a .profile file if one does not exist.

    This solution was used where the application will only use GNU Makefile in a POSIX shell environment. The project is not an open source project where platform compatibility is an issue.

    The goal was to create a Makefile that facilitates both setup and use of a particular kind of workspace. The Makefile brings along with it various simple resources without requiring things like another special archive, etc. It is, in a sense, a shell archive. A procedure can then say things like drop this Makefile in the folder to work in. Set up your workspace enter make workspace, then to do blah, enter make blah, etc.

    What can get tricky is figuring out what to shell quote. The above does the job and is close to the idea of specifying a here document in the Makefile. Whether it is a good idea for general use is a whole other issue.

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

    I believe the safest answer for cross-platform use would be to use one echo per line:

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

    This avoids making any assumptions of on the version of echo available.

    0 讨论(0)
提交回复
热议问题