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

[PATCH 03/13] Makefile: introduce make-var helper function

From
Jeff King <peff@peff.net>
Date
Feb 5, 2014, 17:50 UTC
Message-ID
<20140205175002.GC15218@sigill.intra.peff.net>
In-Reply-To
<20140205174823.GA15070@sigill.intra.peff.net>

It's a common pattern in our Makefile to echo some make variables into a file, but only if they are different from a previous run. This sentinel file can then be used as a dependency to trigger rebuilds when the make variable changes.

The code to do this is a bit ugly and repetetive; let's factor it out into a reusable function.

Note that this relies on the "call" and "eval" functions of GNU make. We previously avoided using "call", as explained in 39c015c (Fixes for ancient versions of GNU make, 2006-02-18). However, it has been 8 years since then, so perhaps its use is acceptable now.

The "call" function dates back to GNU make 3.77.90 (1997-07-21). The "eval" function dates back to 3.80 (2002-07-08).

If it's still a problem to use these functions, we can do similar meta-programming with something like:

	include magic.mak
	magic.mak:
		./generate-magic-rules >$@+
		mv $@+ $@
where the rules are generated by a shell (or other) script.
Signed-off-by: Jeff King <peff@peff.net>
---
 Makefile | 105 ++++++++++++++++++++++++---------------------------------------
 1 file changed, 40 insertions(+), 65 deletions(-)
diff --git a/Makefile b/Makefile
index 1f3e5d9..50bf252 100644
--- a/Makefile
+++ b/Makefile
@@ -1561,6 +1561,20 @@ ifneq ("$(PROFILE)","")
 endif
 endif
 
+# usage: $(eval $(call make-var,FN,DESC,CONTENTS))
+#
+# Create a rule to write $CONTENTS (which should come from a make variable)
+# to GIT-$FN, but only if not already there. This can be used to create a
+# dependency on a Makefile variable. Prints $DESC to the user.
+define make-var
+GIT-$1: FORCE
+	@VALUE='$$(subst ','\'',$3)'; \
+	if test x"$$$$VALUE" != x"`cat $$@ 2>/dev/null`"; then \
+		echo >&2 "    * new $2"; \
+		echo "$$$$VALUE" >$$@; \
+	fi
+endef
+
 # Shell quote (do not use $(call) to accommodate ancient setups);
 
 SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER))
@@ -1615,13 +1629,9 @@ SHELL_PATH_CQ_SQ = $(subst ','\'',$(SHELL_PATH_CQ))
 BASIC_CFLAGS += -DSHELL_PATH='$(SHELL_PATH_CQ_SQ)'
 endif
 
-GIT_USER_AGENT_SQ = $(subst ','\'',$(GIT_USER_AGENT))
 GIT_USER_AGENT_CQ = "$(subst ",\",$(subst \,\\,$(GIT_USER_AGENT)))"
 GIT_USER_AGENT_CQ_SQ = $(subst ','\'',$(GIT_USER_AGENT_CQ))
-GIT-USER-AGENT: FORCE
-	@if test x'$(GIT_USER_AGENT_SQ)' != x"`cat GIT-USER-AGENT 2>/dev/null`"; then \
-		echo '$(GIT_USER_AGENT_SQ)' >GIT-USER-AGENT; \
-	fi
+$(eval $(call make-var,USER-AGENT,user agent string,$(GIT_USER_AGENT)))
 
 ifdef DEFAULT_HELP_FORMAT
 BASIC_CFLAGS += -DDEFAULT_HELP_FORMAT='"$(DEFAULT_HELP_FORMAT)"'
@@ -1737,9 +1747,17 @@ common-cmds.h: ./generate-cmdlist.sh command-list.txt
 common-cmds.h: $(wildcard Documentation/git-*.txt)
 	$(QUIET_GEN)./generate-cmdlist.sh > $@+ && mv $@+ $@
 
-SCRIPT_DEFINES = $(SHELL_PATH_SQ):$(DIFF_SQ):$(GIT_VERSION):\
-	$(localedir_SQ):$(NO_CURL):$(USE_GETTEXT_SCHEME):$(SANE_TOOL_PATH_SQ):\
-	$(gitwebdir_SQ):$(PERL_PATH_SQ)
+$(eval $(call make-var,SCRIPT-DEFINES,script parameters,\
+	:$(SHELL_PATH)\
+	:$(DIFF)\
+	:$(GIT_VERSION)\
+	:$(localedir)\
+	:$(NO_CURL)\
+	:$(USE_GETTEXT_SCHEME)\
+	:$(SANE_TOOL_PATH)\
+	:$(gitwebdir)\
+	:$(PERL_PATH)\
+))
 define cmd_munge_script
 $(RM) $@ $@+ && \
 sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
@@ -1754,14 +1772,6 @@ sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
     $@.sh >$@+
 endef
 
-GIT-SCRIPT-DEFINES: FORCE
-	@FLAGS='$(SCRIPT_DEFINES)'; \
-	    if test x"$$FLAGS" != x"`cat $@ 2>/dev/null`" ; then \
-		echo >&2 "    * new script parameters"; \
-		echo "$$FLAGS" >$@; \
-            fi
-
-
 $(patsubst %.sh,%,$(SCRIPT_SH)) : % : %.sh GIT-SCRIPT-DEFINES
 	$(QUIET_GEN)$(cmd_munge_script) && \
 	chmod +x $@+ && \
@@ -1789,7 +1799,10 @@ perl/PM.stamp: FORCE
 perl/perl.mak: GIT-CFLAGS GIT-PREFIX perl/Makefile perl/Makefile.PL
 	$(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
 
-PERL_DEFINES = $(PERL_PATH_SQ):$(PERLLIB_EXTRA_SQ)
+$(eval $(call make-var,PERL-DEFINES,perl-specific parameters,\
+	:$(PERL_PATH)\
+	:$(PERLLIB_EXTRA)\
+))
 $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl perl/perl.mak GIT-PERL-DEFINES GIT-VERSION-FILE
 	$(QUIET_GEN)$(RM) $@ $@+ && \
 	INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C perl -s --no-print-directory instlibdir` && \
@@ -1807,14 +1820,6 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl perl/perl.mak GIT-PERL-DEFINES G
 	chmod +x $@+ && \
 	mv $@+ $@
 
-GIT-PERL-DEFINES: FORCE
-	@FLAGS='$(PERL_DEFINES)'; \
-	    if test x"$$FLAGS" != x"`cat $@ 2>/dev/null`" ; then \
-		echo >&2 "    * new perl-specific parameters"; \
-		echo "$$FLAGS" >$@; \
-	    fi
-
-
 .PHONY: gitweb
 gitweb:
 	$(QUIET_SUBDIR0)gitweb $(QUIET_SUBDIR1) all
@@ -1835,6 +1840,7 @@ $(patsubst %.perl,%,$(SCRIPT_PERL)) git-instaweb: % : unimplemented.sh
 endif # NO_PERL
 
 ifndef NO_PYTHON
+$(eval $(call make-var,PYTHON-VARS,Python interpreter location,$(PYTHON_PATH)))
 $(SCRIPT_PYTHON_GEN): GIT-CFLAGS GIT-PREFIX GIT-PYTHON-VARS
 $(SCRIPT_PYTHON_GEN): % : %.py
 	$(QUIET_GEN)$(RM) $@ $@+ && \
@@ -2154,34 +2160,15 @@ cscope:
 	$(RM) cscope*
 	$(FIND_SOURCE_FILES) | xargs cscope -b
 
-### Detect prefix changes
-TRACK_PREFIX = $(bindir_SQ):$(gitexecdir_SQ):$(template_dir_SQ):$(prefix_SQ):\
-		$(localedir_SQ)
-
-GIT-PREFIX: FORCE
-	@FLAGS='$(TRACK_PREFIX)'; \
-	if test x"$$FLAGS" != x"`cat GIT-PREFIX 2>/dev/null`" ; then \
-		echo >&2 "    * new prefix flags"; \
-		echo "$$FLAGS" >GIT-PREFIX; \
-	fi
-
-TRACK_CFLAGS = $(CC):$(subst ','\'',$(ALL_CFLAGS))
-
-GIT-CFLAGS: FORCE
-	@FLAGS='$(TRACK_CFLAGS)'; \
-	    if test x"$$FLAGS" != x"`cat GIT-CFLAGS 2>/dev/null`" ; then \
-		echo >&2 "    * new build flags"; \
-		echo "$$FLAGS" >GIT-CFLAGS; \
-            fi
-
-TRACK_LDFLAGS = $(subst ','\'',$(ALL_LDFLAGS))
-
-GIT-LDFLAGS: FORCE
-	@FLAGS='$(TRACK_LDFLAGS)'; \
-	    if test x"$$FLAGS" != x"`cat GIT-LDFLAGS 2>/dev/null`" ; then \
-		echo >&2 "    * new link flags"; \
-		echo "$$FLAGS" >GIT-LDFLAGS; \
-            fi
+$(eval $(call make-var,PREFIX,prefix flags,\
+	:$(bindir)\
+	:$(gitexecdir)\
+	:$(template_dir)\
+	:$(prefix)\
+	:$(localedir)\
+))
+$(eval $(call make-var,CFLAGS,build flags,$(ALL_CFLAGS)))
+$(eval $(call make-var,LDFLAGS,link flags,$(ALL_LDFLAGS)))
 
 # We need to apply sq twice, once to protect from the shell
 # that runs GIT-BUILD-OPTIONS, and then again to protect it
@@ -2224,18 +2211,6 @@ ifdef GIT_PERF_MAKE_OPTS
 	@echo GIT_PERF_MAKE_OPTS=\''$(subst ','\'',$(subst ','\'',$(GIT_PERF_MAKE_OPTS)))'\' >>$@
 endif
 
-### Detect Python interpreter path changes
-ifndef NO_PYTHON
-TRACK_PYTHON = $(subst ','\'',-DPYTHON_PATH='$(PYTHON_PATH_SQ)')
-
-GIT-PYTHON-VARS: FORCE
-	@VARS='$(TRACK_PYTHON)'; \
-	    if test x"$$VARS" != x"`cat $@ 2>/dev/null`" ; then \
-		echo >&2 "    * new Python interpreter location"; \
-		echo "$$VARS" >$@; \
-            fi
-endif
-
 test_bindir_programs := $(patsubst %,bin-wrappers/%,$(BINDIR_PROGRAMS_NEED_X) $(BINDIR_PROGRAMS_NO_X) $(TEST_PROGRAMS_NEED_X))
 
 all:: $(TEST_PROGRAMS) $(test_bindir_programs)
-- 
1.8.5.2.500.g8060133
Previous: Jeff KingNext: Eric Sunshine
Message 4 of 28 in “makefile refactoring”
  1. 0/13 makefile refactoringJeff King, Feb 5, 2014
  2. 01/13 Makefile: drop USE_GETTEXT_SCHEME from GIT-CFLAGSJeff King, Feb 5, 2014
  3. 02/13 Makefile: fix git-instaweb dependency on gitwebJeff King, Feb 5, 2014
  4. 03/13 Makefile: introduce make-var helper functionJeff King, Feb 5, 2014
  5. Eric SunshineFeb 6, 2014
  6. 04/13 Makefile: use tempfile/mv strategy for GIT-*Jeff King, Feb 5, 2014
  7. 05/13 Makefile: prefer printf to echo for GIT-*Jeff King, Feb 5, 2014
  8. 06/13 Makefile: store GIT-* sentinel files in MAKE/Jeff King, Feb 5, 2014
  9. Junio C HamanoFeb 5, 2014
  10. 07/13 Makefile: always create files via make-varJeff King, Feb 5, 2014
  11. 08/13 Makefile: introduce sq function for shell-quotingJeff King, Feb 5, 2014
  12. Junio C HamanoFeb 5, 2014
  13. 09/13 Makefile: add c-quote helper functionJeff King, Feb 5, 2014
  14. Junio C HamanoFeb 5, 2014
  15. Jeff KingFeb 5, 2014
  16. 10/13 Makefile: drop *_SQ variablesJeff King, Feb 5, 2014
  17. Junio C HamanoFeb 5, 2014
  18. 11/13 Makefile: auto-build C strings from make variablesJeff King, Feb 5, 2014
  19. Junio C HamanoFeb 5, 2014
  20. Jeff KingFeb 5, 2014
  21. 12/13 Makefile: teach scripts to include make variablesJeff King, Feb 5, 2014
  22. Junio C HamanoFeb 5, 2014
  23. Jeff KingFeb 5, 2014
  24. Thomas RastFeb 8, 2014
  25. Jeff KingFeb 10, 2014
  26. 13/13 move LESS/LV pager environment to MakefileJeff King, Feb 5, 2014
  27. Jeff KingFeb 5, 2014
  28. Jeff KingFeb 5, 2014

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.