'How do I get a variable into a $(shell) command in a makefile?

❯ make --version
GNU Make 3.81
❯ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)

How can I pass a variable from inside a for loop to $(shell)? I can access the var outside of $(shell) but I can't figure out how to pass it in:

A_LIST:= one two

.PHONY: loop
loop:
    @for iii in $(A_LIST) ; do \
        echo inside recipe loop with sh command: $$iii ; \
        export SAVED_OUTPUT=$(shell echo $$iii) ; \
        echo $$SAVED_OUTPUT ; \
    done

This is the output I get:

inside recipe loop with sh command: one
<blank line here>
inside recipe loop with sh command: two
<blank line here>

The last line in the loop echo $$SAVED_OUTPUT should output one and two because it is echoing the var and storing it in another var. But it is a blank line. I suspect it's because it's looking for an env var $iii but that doesn't exist- so how to I pass the value of iii into the shell?

Here is a bad way of doing this I don't like. I don't want to have to write a local file just to access a variable like this:

.PHONY: loop
loop:
    @for iii in $(A_LIST) ; do \
        echo inside recipe loop with sh command: $$iii ; \
        echo $$iii > scratch ; \
        export SAVED_OUTPUT=$(shell echo $$(cat scratch)) ; \
        echo $$SAVED_OUTPUT ; \
    done


Solution 1:[1]

The for loop is already being executed by a shell - in this case, there's no reason to bring $(shell ...) into it too. Just use normal $() shell command substitution syntax (Doubling up the $ to make make happy, like with the variable names):

A_LIST:= one two

.PHONY: loop
loop:
    @for iii in $(A_LIST) ; do \
        echo "inside recipe loop with sh command: $$iii" ; \
        SAVED_OUTPUT="$$(somecommand "$$iii")" ; \
        echo "$$SAVED_OUTPUT" ; \
    done

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1