Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile assign command output to variable

Tags:

I have a script that compresses my css files and outputs the filename of the output file.
I'm trying to build a makefile to automatize the process:

all:     @echo "Compiling CSS"     CSS_OUTPUT=$(shell php minify_css.php )     echo $(CSS_OUTPUT) 

I'm trying to store the output filename in CSS_OUTPUT variable, but I'm doing something wrong, as this whole makefile just prints:

$ make abcdefg.css Compiling CSS CSS_OUTPUT= echo  

So output is not assigned to CSS_OUTPUT. Also, why is php output printed before the @echo "Compiling CSS"?

I've tried with this:

all:     @echo "Compiling CSS"     CSS_OUTPUT=$(shell echo php minify_css.php )     echo $(CSS_OUTPUT) 

But it only gets worse:

$ make Compiling CSS CSS_OUTPUT=php minify_css.php ./minify_css.php: line 1: ?php: No such file or directory ./minify_css.php: line 3: syntax error near unexpected token `dirname' ./minify_css.php: line 3: `require_once( dirname(__FILE__) . DIRECTORY_SEPARATOR . 'maintenance.php' );' make: *** [css] Error 2 

Edit Following the answer provided in comments, which suggests using eval:

@echo "Compiling CSS" $(eval CSS_OUTPUT:=$(shell php minify_css.php)) echo ${CSS_OUTPUT} 

Outputs:

make: *** No targets specified and no makefile found.  Stop. 
like image 685
Pherrymason Avatar asked Jan 31 '12 15:01

Pherrymason


People also ask

How do you assign the output of a command to a variable?

To store the output of a command in a variable, you can use the shell command substitution feature in the forms below: variable_name=$(command) variable_name=$(command [option ...] arg1 arg2 ...) OR variable_name='command' variable_name='command [option ...]

What is := in makefile?

Expanded assignment = defines a recursively-expanded variable. := defines a simply-expanded variable.

What is a makefile target?

A simple makefile consists of "rules" with the following shape: target ... : dependencies ... command ... ... A target is usually the name of a file that is generated by a program; examples of targets are executable or object files.


1 Answers

Make works in two phases. First, it reads in the makefile, evaluates variables and builds a dependency graph. Make functions also get evaluated during this phase. In the second phase it executes the necessary recipes to update the main target. This means the $(shell ...) function call gets expanded during the first phase, before any recipe is run. The output of the command is substituted for the shell function call, but I suspect the output of the php command doesn't go to STDOUT, so instead of ending up with CSS_OUTPUT=abcdefg.css (which would be what you want), abcdefg.css is echoed to the screen and the result of the shell function is empty.

Next the recipe is executed, but when this is done, each line is run in a separate shell instance, so the commands on different lines in a recipe have no access to shell variables set on another line (which would be useless in this case anyway, because of the previous issue). One way to counter this is to glue the lines together by ending them with a semicolon and a backslash. Now they get executed as one line in a single shell instance.

Another problem is that in the last line of the recipe, you don't refer to a shell variable (which is what CSS_OUTPUT is), but to a makefile variable that has never been set.

Is there any reason why you don't just do it this way:

all:     @echo "Compiling CSS"     php minify_css.php 
like image 200
eriktous Avatar answered Oct 18 '22 02:10

eriktous