git/list[1] front-page[2] threads[3] people[4] search[5] about
 

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

From
Paul Smith <psmith@gnu.org>
Date
Apr 9, 2024, 20:44 UTC
Message-ID
<daa51548ff2d0cfc4407bbdbe99223c84321a503.camel@gnu.org>
In-Reply-To
<20240409000414.GA1647304@coredump.intra.peff.net>
On Mon, 2024-04-08 at 20:04 -0400, Jeff King wrote:
Show 6 quoted lines
> > .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" :)

Show 9 quoted lines
> 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.

Previous: Jeff KingNext: Junio C Hamano
Message 12 of 13 in “Makefiles are broken as of GNU Make commit 07fcee35f058a876447c8a021f9eb1943f902534”
  1. Dario GjorgjevskiApr 8, 2024
  2. Makefile(s): avoid recipe prefix in conditional statementsTaylor Blau, Apr 8, 2024
  3. Junio C HamanoApr 8, 2024
  4. Paul SmithApr 8, 2024
  5. Junio C HamanoApr 8, 2024
  6. Paul SmithApr 9, 2024
  7. Junio C HamanoApr 8, 2024
  8. Paul SmithApr 9, 2024
  9. Junio C HamanoApr 9, 2024
  10. Jeff KingApr 9, 2024
  11. Jeff KingApr 9, 2024
  12. Paul SmithApr 9, 2024
  13. Junio C HamanoApr 8, 2024

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.