makefilegnu-makerecipe

Defining makefile variable at build time and using it in foreach


I am defining a makefile variable by parsing a json file using jq.

define variable
    $(eval objects := $(shell jq -c '.abc.values[]' config.json))
endef
target_a:
    $(variable)
    @echo "from target-a: $(objects)"
target_b: $(foreach X, $(objects), stage_$(X))

I am getting an output that's the same as the json list:

from target-a: first second

This means the variable is getting initialized correctly but the foreach is not triggering any stage_% targets. Why is that?


Solution

  • Basically your makefile cannot work. Make proceeds in two distinct steps: first all makefiles are entirely parsed and an internal graph of the targets and prerequisites is created. Second make walks that graph and invokes all the recipes. All prerequisites must be defined during the first step. All recipes are only expanded during the second step.

    Here, you've added the expansion of the objects variable into the recipe for target_a, so that will not happen until the second step, IF make decides to rebuild the target target_a because it's out of date. But, the definition of the prerequisites of target_b has already happened a long time ago, when make was parsing the makefile in the first step.

    You can do this in your example and it will work:

    objects := $(shell jq -c '.abc.values[]' config.json)
    
    target_a:
            @echo "from target-a: $(objects)"
    
    target_b: $(foreach X, $(objects), stage_$(X))
    

    Here, objects is expanded as the makefile is parsed and so it will have a value before target_b is expanded.

    Maybe there's some reason you can't do it this way, but if so you've simplified your example too much for us to help.