Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't Make allow indented "if" statements?

It's a constant thorn in my side when trying to read a makefile with nested logic, that Make does not allow indented if statements. Why is this, and is there a good way to work around this limitation, and still have readable makefiles?

Update: I now realise that this question is based on a false premise, but I believe that leaving it here may be valuable to anyone who makes the same mistake that I did.

like image 655
LongTP5 Avatar asked Feb 22 '19 04:02

LongTP5


People also ask

DO IF statements need to be indented in Python?

To indicate a block of code in Python, you must indent each line of the block by the same amount. The two blocks of code in our example if-statement are both indented four spaces, which is a typical amount of indentation for Python.

Which part of if statement is indented?

The correct answer is "The statements within if".

What is indentation explain it using if else conditional statement?

The if..else statement evaluates test expression and will execute the body of if only when the test condition is True . If the condition is False , the body of else is executed. Indentation is used to separate the blocks.


1 Answers

Thanks to the help of others, I now realize that my question is posed on a false premise. Makefiles absolutely do allow for indented if statements, or rather indented conditionals to be more precise. What they don't allow for - at least out of the box - are tabbed conditionals. This is because, by default, Make interprets tabs as especially meaningful characters. Almost any line beginning with a tab character is interpreted to be part of a recipe. Therefore, any line that is not intended to be part of a recipe - such as conditionals - should not begin with a tab.

As far as answering the part of my question that asked why they chose to use the tab character in this way, I haven't found an answer. Perhaps the designers intended for conditionals to be used sparingly.

As for workarounds, here I will attempt to describe a couple.

The first solution is a terrible pain if you don't have an editor that shows whitespace characters, but if you do, the simplest thing to do might be to just add some spaces to indent your non recipe code. This is a rather hackish workaround though and probably ill advised.

Another solution (courtesy of @Stefan Becker) is to set the special variable, .RECIPEPREFIX to a character other than tab. Here's an example of what I tried:

.RECIPEPREFIX := >
# Now, all recipes will begin with the > character rather than a tab.

things = something another_thing something_else nothing
nothing = true

something: another_thing something_else
# See how each line of a recipe now begins with >.
# You can see I also added a tab after the >. 
# These tabs doesn't mean anything to Make; it's just for readability.
>   $(info Making $@.)
>   @touch $@

another_thing:
>   $(info Making $@.)
    # See also how lines like comments can be tabbed, 
    # but no longer add anything meaningful to recipes.
>   @touch $@

something_else:
>   $(info Making $@.)
>   @touch $@
    # And just to prove the situation with conditionals is resolved...
    # See how the @touch command begins with the new RECIPEPREFIX 
    # but the conditionals don't.
    ifeq ($(nothing),true)
>       $(info Also making nothing, because nothing is true.)
>       @touch nothing
    endif

.PHONY: everything_clean
everything_clean:
>   $(info Cleaning up everything.)
>   rm -f $(things)

One thing worth remembering is that recipe lines must begin with the new RECIPEPREFIX. That is to say, that something like this won't work:

something: another_thing something_else
# Remember that the RECIPEPREFIX must come first. 
# Indenting your recipe lines first and then using the RECIPEPRIFX will not work.
    >$(info Making $@.)
    >@touch $@
like image 172
LongTP5 Avatar answered Sep 28 '22 09:09

LongTP5