Search code examples
shellmakefilegnu-make

Is it possible to compare a variable with multiple values in if statement of a make target?


I am trying to run a make target where a particular value is passed on CLI, but this value should be compared with 2 or more possible values, like the value being passed on cli should be equal to any one from the pre existing list, so that the condition becomes true and if block gets executed!

.PHONY:plan-infra
plan-infra: configure  ## Plan Infra
    @if [ "${infra_module_path}" = "emr" or "gmr" ]; then\
        echo "test";\
    fi


$ make plan-infra -e infra_module_path=emr

So if the variable "infra_module_path" is either "emr" or "gmr" the if block should get executed!


Solution

  • The filter GNU make function is your friend:

    .PHONY:plan-infra
    
    MATCH := $(filter emr gmr,$(infra_module_path))
    
    plan-infra: configure  ## Plan Infra
        @if [ -n "$(MATCH)" ]; then\
            echo "test";\
        fi
    

    But note that this will also match if you pass values containing several space-separated tokens with at least one matching, e.g.,

    make plan-infra -e infra_module_path="emr foo bar"
    

    As noted by MadScientist, filter-out is a bit better because it returns the empty string when the string contains only the filtered tokens; it is thus more accurate:

    .PHONY:plan-infra
    
    MATCH := $(filter-out emr gmr,$(infra_module_path))
    
    plan-infra: configure  ## Plan Infra
        @if [ -z "$(MATCH)" ]; then\
            echo "test";\
        fi
    

    But it is still not 100% accurate:

    make plan-infra -e infra_module_path="emr qmr"
    

    still matches. If your really need exact match, while it is doable with make functions (at least in your case), as noted by Charles Duffy and MadScientist, it would be better to use shell constructs. Just in case you absolutely need exact match using make functions:

    .PHONY:plan-infra
    
    ifeq ($(words $(infra_module_path)),1)
    MATCH := $(filter-out emr gmr,$(infra_module_path))
    else
    MATCH := no
    endif
    
    plan-infra: configure  ## Plan Infra
        @if [ -z "$(MATCH)" ]; then\
            echo "test";\
        fi