Hi,
Paul Smith, the GNU make maintainer, gives this recommendation how
to disable built-in rules and thus speed up make's processing [1]:
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
My recommendation has been to disable the built-in rules directly, if
you don't need them. For example you can use:
.SUFFIXES:
to disable most of the built in rules (this is a POSIX standard
facility so it's helpful even for other versions of make).
Unfortunately that doesn't fix all problems because GNU Make also has a
few built-in rules that are defined using pattern rules (because suffix
rules are not powerful enough). So a full list of "turn it all off"
would be this:
.SUFFIXES:
%:: %,v
%:: RCS/%,v
%:: RCS/%
%:: s.%
%:: SCCS/s.%
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
GNU Automake already emits the '.SUFFIXES:' line. To optimize things
for GNU make, it should also emit the remaining part.
It has no effect with non-GNU make [2].
The effect, for example in gettext's gettext-runtime/src directory, is
that
- The output of "make -n -d" shrinks from 11028 lines to 4928 lines.
- The number of 'stat()' calls made by "make -n" shrinks from 188 to 178.
(make no longer tests whether various directories have an 'RCS' or 'SCCS'
subdirectory.)
Patch is attached.
Bruno
[1] https://lists.gnu.org/archive/html/bug-make/2023-07/msg00063.html
[2] https://lists.gnu.org/archive/html/bug-make/2023-07/msg00067.html
>From c8ca5b95a0c322177ba0fb55ddabc1c92fa04f10 Mon Sep 17 00:00:00 2001
From: Bruno Haible <[email protected]>
Date: Thu, 20 Jul 2023 11:50:51 +0200
Subject: [PATCH] Speed up GNU make's internal processing.
Based on a recommendation by Paul Smith in
<https://lists.gnu.org/archive/html/bug-make/2023-07/msg00063.html>.
* lib/am/footer.am: Disable GNU make's internal pattern rules.
* lib/Automake/Rule.pm (_conditionals_for_rule): Add special handling
for these pattern rules from footer.am.
(define): Likewise.
* t/nodep.sh: Update test.
---
lib/Automake/Rule.pm | 39 +++++++++++++++++++++++----------------
lib/am/footer.am | 11 +++++++++++
t/nodep.sh | 2 +-
3 files changed, 35 insertions(+), 17 deletions(-)
diff --git a/lib/Automake/Rule.pm b/lib/Automake/Rule.pm
index 9f72d2728..52ee3be4a 100644
--- a/lib/Automake/Rule.pm
+++ b/lib/Automake/Rule.pm
@@ -695,6 +695,9 @@ sub _conditionals_for_rule ($$$$)
return $cond if !$message; # No ambiguity.
+ # Don't coalesce the several pattern rules from footer.am into a single one.
+ return $cond if $target eq "%:" && $where->get =~ /\/am\/footer\.am$/;
+
if ($owner == RULE_USER)
{
# For user rules, just diagnose the ambiguity.
@@ -764,23 +767,27 @@ sub define ($$$$$)
my $tdef = _rule_defn_with_exeext_awareness ($target, $cond, $where);
- # A GNU make-style pattern rule has a single "%" in the target name.
- msg ('portability', $where,
- "'%'-style pattern rules are a GNU make extension")
- if $target =~ /^[^%]*%[^%]*$/;
-
- # See whether this is a duplicated target declaration.
- if ($tdef)
+ # The pattern rules in footer.am look like duplicates, but really aren't.
+ if ($source !~ /\/am\/footer\.am$/)
{
- # Diagnose invalid target redefinitions, if any. Note that some
- # target redefinitions are valid (e.g., for multiple-targets
- # pattern rules).
- _maybe_warn_about_duplicated_target ($target, $tdef, $source,
- $owner, $cond, $where);
- # Return so we don't redefine the rule in our tables, don't check
- # for ambiguous condition, etc. The rule will be output anyway
- # because '&read_am_file' ignores the return code.
- return ();
+ # A GNU make-style pattern rule has a single "%" in the target name.
+ msg ('portability', $where,
+ "'%'-style pattern rules are a GNU make extension")
+ if $target =~ /^[^%]*%[^%]*$/;
+
+ # See whether this is a duplicated target declaration.
+ if ($tdef)
+ {
+ # Diagnose invalid target redefinitions, if any. Note that some
+ # target redefinitions are valid (e.g., for multiple-targets
+ # pattern rules).
+ _maybe_warn_about_duplicated_target ($target, $tdef, $source,
+ $owner, $cond, $where);
+ # Return so we don't redefine the rule in our tables, don't check
+ # for ambiguous condition, etc. The rule will be output anyway
+ # because '&read_am_file' ignores the return code.
+ return ();
+ }
}
my $rule = _crule $target;
diff --git a/lib/am/footer.am b/lib/am/footer.am
index 9715c826c..388defb14 100644
--- a/lib/am/footer.am
+++ b/lib/am/footer.am
@@ -17,3 +17,14 @@
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:
+
+# Tell GNU make to disable its built-in pattern rules.
+## This reduces make's internal processing.
+## Recommended by Paul Smith in
+## <https://lists.gnu.org/archive/html/bug-make/2023-07/msg00063.html>.
+## These rules have no effect on non-GNU make implementations.
+%:: %,v
+%:: RCS/%,v
+%:: RCS/%
+%:: s.%
+%:: SCCS/s.%
diff --git a/t/nodep.sh b/t/nodep.sh
index 4201c8ead..0174b838e 100644
--- a/t/nodep.sh
+++ b/t/nodep.sh
@@ -37,6 +37,6 @@ $ACLOCAL
$AUTOMAKE
sed 's/printf .*%s//' Makefile.in > Makefile.tmp
-grep '%' Makefile.tmp && exit 1
+grep -v '^%::' Makefile.tmp | grep '%' && exit 1
:
--
2.34.1