Re: [PATCH] Makefile(s): avoid recipe prefix in conditional statements

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

 



On Mon, 2024-04-08 at 20:04 -0400, Jeff King wrote:
> > .RECIPEPREFIX was introduced in GNU Make 3.82, which was released
> > in 2010 FYI.
> 
> Unfortunately, that's too recent for us. :( We try to keep the GNU
> make dependency to 3.81, since that's the latest one Apple ships
> (because they're allergic to GPLv3).

I understand that position, for Git.  I hope you can understand that in
my position I have no interest in catering to Apple's ridiculous
corporate antics and can only shrug and say "oh well" :)

> I do find it curious that in:
> 
> ifdef FOO
>  SOME_VAR += bar
> endif
> 
> the tab is significant for "ifdef" but not for SOME_VAR (at least
> that is implied by Taylor's patch, which does not touch the bodies
> within the conditionals).

The handling of TAB in makefiles is actually more subtle than the
simple "if it starts with a TAB it's part of a recipe".  The full
statement is, "if it starts with a TAB _and is in a recipe context_
then it's part of a recipe".

A recipe context starts after a target is defined, and it ends only
when the first non-TAB-indented, non-comment line is parsed (or EOF).

The text above will work ONLY if the content BEFORE that text is not a
recipe.  If you add a recipe before that line, then the SOME_VAR += bar
will suddenly be considered by make as part of that recipe and will be
an error when you run that recipe (since that's not valid shell
syntax).

So for example if you have:

  $ cat Makefile

  # set up the variable SOME_VAR
  ifndef TRUE
  <TAB>SOME_VAR = bar
  endif

  all: ; echo $(SOME_VAR)

This is fine.  But if you then modify your makefile like this:

  $ cat Makefile

  recurse: ; $(MAKE) -C subdir

  # set up the variable SOME_VAR
  ifndef TRUE
  <TAB>SOME_VAR = bar
  endif

  all: ; echo $(SOME_VAR)

It LOOKS fine but it's completely broken because the SOME_VAR
assignment now becomes part of the recipe for the recurse target.

   (Just to note, this is not due to a recent change in GNU Make, and
   in fact this is not even specific to GNU Make: all versions of make
   behave like this.)

So while the patch proposed here does not remove all TAB characters, my
best advice is that as a project you SHOULD consider pro-actively
removing all non-recipe-introducing TAB characters.  They are dangerous
and misleading, even outside of this ifdef kerfuffle.


All I can do is reiterate my original statement: it's a bad idea to
consider TAB characters as whitespace or "just indentation" AT ALL when
editing makefiles.  TABs are not whitespace.  They are meaningful
tokens, like "$" or "#", and should only ever be used in places where
that meaning is desired.  The fact that they look like indentation and
can be used in some other places as "just indentation" and kinda-sorta
work, is an accident waiting to happen if it's taken advantage of.





[Index of Archives]     [Linux Kernel Development]     [Gcc Help]     [IETF Annouce]     [DCCP]     [Netdev]     [Networking]     [Security]     [V4L]     [Bugtraq]     [Yosemite]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux SCSI]     [Fedora Users]

  Powered by Linux