Search code examples
bashmakefileescapinggnu-makequoting

Dollar in conditional variable assignment operator in Makefile


Is it possible to pass value with single dollar from shell to Makefile, or I it is only way to put double dollar in bash and then to call make?

Makefile is:

HASH ?= $$6$$salt$$val

.PHONY: tst
tst:
        echo '$(HASH)'

Command to run:

> make HASH='$6$salt$val'
echo 'altal'
altal

If I use double quotes, all is fine:

> make HASH='$$6$$salt$$val'
echo '$6$salt$val'
$6$salt$val

But is it possible do not make substitution $ to $$ in bash?


Solution

  • How about writing the initialisation within the file identical to the one coming from the command line? The below script demonstrates how to rewrite a variable with the override directive:

    quote-one-level = $(eval override $1=$(subst $,$$$$,$(value $1)))
    
    var-info = $(info $1=$(value $1) flavour=$(flavor $1) origin=$(origin $1))
    
    A ?= $abc
    
    $(call var-info,A)
    $(call quote-one-level,A)
    $(call var-info,A)
    
    $(call var-info,B)
    $(call quote-one-level,B)
    $(call var-info,B)
    
    export A
    export B
    
    all:
        @echo A = '$(A)'
        @echo B = '$(B)'
    ifeq ($(MAKELEVEL),0)
        $(MAKE)
    endif
    

    Inflating one $ to $$$$ (and not just $$) is necessary because the eval command literally generates make code, thereby obviously reducing the quoting level by one. Resulting output:

    $ make B='$abc'
    A=$abc flavour=recursive origin=file
    A=$$abc flavour=recursive origin=override
    B=$abc flavour=recursive origin=command line
    B=$$abc flavour=recursive origin=override
    A = $abc
    B = $abc
    make
    make[1]: Entering directory 
    A=$abc flavour=recursive origin=environment
    A=$$abc flavour=recursive origin=override
    B=$abc flavour=recursive origin=command line
    B=$$abc flavour=recursive origin=override
    A = $abc
    B = $abc
    make[1]: Leaving directory