Heredoc in a Makefile?

前端 未结 7 1064
半阙折子戏
半阙折子戏 2020-12-25 12:36

Is this possible at all and how?

Update: I need this because I create a file both from dynamic and static data.

Use case:

7条回答
  •  太阳男子
    2020-12-25 13:24

    Yes, you can. As others note, you probably shouldn't, but you can. Ash's answer has one solution involving define commands, but that is combersome and can make it tricky to get variables expanded to the right values. Another trick is to use the .ONESHELL: special target.

    Sometimes you would prefer that all the lines in the recipe be passed to a single invocation of the shell. There are generally two situations where this is useful: first, it can improve performance in makefiles where recipes consist of many command lines, by avoiding extra processes. Second, you might want newlines to be included in your recipe command (for example perhaps you are using a very different interpreter as your SHELL). If the .ONESHELL special target appears anywhere in the makefile then all recipe lines for each target will be provided to a single invocation of the shell. Newlines between recipe lines will be preserved.

    A couple words of warning:

    • This will affect how all recipes in your Makefile work.
    • Line prefix operators such as - or @ to suppress output or ignore errors only work on the first line of all recipes and take effect for all lines following.
    • Some old versions or GNU Make (such as that running by default on Travis's CI system even in the new containers) may ignore this directive leading to strange bugs and gotchas. Make sure you know your target environments.

    With that out of the way, here's how it might look to generate a markdown file:

    SHELL = bash
    .ONESHELL:
    MYVAR = "Some Title"
    
    file.md:
        cat <<- EOF > $@
            $(MYVAR)
            ========
    
            This stuff will all be written to the target file. Be sure
            to escape dollar-signs and backslashes as Make will be scanning
            this text for variable replacements before bash scans it for its
            own strings.
    
            Otherwise formatting is just as in any other bash heredoc. Note
            I used the <<- operator which allows for indentation. This markdown
            file will not have whitespace at the start of lines.
    
            Here is a programmatic way to generate a markdwon list all PDF files
            in the current directory:
    
            `find -maxdepth 1 -name '*.pdf' -exec echo " + {}" \;`
        EOF
    

    Note one additional gotcha is that Make skips blank lines. If having a blank line in the content of your heredoc is important, you need to make sure to indent that line with the appropriate level of whitespace to match the heredoc or Make will eat it and not even pass it to cat!

提交回复
热议问题