Pergunta

I understand that this is a simple question but i am unable to find the reason/solution. I have defined a simple shell function in Makefile that is doing as follows,

define my_function
    my_var="Hello";
    echo $(my_var);
    echo Recvd arg = $(1);
endef

Please note that this is defined inside a makefile and I am using in one of my rule,

 $(obj_dir)/%.o: $(src_base)/%.cpp 
 $(q)$(CXX) $(CXXFLAGS) -o $@ 
 $(call my_function, $@) 

But the local variable my_var never gets assigned. I have tried many things using eval, set and export but nothing seems to be assigning value to variable in the function. And echo $(my_var) will just print nothing. This works fine in shell script but when used in Makefile, it causes this issue.

Please help me sort this out. Help will be highly appreciated.

Foi útil?

Solução

Make will invoke every logical line of a recipe in a separate shell. So for something like:

foo:
        echo line1
        echo line2

this starts two different shells, one to run the first echo and another to run the second (in reality make has some performance enhancements so that it avoids starting a shell if the command is "simple enough", but the behavior is the same either way).

So if you write a variable in one line then use it in another line, the value will be lost when the shell exits:

foo:
        foo=bar
        echo $$foo

prints nothing. In order to use multiple physical lines but a single logical line you must end each physical line with a backslash/newline combination: make will collect them and send them to a single shell:

foo:
        foo=bar; \
        echo $$foo

will print "bar".

This holds true even within multi-line variable assignments. Also, you must use $$ (as I do above) when you want to refer to a shell variable. Using a single $ will refer to the make variable by that name. And the shell variable referencing doesn't support parentheses (but you can use curly braces if you want). So you must write:

define my_function
    my_var="Hello"; \
    echo $$my_var; \
    echo Recvd arg = $(1);
endef

Outras dicas

I have nothing to add to MadScientist's answer but this: If you don't mind slightly longer lines, you can also place several shell commands on one line separated by semicolons:

define my_function
    my_var="Hello"; echo $$my_var; echo Recvd arg = $(1)
endef
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top