bug-make
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [bug #59956] Recipes inside conditionals can break the parser


From: Edward Welbourne
Subject: Re: [bug #59956] Recipes inside conditionals can break the parser
Date: Thu, 28 Jan 2021 13:00:48 +0000

> Consider the following example:

> ifeq (1,0)
> test:
>         @if [ "asd" == "123" ]; then
>                 echo "true"
>         else
>                 echo "false"
>         fi
> endif

> The *else* recipe at line 5 is treated as part of the *ifeq (1,0)*
> conditional thus making the next recipe line fail because there is no
> target before it:

> Makefile:6: *** recipe commences before first target.  Stop.

... and this could all too easily go *unreported* if this conditional
target-and-rule appeared just after some other.

I expected it to lead to the resulting rule getting a syntax error, but
am now baffled to find, by experiment, that (with suitable blocks of
spaces replaced by tabs, of course, if my mailer has substituted spaces
for tabs, which it probably has)

.ONESHELL:

fluff:
        @echo fluff

ifeq (1,0)
test:
        @if [ "asd" == "123" ]; then
                echo "true"
        else
                echo "false"
        fi
endif

        echo puff

doesn't provoke an error; make fluff simply echoes fluff then puff,
without echoing false or complaining of a syntax error due to the fi.
Removing the tab before else does get me the expected syntax error, so I
think something more complicated is going on here than simply the else
being recognised as belonging to the ifeq.

Can anyone explain that ?

> _I know the recipe does not make any sense without .ONESHELL, but it
> should not matter. Maybe the user has a shell with a valid "else"
> command.

That has proven a fascinating topic, thanks for bringing it up.
I particularly liked Paul's example of how adding a .PHONY rule could
dramatically change the meaning of a Makefile that uses tabs to indent
things not intended as rules.  One more reason to *only* use tabs in
rules.

The error message isn't much help, even when you do get it, but once
you've worked out what the problem there is at least a straightforward
work-around for the case above; just (regardless of .ONESHELL being set)
backslash-escape relevant newlines (and add semicolons before them,
where needed),

ifeq (1,0)
test:
        @if [ "asd" == "123" ]; then \
                echo "true"; \
        else \
                echo "false"; \
        fi
endif

so that make sees the rule all as one line and the else doesn't appear
(as far as make is concerned) as a line on its own.

        Eddy.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]