Search code examples
bashmakefileconditional-compilation

Ifdef conditional unexpected behavior


I have a Makefile with command like this:

#Makefile
    hello:
        echo 'hello'
        echo $(TAG)
        ifdef TAG
              $(warning MYWARNING)
        else
              $(error MYERROR)
        endif

I use it like:

# make TAG='1.0' hello

I expect that command performs echo 'hello', then echo $(TAG) and $(warning MYWARNING) but I get:

Makefile:17: MYWARNING
Makefile:19: *** MYERROR.  Stop.

What is wrong?


Solution

  • Let's try some simpler cases(*).

    hello:
        echo hello
        $(error MYERROR)
    

    This produces:

    Makefile:3: *** MYERROR.  Stop.
    

    Notice that the error blocks the echo, even thought it comes afterward.

    Now let's try something silly:

    hello:
        ifdef TAG
    

    The result is:

    ifdef TAG
    make: ifdef: No such file or directory
    

    "ifdef TAG", interpreted as a shell command, makes no sense. And it is interpreted as a shell command because it's in a recipe and preceded by a TAB.

    Now let's combine them:

    hello:
        ifdef TAG
        $(error MYERROR)
    

    The result is Makefile:3: *** MYERROR. Stop. So the error obscures the fact that the ifdef... was incorrect.

    Do we want a shell conditional, or a Make conditional? If we want to Make to act on it (with error or warning), then it must be a Make conditional, so we must not preceded it with a TAB:

    hello:
    ifdef TAG
        $(warning MYWARNING)
    else
        $(error MYERROR)
    endif
    

    This works as intended.

    (*) as you ought to have tried before you posted.