Package: dpkg-dev
Followup-For: Bug #872381

The attached changes are split into smaller chunks and rebased on
55cdc52e.  A merge conflict with 52166568 could have easily been
avoided, please review pending patches before reformatting comments.
>From f021e4d5ada4df39948afa339bd3a0859d28ed5a Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <nico...@debian.org>
Date: Mon, 29 Jul 2019 14:38:32 +0200
Subject: [PATCH 1/7] scripts/mk: simplify Makefile.am with sed --in-place
 option

---
 scripts/mk/Makefile.am | 18 ++++--------------
 1 file changed, 4 insertions(+), 14 deletions(-)

diff --git a/scripts/mk/Makefile.am b/scripts/mk/Makefile.am
index 9f0462eca..92e95c429 100644
--- a/scripts/mk/Makefile.am
+++ b/scripts/mk/Makefile.am
@@ -9,18 +9,8 @@ dist_pkgdata_DATA = \
 	pkg-info.mk \
 	vendor.mk
 
-do_path_subst = $(AM_V_GEN) sed \
-	-e "s:dpkg_datadir[[:space:]]*=[[:space:]]*[^[:space:]]*:dpkg_datadir = $(pkgdatadir):"
-
 install-data-hook:
-	mv $(DESTDIR)$(pkgdatadir)/default.mk \
-	   $(DESTDIR)$(pkgdatadir)/default.mk.tmp
-	$(do_path_subst) <$(DESTDIR)$(pkgdatadir)/default.mk.tmp \
-	                 >$(DESTDIR)$(pkgdatadir)/default.mk
-	rm -f $(DESTDIR)$(pkgdatadir)/default.mk.tmp
-
-	mv $(DESTDIR)$(pkgdatadir)/buildtools.mk \
-	   $(DESTDIR)$(pkgdatadir)/buildtools.mk.tmp
-	$(do_path_subst) <$(DESTDIR)$(pkgdatadir)/buildtools.mk.tmp \
-	                 >$(DESTDIR)$(pkgdatadir)/buildtools.mk
-	rm -f $(DESTDIR)$(pkgdatadir)/buildtools.mk.tmp
+	$(AM_V_GEN) sed --in-place \
+	  's:dpkg_datadir[[:space:]]*=[[:space:]]*[^[:space:]]*:dpkg_datadir = $(pkgdatadir):' \
+	  $(DESTDIR)$(pkgdatadir)/buildtools.mk \
+	  $(DESTDIR)$(pkgdatadir)/default.mk
-- 
2.30.0

>From 447b6dd8ff7bd1ed21c63a6285193fdd1980eebc Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <nico...@debian.org>
Date: Thu, 11 Feb 2021 15:36:15 +0100
Subject: [PATCH 2/7] scripts: test SOURCE_DATE_EPOCH

Set SOURCE_DATE_EPOCH either from the environment or the Debian changelog.
Check that the value is (re)exported.
---
 scripts/t/mk.t           | 9 ++++++++-
 scripts/t/mk/pkg-info.mk | 2 ++
 2 files changed, 10 insertions(+), 1 deletion(-)

diff --git a/scripts/t/mk.t b/scripts/t/mk.t
index 766aa82e0..c9ca0bc9f 100644
--- a/scripts/t/mk.t
+++ b/scripts/t/mk.t
@@ -16,7 +16,7 @@
 use strict;
 use warnings;
 
-use Test::More tests => 10;
+use Test::More tests => 11;
 use Test::Dpkg qw(:paths);
 
 use File::Spec::Functions qw(rel2abs);
@@ -126,6 +126,13 @@ foreach my $tool (keys %buildtools) {
     delete $ENV{"${tool}_FOR_BUILD"};
 }
 
+delete $ENV{SOURCE_DATE_EPOCH};
+$ENV{TEST_SOURCE_DATE_EPOCH} = `date +%s -d "Tue, 04 Aug 2015 16:13:50 +0200"`;
+chomp $ENV{TEST_SOURCE_DATE_EPOCH};
+test_makefile('pkg-info.mk');
+
+$ENV{SOURCE_DATE_EPOCH} = 100;
+$ENV{TEST_SOURCE_DATE_EPOCH} = 100;
 test_makefile('pkg-info.mk');
 
 test_makefile('vendor.mk');
diff --git a/scripts/t/mk/pkg-info.mk b/scripts/t/mk/pkg-info.mk
index 22a2bf44f..c0e3287b5 100644
--- a/scripts/t/mk/pkg-info.mk
+++ b/scripts/t/mk/pkg-info.mk
@@ -7,3 +7,5 @@ test:
 	test "$(DEB_VERSION_UPSTREAM_REVISION)" = "2:3.4-5-6"
 	test "$(DEB_VERSION_UPSTREAM)" = "2:3.4-5"
 	test "$(DEB_DISTRIBUTION)" = "suite"
+	test '$(SOURCE_DATE_EPOCH)' = '$(TEST_SOURCE_DATE_EPOCH)'
+	test "$${SOURCE_DATE_EPOCH}" = '$(TEST_SOURCE_DATE_EPOCH)'
-- 
2.30.0

>From c7e5b518b5f356cba972c50f2f85187f8a17872a Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <nico...@debian.org>
Date: Thu, 11 Feb 2021 15:45:03 +0100
Subject: [PATCH 3/7] scripts/t: slightly optimize hash traversals

Iterate on key/value pairs instead of iterating on keys then search
for each value.
---
 scripts/t/mk.t | 23 +++++++++++++++--------
 1 file changed, 15 insertions(+), 8 deletions(-)

diff --git a/scripts/t/mk.t b/scripts/t/mk.t
index c9ca0bc9f..33c933f06 100644
--- a/scripts/t/mk.t
+++ b/scripts/t/mk.t
@@ -69,10 +69,15 @@ sub cmd_get_vars {
 
 my %arch = cmd_get_vars($ENV{PERL}, "$srcdir/dpkg-architecture.pl", '-f');
 
-delete $ENV{$_} foreach keys %arch;
-$ENV{"TEST_$_"} = $arch{$_} foreach keys %arch;
+while (my ($k, $v) = each %arch) {
+    delete $ENV{$k};
+    $ENV{"TEST_$k"} = $v;
+}
 test_makefile('architecture.mk');
-$ENV{$_} = $arch{$_} foreach keys %arch;
+
+while (my ($k, $v) = each %arch) {
+    $ENV{$k} = $v;
+}
 test_makefile('architecture.mk');
 
 $ENV{DEB_BUILD_OPTIONS} = 'parallel=16';
@@ -83,8 +88,10 @@ delete $ENV{TEST_DEB_BUILD_OPTION_PARALLEL};
 
 my %buildflag = cmd_get_vars($ENV{PERL}, "$srcdir/dpkg-buildflags.pl");
 
-delete $ENV{$_} foreach keys %buildflag;
-$ENV{"TEST_$_"} = $buildflag{$_} foreach keys %buildflag;
+while (my ($k, $v) = each %buildflag) {
+    delete $ENV{$k};
+    $ENV{"TEST_$k"} = $v;
+}
 test_makefile('buildflags.mk');
 
 my %buildtools = (
@@ -107,11 +114,11 @@ my %buildtools = (
     PKG_CONFIG => 'pkg-config',
 );
 
-foreach my $tool (keys %buildtools) {
+while (my ($tool, $default) = each %buildtools) {
     delete $ENV{$tool};
-    $ENV{"TEST_$tool"} = "$ENV{DEB_HOST_GNU_TYPE}-$buildtools{$tool}";
+    $ENV{"TEST_$tool"} = "$ENV{DEB_HOST_GNU_TYPE}-$default";
     delete $ENV{"${tool}_FOR_BUILD"};
-    $ENV{"TEST_${tool}_FOR_BUILD"} = "$ENV{DEB_BUILD_GNU_TYPE}-$buildtools{$tool}";
+    $ENV{"TEST_${tool}_FOR_BUILD"} = "$ENV{DEB_BUILD_GNU_TYPE}-$default";
 }
 test_makefile('buildtools.mk');
 
-- 
2.30.0

>From 64b7b7aab66a48bb47a5747116f752b86e1a1b66 Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <nico...@debian.org>
Date: Thu, 11 Feb 2021 16:09:48 +0100
Subject: [PATCH 4/7] scripts/t: use loops instead of repetitions, check
 exports and overrides

Replace copied lines with loops.

Add tests: architecture variable override, buildflags set and export,
buildtool override and export.
---
 scripts/t/mk/architecture.mk | 57 +++++++++++++-------------------
 scripts/t/mk/buildflags.mk   | 35 +++++++++++++-------
 scripts/t/mk/buildtools.mk   | 63 +++++++++++++++++-------------------
 3 files changed, 77 insertions(+), 78 deletions(-)

diff --git a/scripts/t/mk/architecture.mk b/scripts/t/mk/architecture.mk
index 2ac0222ca..939835be3 100644
--- a/scripts/t/mk/architecture.mk
+++ b/scripts/t/mk/architecture.mk
@@ -1,36 +1,25 @@
+DEB_BUILD_ARCH := overridden
+
 include $(srcdir)/mk/architecture.mk
 
-test:
-	test "$(DEB_BUILD_ARCH)" = "$(TEST_DEB_BUILD_ARCH)"
-	test "$(DEB_BUILD_ARCH_ABI)" = "$(TEST_DEB_BUILD_ARCH_ABI)"
-	test "$(DEB_BUILD_ARCH_BITS)" = "$(TEST_DEB_BUILD_ARCH_BITS)"
-	test "$(DEB_BUILD_ARCH_CPU)" = "$(TEST_DEB_BUILD_ARCH_CPU)"
-	test "$(DEB_BUILD_ARCH_ENDIAN)" = "$(TEST_DEB_BUILD_ARCH_ENDIAN)"
-	test "$(DEB_BUILD_ARCH_LIBC)" = "$(TEST_DEB_BUILD_ARCH_LIBC)"
-	test "$(DEB_BUILD_ARCH_OS)" = "$(TEST_DEB_BUILD_ARCH_OS)"
-	test "$(DEB_BUILD_GNU_CPU)" = "$(TEST_DEB_BUILD_GNU_CPU)"
-	test "$(DEB_BUILD_GNU_SYSTEM)" = "$(TEST_DEB_BUILD_GNU_SYSTEM)"
-	test "$(DEB_BUILD_GNU_TYPE)" = "$(TEST_DEB_BUILD_GNU_TYPE)"
-	test "$(DEB_BUILD_MULTIARCH)" = "$(TEST_DEB_BUILD_MULTIARCH)"
-	test "$(DEB_HOST_ARCH)" = "$(TEST_DEB_HOST_ARCH)"
-	test "$(DEB_HOST_ARCH_ABI)" = "$(TEST_DEB_HOST_ARCH_ABI)"
-	test "$(DEB_HOST_ARCH_BITS)" = "$(TEST_DEB_HOST_ARCH_BITS)"
-	test "$(DEB_HOST_ARCH_CPU)" = "$(TEST_DEB_HOST_ARCH_CPU)"
-	test "$(DEB_HOST_ARCH_ENDIAN)" = "$(TEST_DEB_HOST_ARCH_ENDIAN)"
-	test "$(DEB_HOST_ARCH_LIBC)" = "$(TEST_DEB_HOST_ARCH_LIBC)"
-	test "$(DEB_HOST_ARCH_OS)" = "$(TEST_DEB_HOST_ARCH_OS)"
-	test "$(DEB_HOST_GNU_CPU)" = "$(TEST_DEB_HOST_GNU_CPU)"
-	test "$(DEB_HOST_GNU_SYSTEM)" = "$(TEST_DEB_HOST_GNU_SYSTEM)"
-	test "$(DEB_HOST_GNU_TYPE)" = "$(TEST_DEB_HOST_GNU_TYPE)"
-	test "$(DEB_HOST_MULTIARCH)" = "$(TEST_DEB_HOST_MULTIARCH)"
-	test "$(DEB_TARGET_ARCH)" = "$(TEST_DEB_TARGET_ARCH)"
-	test "$(DEB_TARGET_ARCH_ABI)" = "$(TEST_DEB_TARGET_ARCH_ABI)"
-	test "$(DEB_TARGET_ARCH_BITS)" = "$(TEST_DEB_TARGET_ARCH_BITS)"
-	test "$(DEB_TARGET_ARCH_CPU)" = "$(TEST_DEB_TARGET_ARCH_CPU)"
-	test "$(DEB_TARGET_ARCH_ENDIAN)" = "$(TEST_DEB_TARGET_ARCH_ENDIAN)"
-	test "$(DEB_TARGET_ARCH_LIBC)" = "$(TEST_DEB_TARGET_ARCH_LIBC)"
-	test "$(DEB_TARGET_ARCH_OS)" = "$(TEST_DEB_TARGET_ARCH_OS)"
-	test "$(DEB_TARGET_GNU_CPU)" = "$(TEST_DEB_TARGET_GNU_CPU)"
-	test "$(DEB_TARGET_GNU_SYSTEM)" = "$(TEST_DEB_TARGET_GNU_SYSTEM)"
-	test "$(DEB_TARGET_GNU_TYPE)" = "$(TEST_DEB_TARGET_GNU_TYPE)"
-	test "$(DEB_TARGET_MULTIARCH)" = "$(TEST_DEB_TARGET_MULTIARCH)"
+vars := $(foreach machine,BUILD HOST TARGET,$(foreach var,\
+  ARCH \
+  ARCH_ABI \
+  ARCH_BITS \
+  ARCH_CPU \
+  ARCH_ENDIAN \
+  ARCH_LIBC \
+  ARCH_OS \
+  GNU_CPU \
+  GNU_SYSTEM \
+  GNU_TYPE \
+  MULTIARCH \
+,DEB_$(machine)_$(var)))
+
+test: $(vars)
+DEB_BUILD_ARCH:
+	test '$($@)' = overridden
+	test "$${$@}" = overridden
+$(filter-out DEB_BUILD_ARCH,$(vars)):
+	test '$($@)' = '$(TEST_$@)'
+	test "$${$@}" = '$(TEST_$@)'
diff --git a/scripts/t/mk/buildflags.mk b/scripts/t/mk/buildflags.mk
index 90274ef90..19e50eb8e 100644
--- a/scripts/t/mk/buildflags.mk
+++ b/scripts/t/mk/buildflags.mk
@@ -1,15 +1,28 @@
 DEB_CPPFLAGS_MAINT_APPEND = -DTEST_MK=test
+DEB_CXXFLAGS_MAINT_SET := set
+DPKG_EXPORT_BUILDFLAGS := 1
 
 include $(srcdir)/mk/buildflags.mk
 
-test:
-	test "$(CFLAGS)" = "$(TEST_CFLAGS)"
-	test "$(CPPFLAGS)" = "$(TEST_CPPFLAGS) -DTEST_MK=test"
-	test "$(CXXFLAGS)" = "$(TEST_CXXFLAGS)"
-	test "$(DFLAGS)" = "$(TEST_DFLAGS)"
-	test "$(FCFLAGS)" = "$(TEST_FCFLAGS)"
-	test "$(FFLAGS)" = "$(TEST_FFLAGS)"
-	test "$(GCJFLAGS)" = "$(TEST_GCJFLAGS)"
-	test "$(LDFLAGS)" = "$(TEST_LDFLAGS)"
-	test "$(OBJCFLAGS)" = "$(TEST_OBJCFLAGS)"
-	test "$(OBJCXXFLAGS)" = "$(TEST_OBJCXXFLAGS)"
+vars := \
+  CFLAGS \
+  CPPFLAGS \
+  CXXFLAGS \
+  DFLAGS \
+  FCFLAGS \
+  FFLAGS \
+  GCJFLAGS \
+  LDFLAGS \
+  OBJCFLAGS \
+  OBJCXXFLAGS
+
+test: $(vars)
+CPPFLAGS:
+	test '$($@)' = '$(TEST_$@) -DTEST_MK=test'
+	test "$${$@}" = '$(TEST_$@) -DTEST_MK=test'
+CXXFLAGS:
+	test '$($@)' = set
+	test "$${$@}" = set
+$(filter-out CPPFLAGS CXXFLAGS,$(vars)):
+	test '$($@)' = '$(TEST_$@)'
+	test "$${$@}" = '$(TEST_$@)'
diff --git a/scripts/t/mk/buildtools.mk b/scripts/t/mk/buildtools.mk
index 0077791b5..375e2684c 100644
--- a/scripts/t/mk/buildtools.mk
+++ b/scripts/t/mk/buildtools.mk
@@ -1,35 +1,32 @@
+AR := overridden
+DPKG_EXPORT_BUILDTOOLS := 1
+
 include $(srcdir)/mk/buildtools.mk
 
-test:
-	test "$(AS)" = "$(TEST_AS)"
-	test "$(AS_FOR_BUILD)" = "$(TEST_AS_FOR_BUILD)"
-	test "$(CC)" = "$(TEST_CC)"
-	test "$(CC_FOR_BUILD)" = "$(TEST_CC_FOR_BUILD)"
-	test "$(CXX)" = "$(TEST_CXX)"
-	test "$(CXX_FOR_BUILD)" = "$(TEST_CXX_FOR_BUILD)"
-	test "$(OBJC)" = "$(TEST_OBJC)"
-	test "$(OBJC_FOR_BUILD)" = "$(TEST_OBJC_FOR_BUILD)"
-	test "$(OBJCXX)" = "$(TEST_OBJCXX)"
-	test "$(OBJCXX_FOR_BUILD)" = "$(TEST_OBJCXX_FOR_BUILD)"
-	test "$(GCJ)" = "$(TEST_GCJ)"
-	test "$(GCJ_FOR_BUILD)" = "$(TEST_GCJ_FOR_BUILD)"
-	test "$(F77)" = "$(TEST_F77)"
-	test "$(F77_FOR_BUILD)" = "$(TEST_F77_FOR_BUILD)"
-	test "$(FC)" = "$(TEST_FC)"
-	test "$(FC_FOR_BUILD)" = "$(TEST_FC_FOR_BUILD)"
-	test "$(LD)" = "$(TEST_LD)"
-	test "$(LD_FOR_BUILD)" = "$(TEST_LD_FOR_BUILD)"
-	test "$(STRIP)" = "$(TEST_STRIP)"
-	test "$(STRIP_FOR_BUILD)" = "$(TEST_STRIP_FOR_BUILD)"
-	test "$(OBJCOPY)" = "$(TEST_OBJCOPY)"
-	test "$(OBJCOPY_FOR_BUILD)" = "$(TEST_OBJCOPY_FOR_BUILD)"
-	test "$(OBJDUMP)" = "$(TEST_OBJDUMP)"
-	test "$(OBJDUMP_FOR_BUILD)" = "$(TEST_OBJDUMP_FOR_BUILD)"
-	test "$(NM)" = "$(TEST_NM)"
-	test "$(NM_FOR_BUILD)" = "$(TEST_NM_FOR_BUILD)"
-	test "$(AR)" = "$(TEST_AR)"
-	test "$(AR_FOR_BUILD)" = "$(TEST_AR_FOR_BUILD)"
-	test "$(RANLIB)" = "$(TEST_RANLIB)"
-	test "$(RANLIB_FOR_BUILD)" = "$(TEST_RANLIB_FOR_BUILD)"
-	test "$(PKG_CONFIG)" = "$(TEST_PKG_CONFIG)"
-	test "$(PKG_CONFIG_FOR_BUILD)" = "$(TEST_PKG_CONFIG_FOR_BUILD)"
+vars := $(foreach tool,\
+  AR \
+  AS \
+  CC \
+  CPP \
+  CXX \
+  F77 \
+  FC \
+  GCJ \
+  LD \
+  NM \
+  OBJC \
+  OBJCOPY \
+  OBJCXX \
+  OBJDUMP \
+  PKG_CONFIG \
+  RANLIB \
+  STRIP \
+,$(tool) $(tool)_FOR_BUILD)
+
+test: $(vars)
+AR AR_FOR_BUILD:
+	test '$($@)' = overridden
+	test "$${$@}" = overridden
+$(filter-out AR AR_FOR_BUILD,$(vars)):
+	test '$($@)' = '$(TEST_$@)'
+	test "$${$@}" = '$(TEST_$@)'
-- 
2.30.0

>From 44261047dd9d823d85f2727ca5c9247a61b2ba0f Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <nico...@debian.org>
Date: Thu, 11 Feb 2021 16:34:23 +0100
Subject: [PATCH 5/7] scripts/buildtools.mk: remove unneeded tests

The ?= had no effect when the previous test was succeeding.  Make that
explicit with an 'else'.

The 'ifdef' was always succeeding because previous stanza sets $1.
---
 scripts/mk/buildtools.mk | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/scripts/mk/buildtools.mk b/scripts/mk/buildtools.mk
index b2ab2a2ac..f05a9177e 100644
--- a/scripts/mk/buildtools.mk
+++ b/scripts/mk/buildtools.mk
@@ -37,16 +37,16 @@ define dpkg_buildtool_setvar
 ifeq (,$(findstring $(3),$(DEB_BUILD_OPTIONS)))
 ifeq ($(origin $(1)),default)
 $(1) = $(DEB_HOST_GNU_TYPE)-$(2)
-endif
+else
 $(1) ?= $(DEB_HOST_GNU_TYPE)-$(2)
+endif
 
 # On native build fallback to use TOOL if that's defined.
 ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
-ifdef $(1)
 $(1)_FOR_BUILD ?= $$($(1))
-endif
-endif
+else
 $(1)_FOR_BUILD ?= $(DEB_BUILD_GNU_TYPE)-$(2)
+endif
 else
 $(1) = :
 $(1)_FOR_BUILD = :
-- 
2.30.0

>From 6e5fc6c1a9976fd81ca8b66114e51bb3fc74abf8 Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <nicolas.bouleng...@free.fr>
Date: Sat, 13 Feb 2021 09:58:27 +0100
Subject: [PATCH 6/7] scripts: indents buildtools.mk

---
 scripts/mk/buildtools.mk | 44 ++++++++++++++++++++++------------------
 1 file changed, 24 insertions(+), 20 deletions(-)

diff --git a/scripts/mk/buildtools.mk b/scripts/mk/buildtools.mk
index f05a9177e..79c1520e0 100644
--- a/scripts/mk/buildtools.mk
+++ b/scripts/mk/buildtools.mk
@@ -34,28 +34,32 @@ include $(dpkg_datadir)/architecture.mk
 # not defined or contain the make built-in defaults. On native builds if
 # TOOL is defined and TOOL_FOR_BUILD is not, we fallback to use TOOL.
 define dpkg_buildtool_setvar
-ifeq (,$(findstring $(3),$(DEB_BUILD_OPTIONS)))
-ifeq ($(origin $(1)),default)
-$(1) = $(DEB_HOST_GNU_TYPE)-$(2)
-else
-$(1) ?= $(DEB_HOST_GNU_TYPE)-$(2)
-endif
 
-# On native build fallback to use TOOL if that's defined.
-ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
-$(1)_FOR_BUILD ?= $$($(1))
-else
-$(1)_FOR_BUILD ?= $(DEB_BUILD_GNU_TYPE)-$(2)
-endif
-else
-$(1) = :
-$(1)_FOR_BUILD = :
-endif
+  ifeq (,$(findstring $(3),$(DEB_BUILD_OPTIONS)))
+
+    ifeq ($(origin $(1)),default)
+      $(1) = $(DEB_HOST_GNU_TYPE)-$(2)
+    else
+      $(1) ?= $(DEB_HOST_GNU_TYPE)-$(2)
+    endif
+
+    # On native build fallback to use TOOL if that's defined.
+    ifeq ($(DEB_BUILD_GNU_TYPE),$(DEB_HOST_GNU_TYPE))
+      $(1)_FOR_BUILD ?= $$($(1))
+    else
+      $(1)_FOR_BUILD ?= $(DEB_BUILD_GNU_TYPE)-$(2)
+    endif
+
+  else
+    $(1) = :
+    $(1)_FOR_BUILD = :
+  endif
+
+  ifdef DPKG_EXPORT_BUILDTOOLS
+    export $(1)
+    export $(1)_FOR_BUILD
+  endif
 
-ifdef DPKG_EXPORT_BUILDTOOLS
-export $(1)
-export $(1)_FOR_BUILD
-endif
 endef
 
 $(eval $(call dpkg_buildtool_setvar,AS,as))
-- 
2.30.0

>From 25fd127a2d7a37bed787ab4cd521a91d40a0725b Mon Sep 17 00:00:00 2001
From: Nicolas Boulenguez <nico...@debian.org>
Date: Thu, 11 Feb 2021 16:26:50 +0100
Subject: [PATCH 7/7] scripts/mk: reduce the number of subprocesses

architecture.mk and buildflags.mk spawn less subshells, improving the
overall speed (the tests run twice faster according to bash time
builtin).

pkg-info.mk uses the same trick than buildflags.mk in order to spawn
at most one subshell. The performance gain is visible, but minor
because there are way less variables.
---
 scripts/mk/architecture.mk | 13 ++++++------
 scripts/mk/buildflags.mk   | 23 ++++++++++++++------
 scripts/mk/pkg-info.mk     | 43 +++++++++++++++++++++++++++++++-------
 3 files changed, 58 insertions(+), 21 deletions(-)

diff --git a/scripts/mk/architecture.mk b/scripts/mk/architecture.mk
index 2aa115822..9962a4a13 100644
--- a/scripts/mk/architecture.mk
+++ b/scripts/mk/architecture.mk
@@ -2,10 +2,9 @@
 # DEB_BUILD_* variables that dpkg-architecture can return. Existing values
 # of those variables are preserved as per policy.
 
-dpkg_lazy_eval ?= $$(or $$(value DPKG_CACHE_$(1)),$$(eval DPKG_CACHE_$(1) := $$(shell $(2)))$$(value DPKG_CACHE_$(1)))
-
-dpkg_architecture_setvar = export $(1) ?= $(call dpkg_lazy_eval,$(1),dpkg-architecture -q$(1))
-
-$(foreach machine,BUILD HOST TARGET,\
-  $(foreach var,ARCH ARCH_ABI ARCH_LIBC ARCH_OS ARCH_CPU ARCH_BITS ARCH_ENDIAN GNU_CPU GNU_SYSTEM GNU_TYPE MULTIARCH,\
-    $(eval $(call dpkg_architecture_setvar,DEB_$(machine)_$(var)))))
+# According to dpkg-architecture(1), the variables must always be
+# exported, so we need at least an external subprocess.
+# Attempt to set all variables with this subprocesses.
+# This also avoids maintaining a copy of the variable list here.
+# Each = is replaced with ?= in order to export existing overridden values.
+$(eval $(shell dpkg-architecture | sed 's/\([^=]*\)\(.*\)/$$(eval export \1?\2)/'))
diff --git a/scripts/mk/buildflags.mk b/scripts/mk/buildflags.mk
index cfeabda4f..7bf208cb8 100644
--- a/scripts/mk/buildflags.mk
+++ b/scripts/mk/buildflags.mk
@@ -17,11 +17,13 @@
 # This list is kept in sync with the default set of flags returned
 # by dpkg-buildflags.
 
-dpkg_lazy_eval ?= $$(or $$(value DPKG_CACHE_$(1)),$$(eval DPKG_CACHE_$(1) := $$(shell $(2)))$$(value DPKG_CACHE_$(1)))
-
 DPKG_BUILDFLAGS_LIST = CFLAGS CPPFLAGS CXXFLAGS OBJCFLAGS OBJCXXFLAGS \
                        GCJFLAGS DFLAGS FFLAGS FCFLAGS LDFLAGS
 
+# Accumulate the parameters for dpkg-buildflags, in case it is ever
+# called.
+
+DPKG_BUILDFLAGS_EXPORT_ENVVAR :=
 define dpkg_buildflags_export_envvar
 ifdef $(1)
 DPKG_BUILDFLAGS_EXPORT_ENVVAR += $(1)="$$(value $(1))"
@@ -34,11 +36,20 @@ $(foreach flag,$(DPKG_BUILDFLAGS_LIST),\
   $(foreach operation,SET STRIP APPEND PREPEND,\
     $(eval $(call dpkg_buildflags_export_envvar,DEB_$(flag)_MAINT_$(operation)))))
 
-dpkg_buildflags_setvar = $(1) = $(call dpkg_lazy_eval,$(1),$(DPKG_BUILDFLAGS_EXPORT_ENVVAR) dpkg-buildflags --get $(1))
-
-$(foreach flag,$(DPKG_BUILDFLAGS_LIST),\
-  $(eval $(call dpkg_buildflags_setvar,$(flag))))
+# This variable is only expanded on demand, and we ensure that it
+# happens at most once..
+dpkg-buildflags_run = $(eval $(shell \
+  $(DPKG_BUILDFLAGS_EXPORT_ENVVAR) dpkg-buildflags \
+  | sed 's/^\([^=]*\)\(.*\)/$$(eval \1:\2)/'))
 
 ifdef DPKG_EXPORT_BUILDFLAGS
+  # We must compute all values right now.
+  $(dpkg-buildflags_run)
   export $(DPKG_BUILDFLAGS_LIST)
+else
+  # Only run a subprocess when a variable is actually used,
+  # but then replace each recursive definition with a non-recursive one
+  # (and of course return the asked value).
+  $(foreach var,$(DPKG_BUILDFLAGS_LIST),\
+    $(eval $(var)=$$(dpkg-buildflags_run)$$($(var))))
 endif
diff --git a/scripts/mk/pkg-info.mk b/scripts/mk/pkg-info.mk
index bccde2317..9265f5787 100644
--- a/scripts/mk/pkg-info.mk
+++ b/scripts/mk/pkg-info.mk
@@ -12,16 +12,43 @@
 #   SOURCE_DATE_EPOCH: source release date as seconds since the epoch, as
 #     specified by <https://reproducible-builds.org/specs/source-date-epoch/>
 #     (since dpkg 1.18.8).
+#     If it is undefined, the date of the latest changelog entry is used.
+#     In both cases, the value is exported.
 
-dpkg_late_eval ?= $(or $(value DPKG_CACHE_$(1)),$(eval DPKG_CACHE_$(1) := $(shell $(2)))$(value DPKG_CACHE_$(1)))
 
-DEB_SOURCE = $(call dpkg_late_eval,DEB_SOURCE,dpkg-parsechangelog -SSource)
-DEB_VERSION = $(call dpkg_late_eval,DEB_VERSION,dpkg-parsechangelog -SVersion)
-DEB_VERSION_EPOCH_UPSTREAM = $(call dpkg_late_eval,DEB_VERSION_EPOCH_UPSTREAM,echo '$(DEB_VERSION)' | sed -e 's/-[^-]*$$//')
-DEB_VERSION_UPSTREAM_REVISION = $(call dpkg_late_eval,DEB_VERSION_UPSTREAM_REVISION,echo '$(DEB_VERSION)' | sed -e 's/^[0-9]*://')
-DEB_VERSION_UPSTREAM = $(call dpkg_late_eval,DEB_VERSION_UPSTREAM,echo '$(DEB_VERSION_EPOCH_UPSTREAM)' | sed -e 's/^[0-9]*://')
-DEB_DISTRIBUTION = $(call dpkg_late_eval,DEB_DISTRIBUTION,dpkg-parsechangelog -SDistribution)
+# This variable is only expanded on demand, and we ensure that it
+# happens at most once..
+dpkg-parsechangelog_run = $(eval $(shell dpkg-parsechangelog \
+                                   | sed -n '$(dpkg-parsechangelog_sed)'))
 
-SOURCE_DATE_EPOCH ?= $(call dpkg_late_eval,SOURCE_DATE_EPOCH,dpkg-parsechangelog -STimestamp)
+dpkg-parsechangelog_sed := \
+  s/^Source: \(.*\)/\
+    $$(eval DEB_SOURCE                    := \1)/p;\
+  s/^Version: \([0-9]*:\)\?\(.*\)\(-[^-]*\)$$/\
+    $$(eval DEB_VERSION                   := \1\2\3)\
+    $$(eval DEB_VERSION_EPOCH_UPSTREAM    := \1\2)\
+    $$(eval DEB_VERSION_UPSTREAM_REVISION := \2\3)\
+    $$(eval DEB_VERSION_UPSTREAM          := \2)/p;\
+  s/^Distribution: \(.*\)/\
+    $$(eval DEB_DISTRIBUTION              := \1)/p
+
+ifdef SOURCE_DATE_EPOCH
+  # Only parse the changelog if a variable is actually used,
+  # but then replace each recursive definition with a non-recursive one
+  # (and of course return the asked value).
+  $(foreach var,DEB_SOURCE \
+                DEB_VERSION \
+                DEB_VERSION_EPOCH_UPSTREAM \
+                DEB_VERSION_UPSTREAM_REVISION \
+                DEB_VERSION_UPSTREAM \
+                DEB_DISTRIBUTION,\
+    $(eval $(var) = $$(dpkg-parsechangelog_run)$$($(var))))
+else
+  # We must run a subshell in order to compute SOURCE_DATE_EPOCH,
+  # so we may as well set all variables.
+  dpkg-parsechangelog_sed += \
+    ;s/^Timestamp: \(.*\)/$$(eval SOURCE_DATE_EPOCH:=\1)/p
+  $(dpkg-parsechangelog_run)
+endif
 
 export SOURCE_DATE_EPOCH
-- 
2.30.0

Reply via email to