Search code examples
makefile

How do I print a multiline make variable directly into a pipeline?


Consider a makefile with a multiline item:

define ITEM
line $$ONE
line $$TWO
endef

item:
  echo '$(ITEM)' | ... > $@

The problem is that as ITEM gets complex, I run the risk of getting quote errors and other problems when I echo the item.

I could also run with an export:

export ITEM
item:
  print "%s\n" '$${ITEM}' | ...

But I am not sure that is going to have the same bugs.

Is there some make function that will inject the contents of a variable directly into the shell, as if it were sent to /dev/stdin?

# e.g. something like:
$(info $ITEM) | ...

I understand that I can write the value directly to a file, which I'll be able to process via shell. But being able to write it directly to a pipeline would short circuit that.

  • this will have a series of commands, or introduce requirements like sponge
  • it may also cause me to have to shift from simple envsubst to heavier things like sed to allow in-place modification (to avoid installing sponge)

I also understand I can export the value to all subshells:

  • this may be problematic if my extension is included in a recursive make project, or a make project with a large amount of export-overhead (e.g. parameter?=vars that default to env values introduce a large amount of overhead when .SECONDEXPANSION is enabled)
  • in particular, exporting too much can break the performance of zsh tab completion for make, which is a soft requirement for mac users

But I have no proof exporting and echo "$$ITEM" or print("%s/\n") "$$ITEM" will have proper escapes. So I'll have to test it.


What is not "a way", but the intended best practice for doing this?

If the answer is: use $(file ..), and modify the file in place from there, then so be it; just want to make sure that is optimal.


Solution

  • The usual solution for a complex variable expansion is to just write an external shell file. Or a script (perl/python/awk). Or even a special compiled tool to produce something which is needed for actual compilation. It is not a must that everything would be part of makefile.

    Rule of thumb here is: "if you struggling with variables, dollar signs, and quotation marks - maybe it is time to think of external script?"