makefileconditional-statementsgnu-makewhitespace

"ifeq" conditional syntax in makefile


As the conditional-directive ifeq is frequently used to compare word(s) expanded from variables, which often contains white-space, we may want and, in fact need, for Make to strip any leading or trailing white-space.

In fact, you may have an opposite view, i.e., Make should keep verbatim all the arguments to an ifeq conditional. Because the user may have had those whitespaces as part of the test, with the intention for those whitespaces to play a deciding factor, when evaluating this ifeq directive, as true or false.

I can not decide, which of them is more correct. In fact, I'm not alone! Make itself cannot decide, which of them is correct.

So, it may or may not strip leading or trailing whitespace. In fact, sometimes it will strip only leading whitespace. Not disappointing, Make will sometimes strip only trailing whitespace.

Showcasing my Observations

Of course, there are too many cases to check, so I will do only a few of them.

Test case 1

ifeq ( a, a)
all::
    echo 'true'
else
all::
    echo 'false'
endif

Executing, I get:

$ make -r
echo 'false'
false

Test case 2

ifeq (a ,a )
all::
    echo 'true'
else
all::
    echo 'false'
endif

Executing, I get:

$ make -r
echo 'false'
false

Test case 3

ifeq ( a , a )
all::
    echo 'true'
else
all::
    echo 'false'
endif

Executing, I get:

$ make -r
echo 'false'
false

Test case 4

ifeq (a , a)
all::
    echo 'true'
else
all::
    echo 'false'
endif

Executing, I get:

$ make -r
echo 'true'
true

Test case 5

ifeq (a, a)
all::
    echo 'true'
else
all::
    echo 'false'
endif

Executing, I get:

$ make -r
echo 'true'
true

Summary

Summing up these cases, we have:

# Both have only leading whitespace.
ifeq( a, a)    as: false.

# Both have only trailing whitespace.
ifeq(a ,a )    as: false.

# Both have trailing AND trailing whitespace.
ifeq( a , a )  as: false.

# Left-hand side has trailing, and right-hand side has leading whitespace.
ifeq(a , a)    as: true.

# Left-hand side has NO whitespace, and right-hand side has leading whitespace.
ifeq(a, a)     as: true.

So, this methodology, that make uses to evaluate the truthfulness of an ifeq conditional directive, is definitely turning it into:

Do we agree?


Solution

  • You should read this:

    Commas and unmatched parentheses or braces cannot appear in the text of an argument as written; leading spaces cannot appear in the text of the first argument as written. These characters can be put into the argument value by variable substitution. First define variables comma and space whose values are isolated comma and space characters, then substitute these variables where such characters are wanted, like this:

    comma:= ,
    empty:=
    space:= $(empty) $(empty)
    foo:= a b c
    bar:= $(subst $(space),$(comma),$(foo))
    # bar is now ‘a,b,c’.
    

    You should also use the strip function when in doubt.


    Here an example Makefile:

    empty:=
    space:= $(empty) $(empty)
    
    x := $(space)a$(space)
    y := $(space)a$(space)
    
    ifeq ($(x),$(y))
    all::
            @echo 'regular: true'
    else
    all::
            @echo 'regular: false'
    endif
    
    ifeq ($(strip $(x)),$(strip $(y)))
    all::
            @echo 'strip:   true'
    else
    all::
            @echo 'strip:   false'
    endif
    

    And the result:

    1:

    x = $(space)a
    y = $(space)a
    
    regular: true
    strip:   true
    

    2:

    x = a$(space)
    y = a$(space)
    
    regular: true
    strip:   true
    

    3:

    x = $(space)a$(space)
    y = $(space)a$(space)
    
    regular: true
    strip:   true
    

    4:

    x = a$(space)
    y = $(space)a
    
    regular: false
    strip:   true
    

    4:

    x = a
    y = $(space)a
    
    regular: false
    strip:   true