3

I am trying to figure out how to use env variables in makefiles. I have (kind of) specific use-case where I need to do these steps:

  1. run command1
  2. assign output form command2 to env variable
  3. run command3 which read env variable assigned in step 2

This is the makefile implementing the steps described above. However, when I run it prints an empty variable. What am I doing wrong? When I run these commands in my bash it works just fine)🤔

test:
    @bash -c "\
        echo 'need to run some program before assigning env variable';\
        export TEST="$(date)";\
        echo 'printing env';\
        echo ${TEST};\
        "
2
  • Inside a Makefile you need to double every dollar sign that you want to be given to the shell.
    – icarus
    Sep 20, 2021 at 22:05
  • That doesn't work either.
    – Joozty
    Sep 20, 2021 at 22:07

1 Answer 1

3

Dollar signs are used by make, so you need to escape them if you want them passed to the shell. You do this by doubling them.

test:
        @bash -c "\
        echo 'need to run some program before assigning env variable';\
        echo 'The make CC variable is set to :${CC}:';\
        export TEST=\"\$$(date)\";\
        echo 'printing env';\
        echo \$${TEST};\
        "

testwithout:
        @echo 'need to run some program before assigning env variable';\
        echo 'The make CC variable is set to :${CC}:';\
        export TEST="$$(date)";\
        echo 'printing env';\
        echo $${TEST};

The other problems are caused by interpreting the string twice. make takes the recipie, converts the sequence backslash newline, and gives the result to the shell to execute. As you are using double quotes for your bash -c " .... " this results in the shell expanding the dollar signs, so you end up with `bash -c "echo 'need ...' ;export TEST=Mon Sep...; echo ;". Adding some backslash characters protects the dollar signs and the interior double quotes.

There is probably no need to use the bash -c. as shown in the testwithout target. You will still need to construct the command as one line. Gnu make has a .ONESHELL facility to use a single shell to execute a recipe rather than one shell per logical line, which allows you to avoid the contortions.

3
  • sadly it doesn't work for me... When I run make test I see output only from the first two echos
    – Joozty
    Sep 20, 2021 at 22:17
  • Thanks.Also double quotes needs to be escaped. `export TEST=\"\$$(date)\";`. Apart from that it works just fine :)
    – Joozty
    Sep 21, 2021 at 6:54
  • expanded answer and added escaping of the double quotes.
    – icarus
    Sep 21, 2021 at 9:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .