Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Insert a new-line in a Makefile $(foreach ) loop

I'm compiling a large list of files in a Makefile.

my.list : ${deps}
    rm -f $@
    $(foreach F,$^,echo "${F}" >> $@;)

but ${deps} can be large and the generated command-line could be too large for one SHELL call. Is it possible to replace ';' by a newline '\n' ?

like image 921
Pierre Avatar asked Apr 15 '15 13:04

Pierre


3 Answers

You can define a variable that expands to a newline like so:

define NEWLINE

endef

Now you can use $(NEWLINE) to expand to a newline.

This won't change anything though, the foreach will still generate a single command with embedded newlines between the statements, rather than a single command with ; between the statements.

like image 162
Jonathan Wakely Avatar answered Sep 27 '22 17:09

Jonathan Wakely


As already mentioned in Jonathan Wakely's answer, the straightforward answer is

define newline


endef

Interestingly enough, for all chars except newline there is an easier way to get non-printable characters into variables with some help from the shell, e.g.:

tab := $(shell printf '\011')

It won't work here, though, because the builtin shell function replaces all newlines by spaces.

The version above is still a bit fragile though, in particular when combining with automake which will silently remove the second consecutive newline from the input file, turning newline into an empty variable. To force it to keep the newline, we can extend the snippet:

blank :=
define newline

$(blank)
endef

Finally, to actually get a separate shell command for each dependency, you need to run the generated string through eval:

define generate-rule =
my.list : $(1)
    rm -f $$@
    $(foreach F,$$^,$(newline)$(tab)echo "${F}" >> $@)

endef

$(eval $(call generate-rule,$(deps)))
like image 45
Benno Avatar answered Sep 27 '22 17:09

Benno


Possibly the most straight-forward answer is to use:

@printf "\n"

You can also use this, as I commonly do, to show a description when each new make target executes. An example target:

.PHONY: clean-version
clean-version:    ## Reset version back to committed version number
    @printf "\n## Reset version to last committed version number ##\n\n"; \
    $(GIT) checkout $(VERSION_FILE);
like image 41
t-stark Avatar answered Sep 27 '22 17:09

t-stark