Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to make $(eval $(shell ...)) work in GNU make

Tags:

shell

makefile

make syntax is newline-delimited, but $(shell ...) replaces newlines with whitespace. So what's the least ugly way to do

$(eval $(shell program-that-emits-makefile-fragment))

which doesn't work the way one might like.

like image 602
Bryan Avatar asked Aug 19 '10 17:08

Bryan


People also ask

How do I use eval in makefile?

In the manual: The eval function is very special: it allows you to define new makefile constructs that are not constant; which are the result of evaluating other variables and functions. The argument to the eval function is expanded, then the results of that expansion are parsed as makefile syntax.

How do I run a shell command in makefile?

$(shell) $(shell) is a special function in gmake that runs an external command and captures the output for use in the makefile. For example, you could get the current working directory like this: CWD=$(shell pwd) all: @echo This makefile lives in $(CWD).

What is $( make in makefile?

And in your scenario, $MAKE is used in commands part (recipe) of makefile. It means whenever there is a change in dependency, make executes the command make --no-print-directory post-build in whichever directory you are on.

How do I use IFEQ in makefile?

The ifeq directive begins the conditional, and specifies the condition. It contains two arguments, separated by a comma and surrounded by parentheses. Variable substitution is performed on both arguments and then they are compared.


2 Answers

This will probably do for what you have in mind:

makefile_fragment:
  program-that-emits-makefile-fragment > $@

include makefile_fragment

Is that enough? There are additional tricks you can use if you need them, such as having the rule add context around what the program produces, or piping the output through sed to glom it into one line, then parsing it out with backslashes.

like image 198
Beta Avatar answered Sep 24 '22 00:09

Beta


The issue has already been reported to the GNU make maintainers:

http://savannah.gnu.org/bugs/?28230

It was closed with the following comment:

As Philip mentions, this is the intended/documented behavior.
I recommend using "include" rather than eval; have your script write out a file, then include that file.

ADDED: There's a workaround! Here's a sample GNUmakefile (replace 8 spaces by tabs; yes, there are two empty lines after define newline):

define newline


endef

$(eval $(subst #,$(newline),$(shell { echo 'war:'; echo '        echo "not love?"'; echo '        echo "Give peace a chance!"'; } | tr '\n' '#')))

More generally, that's $(eval $(subst #,$(newline),$(shell myscript | tr '\n' '#')))

You have to pick a character that won't appear in the output of the script; # seems a good candidate.

like image 39
Gilles 'SO- stop being evil' Avatar answered Sep 26 '22 00:09

Gilles 'SO- stop being evil'