From 7e7098cd3fffff2a0c5cd6cbdb8035c9c419ffcb Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Mar 2026 13:49:48 +0100 Subject: [PATCH 1/3] Makefile.am: rearrange *CLEANFILES to be initialized on top of file and added to along the way Signed-off-by: Jim Klimov --- Makefile.am | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index bb569d602d..8d9acd82b7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -12,6 +12,10 @@ # include directory for aclocal ACLOCAL_AMFLAGS = -I m4 +CLEANFILES = +DISTCLEANFILES = +MAINTAINERCLEANFILES = + # Autotools' SUBDIRS (our values are listed below) allow for powerful recursive # recipe automation, with one notable weakness: the dirs are processed in a # loop sequentially, even in parallel builds (each such sub-make is parallel @@ -630,8 +634,8 @@ distcleancheck: realclean: maintainer-clean # Files made by our targets: -CLEANFILES = *-spellchecked *.adoc-parsed cppcheck*.xml config.log.inplace-outer -DISTCLEANFILES = ChangeLog +CLEANFILES += *-spellchecked *.adoc-parsed cppcheck*.xml config.log.inplace-outer +DISTCLEANFILES += ChangeLog # Most of the files generated by custom rules in the configure script # or by autogen.sh are cleaned by the Makefile.am in their directories. @@ -647,7 +651,7 @@ DISTCLEANFILES += include/config.h.in~ # from their installation, or made by `automake` etc. on the system # which generates `configure`; rebuilding NUT after deleting these # requires `autogen.sh` script to be re-run (and tools available): -MAINTAINERCLEANFILES = INSTALL +MAINTAINERCLEANFILES += INSTALL MAINTAINERCLEANFILES += aclocal.m4 config.guess config.sub MAINTAINERCLEANFILES += configure MAINTAINERCLEANFILES += depcomp install-sh ltmain.sh test-driver ar-lib From 55a3887ec333cad70513270f0753ec28291b7b59 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Mar 2026 13:51:32 +0100 Subject: [PATCH 2/3] Makefile.am, include/Makefile.am: introduce include/.all.nut_version-generated.timestamp touch-file to quickly skip nut_version.h regeneration even if we configure --enable-force-nut-version (default) [#3039, #3223] Signed-off-by: Jim Klimov --- Makefile.am | 14 ++++++++++++++ include/.gitignore | 1 + include/Makefile.am | 18 +++++++++++++----- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index 8d9acd82b7..40cfdc4f5f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -95,13 +95,22 @@ SUBDIRS_ALL_LIBS_LOCAL = \ #all all-recursive all-am-local all-local: all-fanout-maybe all-recursive: all-fanout-maybe +all: all-fanout-cleanup + +# Run as part of "all", but after the autotools-standard "all-recursive" +# where we quiesce nut_version.h regeneration attempts for each subdir +all-fanout-cleanup: all-recursive + @rm -f include/.all.nut_version-generated.timestamp + # Verbosity for fanout rule tracing; 0/1 (or "default" that may auto-set # to 0 or 1 in some rules below) SUBDIR_MAKE_VERBOSE = default # Run the standard build if going sequential (or with unknown MAKEFLAGS), # or fanout if parallel (presuming GNU/BSD/Sun make at least): +CLEANFILES += include/.all.nut_version-generated.timestamp all-fanout-maybe: @dotMAKE@ + @rm -f include/.all.nut_version-generated.timestamp +@if [ x"$(NUT_MAKE_SKIP_FANOUT)" = xtrue ] ; then \ if [ x"$(SUBDIR_MAKE_VERBOSE)" != x0 ] ; then \ echo " SUBDIR-MAKE $@: skip optimization for parallel make - NUT_MAKE_SKIP_FANOUT is set" ; \ @@ -220,6 +229,10 @@ SUBDIR_TGT_RULE = ( \ all-libs-local/include: @dotMAKE@ +@NUT_VERSION_H_GENERATED=false; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) + @[ -s include/nut_version.h ] + @touch -r include/nut_version.h -d '-10 seconds' include/.all.nut_version-generated.timestamp && exit ; \ + touch -d '1970-01-01' include/.all.nut_version-generated.timestamp && exit ; \ + touch include/.all.nut_version-generated.timestamp ### Delivers: libcommon.la libcommonclient.la libcommonstr.la libcommonstrjson.la ### (consume only one of these at a time!) @@ -1052,6 +1065,7 @@ ChangeLog.adoc: ChangeLog @dotMAKE@ +cd $(abs_top_builddir)/docs && $(MAKE) $(AM_MAKEFLAGS) ../ChangeLog.adoc nut_version.h include/nut_version.h: @dotMAKE@ + @rm -f include/.all.nut_version-generated.timestamp +cd $(abs_top_builddir)/include && $(MAKE) $(AM_MAKEFLAGS) nut_version.h # May involve (re-)build of libupsclient.la diff --git a/include/.gitignore b/include/.gitignore index 69570ffa44..232a47c4e0 100644 --- a/include/.gitignore +++ b/include/.gitignore @@ -1,5 +1,6 @@ /config.h /config.h.in +/.all.nut_version-generated.timestamp /nut_version.h /nut_version.h.tmp* /stamp-h1 diff --git a/include/Makefile.am b/include/Makefile.am index 0c8974891a..281ae4868f 100644 --- a/include/Makefile.am +++ b/include/Makefile.am @@ -45,12 +45,20 @@ MAINTAINERCLEANFILES = Makefile.in .dirstamp # (e.g. a commit tagged as 2.8.3-rc5 can have its own NUT_VERSION based # on 2.8.2-something, but is assumed as a pre-release for 2.8.3 SEMVER) nut_version.h: @FORCE_NUT_VERSION@ - @if [ -s '$@' ] && ( [ x"$(NUT_VERSION_H_GENERATED)" = xtrue ] || [ x"$${NUT_VERSION_H_GENERATED}" = xtrue ] ) ; then \ - if [ x"$(MAINTAINER_GENERATE_HEADER_DEBUG)" = xyes ] ; then \ - echo "=== SKIP (include) $@ (NUT_VERSION_H_GENERATED makevar=$(NUT_VERSION_H_GENERATED) shellvar=$${NUT_VERSION_H_GENERATED})" >&2; \ + @if [ -s '$@' ] ; then \ + if [ x"$(NUT_VERSION_H_GENERATED)" = xtrue ] || [ x"$${NUT_VERSION_H_GENERATED}" = xtrue ] ; then \ + if [ x"$(MAINTAINER_GENERATE_HEADER_DEBUG)" = xyes ] ; then \ + echo "=== SKIP (include) $@ (NUT_VERSION_H_GENERATED makevar=$(NUT_VERSION_H_GENERATED) shellvar=$${NUT_VERSION_H_GENERATED})" >&2; \ + fi ; \ + exit 0 ; \ fi ; \ - exit 0 ; \ - fi ; \ + if test -n "`find '$@' -newer '.all.nut_version-generated.timestamp' 2>/dev/null`" ; then \ + if [ x"$(MAINTAINER_GENERATE_HEADER_DEBUG)" = xyes ] ; then \ + echo "=== SKIP (include) $@ (.all.nut_version-generated.timestamp was made in this larger run and is older than the generated file)" >&2; \ + fi ; \ + exit 0 ; \ + fi ; \ + fi; \ if [ x"$(MAINTAINER_GENERATE_HEADER_DEBUG)" = xyes ] ; then \ echo " GENERATE-HEADER $@ (NUT_VERSION_H_GENERATED makevar=$(NUT_VERSION_H_GENERATED) shellvar=$${NUT_VERSION_H_GENERATED})"; \ else \ From 9b36e2cf3eb268f213230e0985b79cbcec167dd1 Mon Sep 17 00:00:00 2001 From: Jim Klimov Date: Tue, 3 Mar 2026 13:59:04 +0100 Subject: [PATCH 3/3] clients/Makefile.am: do not regenerate libupsclient-version.h each time we evaluate libupsclient.la rule [#3039, #3223, #1484] Signed-off-by: Jim Klimov --- Makefile.am | 16 ++++++++++++---- clients/.gitignore | 1 + clients/Makefile.am | 20 +++++++++++++++++++- 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/Makefile.am b/Makefile.am index 40cfdc4f5f..acc00c75ad 100644 --- a/Makefile.am +++ b/Makefile.am @@ -100,7 +100,8 @@ all: all-fanout-cleanup # Run as part of "all", but after the autotools-standard "all-recursive" # where we quiesce nut_version.h regeneration attempts for each subdir all-fanout-cleanup: all-recursive - @rm -f include/.all.nut_version-generated.timestamp + @rm -f include/.all.nut_version-generated.timestamp \ + clients/.all.libupsclient_version-generated.timestamp # Verbosity for fanout rule tracing; 0/1 (or "default" that may auto-set # to 0 or 1 in some rules below) @@ -108,9 +109,10 @@ SUBDIR_MAKE_VERBOSE = default # Run the standard build if going sequential (or with unknown MAKEFLAGS), # or fanout if parallel (presuming GNU/BSD/Sun make at least): -CLEANFILES += include/.all.nut_version-generated.timestamp +CLEANFILES += include/.all.nut_version-generated.timestamp clients/.all.libupsclient_version-generated.timestamp all-fanout-maybe: @dotMAKE@ - @rm -f include/.all.nut_version-generated.timestamp + @rm -f include/.all.nut_version-generated.timestamp \ + clients/.all.libupsclient_version-generated.timestamp +@if [ x"$(NUT_MAKE_SKIP_FANOUT)" = xtrue ] ; then \ if [ x"$(SUBDIR_MAKE_VERBOSE)" != x0 ] ; then \ echo " SUBDIR-MAKE $@: skip optimization for parallel make - NUT_MAKE_SKIP_FANOUT is set" ; \ @@ -256,6 +258,10 @@ all-libs-local/common: all-libs-local/include @dotMAKE@ all-libs-local/clients: all-libs-local/common @dotMAKE@ +@NUT_VERSION_H_GENERATED=true; export NUT_VERSION_H_GENERATED; \ $(SUBDIR_TGT_RULE) + @[ -s clients/libupsclient-version.h ] + @touch -r clients/libupsclient-version.h -d '-10 seconds' clients/.all.libupsclient_version-generated.timestamp && exit ; \ + touch -d '1970-01-01' clients/.all.libupsclient_version-generated.timestamp && exit ; \ + touch clients/.all.libupsclient_version-generated.timestamp ### Delivers: libdummy_main.la libdummy_serial.la libdummy_upsdrvquery.la ### Delivers: libdummy_mockdrv.la libserial-nutscan.la @@ -1068,8 +1074,10 @@ nut_version.h include/nut_version.h: @dotMAKE@ @rm -f include/.all.nut_version-generated.timestamp +cd $(abs_top_builddir)/include && $(MAKE) $(AM_MAKEFLAGS) nut_version.h +# May depend on nut_version.h at least when we ENABLE_SHARED_PRIVATE_LIBS # May involve (re-)build of libupsclient.la -libupsclient-version.h clients/libupsclient-version.h: @dotMAKE@ +libupsclient-version.h clients/libupsclient-version.h: include/nut_version.h @dotMAKE@ + @rm -f clients/.all.libupsclient_version-generated.timestamp +cd $(abs_top_builddir)/include && $(MAKE) $(AM_MAKEFLAGS) libupsclient-version.h tools/gitlog2changelog.py: tools/gitlog2changelog.py.in @dotMAKE@ diff --git a/clients/.gitignore b/clients/.gitignore index f629dd6aed..7cd848259f 100644 --- a/clients/.gitignore +++ b/clients/.gitignore @@ -1,3 +1,4 @@ +/.all.libupsclient_version-generated.timestamp /libupsclient-version.h /libupsclient-version.h.tmp* /upsimage.cgi diff --git a/clients/Makefile.am b/clients/Makefile.am index f2ca5a3d27..ab81516a16 100644 --- a/clients/Makefile.am +++ b/clients/Makefile.am @@ -201,9 +201,27 @@ endif HAVE_WINDOWS # dlname='libupsclient-6.dll' # library_names='libupsclient.dll.a' # libdir='//lib' +# Note that volatile dependencies like nut_version.h can cause re-evaluation +# of the libupsclient.la goal even if ultimately nothing has changed, and so +# cause needless evaluations of libupsclient-version.h. We try a couple of +# ways to skip this rebuild noise for common NUT parallel `make -j N all` runs. CLEANFILES += libupsclient-version.h libupsclient-version.h.tmp* libupsclient-version.h: libupsclient.la - @echo " GENERATE-HEADER $@" ; \ + @if [ -s '$@' -a -s '$?' ] ; then \ + if test -n "`find '$@' -newer '$?' 2>/dev/null`" ; then \ + if [ x"$(MAINTAINER_GENERATE_HEADER_DEBUG)" = xyes ] ; then \ + echo "=== SKIP (include) $@ (libupsclient.la is older than the generated file - not remade when re-evaluated)" >&2; \ + fi ; \ + exit 0; \ + fi ; \ + if test -n "`find '$@' -newer '.all.libupsclient_version-generated.timestamp' 2>/dev/null`" ; then \ + if [ x"$(MAINTAINER_GENERATE_HEADER_DEBUG)" = xyes ] ; then \ + echo "=== SKIP (include) $@ (.all.libupsclient_version-generated.timestamp was made in this larger run and is older than the generated file)" >&2; \ + fi ; \ + exit 0 ; \ + fi ; \ + fi ; \ + echo " GENERATE-HEADER $@" ; \ RES=0; \ dlname_filter() { sed -e 's/^[^=]*=//' -e 's/^"\(.*\)"$$/\1/' -e 's/^'"'"'\(.*\)'"'"'$$/\1/' ; }; \ SOFILE_LIBUPSCLIENT="`$(EGREP) '^dlname' '$?' | dlname_filter`" \