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

Re: [PATCH 2/8] Documentation/Makefile: conditionally include ../GIT-VERSION-FILE

From
Ramsay Jones <ramsay@ramsayjones.plus.com>
Date
Nov 6, 2020, 19:38 UTC
Message-ID
<a654c95f-2367-5805-d4f8-56c466a141d4@ramsayjones.plus.com>
In-Reply-To
<20201106181804.GA183267@coredump.intra.peff.net>
On 06/11/2020 18:18, Jeff King wrote:
Show 74 quoted lines
> On Thu, Nov 05, 2020 at 09:03:49PM +0000, Ramsay Jones wrote:
> 
>> diff --git a/Documentation/Makefile b/Documentation/Makefile
>> index 652d57a1b6..5c680024eb 100644
>> --- a/Documentation/Makefile
>> +++ b/Documentation/Makefile
>> @@ -272,7 +272,9 @@ install-html: html
>>  ../GIT-VERSION-FILE: FORCE
>>  	$(QUIET_SUBDIR0)../ $(QUIET_SUBDIR1) GIT-VERSION-FILE
>>  
>> +ifneq ($(MAKECMDGOALS),clean)
>>  -include ../GIT-VERSION-FILE
>> +endif
> 
> Calling out "clean" here specially feels somewhat backwards to me, in
> terms of Makefile design. In an ideal world we provide all of the
> dependencies to "make", and based on the targets we are building, it
> decides what needs to be done.
> 
> This works with normal targets, obviously, but also with variables. If
> we do:
> 
>   FOO = $(shell do-the-thing)
> 
> then we execute that command only when $(FOO) is needed[1].
> 
> But "include" here is tricky. It is loaded regardless of whether the
> values it contains are needed or not. I wonder if we could do better by
> giving make more information about what we're expecting to get from it.
> I.e., if we wrote:
> 
>   GIT_VERSION = $(shell awk '{print $3}' GIT-VERSION-FILE)
> 
> Then "make clean", not needing the value of $(GIT_VERSION), wouldn't run
> that shell snippet at all. Of course there's a catch; we are also
> relying on the include to trigger the dependency. So it is really more
> like:
> 
>   GIT_VERSION = $(shell make GIT-VERSION-FILE && awk '{print $3}' GIT-VERSION-FILE)
> 
> I'm not sure how bad that is. Re-invoking make seems like it could get
> expensive, especially for the common case that we're building actual
> binaries and we _do_ need the version. But we could probably cut "make"
> out of the loop entirely. Generating GIT-VERSION-FILE is already a FORCE
> target, so really:
> 
>   GIT_VERSION = $(shell ./GIT-VERSION-GEN)
> 
> would be equivalent-ish (with some output changes, and possibly we'd
> want to stash the value in a file for any other scripts to make use of).
> 
> This is all just stuff I've written in my editor and not tried. I won't
> be surprised if there are some gotchas. But it at least seems like a
> conceptually cleaner path.
> 
> -Peff
> 
> [1] Variable assignment actually has a slight problem in the opposite
>     direction: it wants to run the shell snippet every time the variable
>     is referenced. There's a trick to get around that described in
>     0573831950 (Makefile: avoid running curl-config unnecessarily,
>     2020-04-04).
> 
>     It's built around evals. In fact, I suspect you could build a
>     function around eval that actually works similar to include, but
>     lazy-loads the file only when one of its stubs is referenced. I.e.,
>     something like:
> 
>       GIT_VERSION = $(eval include GIT-VERSION-FILE)
> 
>     would probably work (and for other includes, multiple variables
>     could mention the same file; as soon as it gets included, it
>     overwrites the stubs).
> 

Heh, in another reply in this thread, I mentioned that I had an alternate patch I was toying with. If I tell you it was inspired by your commit 0573831950 (Makefile: avoid running curl-config unnecessarily, 04-04-2020), you would probably not be surprised that it looks similar to what you outline here. I had only just started looking at this approach, but it has some wrinkles, so I thought I would look at it after submitting this series 'because this is an easy win'! ;-)

I hadn't done so yet, but I had planned to modify the GIT-VERSION-GEN script (with -v parameter, say) to just output the version to stdout, because it would save a sed invocation. It currently looks something like this:

  diff --git a/Makefile b/Makefile
  index 372139f1f2..f166fbe067 100644
  --- a/Makefile
  +++ b/Makefile
  @@ -493,7 +493,11 @@ all::
 
   GIT-VERSION-FILE: FORCE
          @$(SHELL_PATH) ./GIT-VERSION-GEN
  --include GIT-VERSION-FILE
  +
  +ifeq ($(wildcard GIT-VERSION-FILE),)
  +$(shell ./GIT-VERSION-GEN)
  +endif
  +GIT_VERSION = $(eval GIT_VERSION := $$(shell cat GIT-VERSION-FILE | sed -e 's/^GIT_VERSION = //'))$(GIT_VERSION)
 
   # Set our default configuration.
   #

Ignore the 'ifeq' for now (I had several versions, including getting rid of the GIT-VERSION-FILE rule, but that caused problems without changing the Documentation/Makefile, and several others ... (including in contrib)).

So, I haven't worked everything out yet, but I had planned to look at this next.

ATB, Ramsay Jones

Previous: Jeff KingNext: Jeff King
Message 5 of 7 in “Documentation/Makefile: conditionally include ../GIT-VERSION-FILE”
  1. 2/8 Documentation/Makefile: conditionally include ../GIT-VERSION-FILERamsay Jones, Nov 5, 2020
  2. Junio C HamanoNov 5, 2020
  3. Ramsay JonesNov 6, 2020
  4. Jeff KingNov 6, 2020
  5. Ramsay JonesNov 6, 2020
  6. Jeff KingNov 6, 2020
  7. Junio C HamanoNov 6, 2020

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.