Dear Recipient,

bug#45756 that you reported has been fixed. A patch is attacked for your convenience. Thank you for contributing.

I have decided to follow the advice in the discussion thread and gate this functionality behind an explicit ./configure flag. I believe that this is the cleanest way to introduce it without breaking unrelated things. Please let me know if this is the solution that oyu had in mind. Thanks.

-------- Forwarded Message --------
Subject: [automake-commit] 02/02: build: add opt-in compiler jobserver support (bug#45756)
Date: Mon, 19 Oct 2026 07:39:44 -0400
From: Kamila Szewczyk <[email protected]>
Reply-To: [email protected]
To: [email protected]

iczelia pushed a commit to branch master
in repository automake.

View the commit online:
https://git.savannah.gnu.org/gitweb/?p=automake.git;a=commitdiff;h=88ef2eb74d39fcab1065f231f3446fa2d420278d

commit 88ef2eb74d39fcab1065f231f3446fa2d420278d
Author: Kamila Szewczyk <[email protected]>
AuthorDate: Mon Oct 19 13:39:28 2026 +0200

     build: add opt-in compiler jobserver support (bug#45756)
* m4/jobserver.m4 (_AM_JOBSERVER): Add --enable-jobserver and define AM_JOBSERVER. Require GNU make when enabled.
    * m4/init.m4 (AM_INIT_AUTOMAKE): Require _AM_JOBSERVER.
    * m4/local.mk: Distribute the new macro.
* bin/automake.in (handle_languages): Prefix object compilation recipes, accounting for depcomp continuation lines.
    * lib/am/program.am: Prefix program link commands.
    * lib/am/ltlibrary.am: Prefix Libtool library link commands.
* t/jobserver.sh: Test descriptor inheritance, dependency tracking, Libtool, silent rules, and non-executing make modes.
    * t/list-of-tests.mk: Register it.
    * doc/automake.texi (Linking): Document the option.
    * NEWS: Mention the feature.
---
 NEWS                |   5 ++
 bin/automake.in     |  11 +++++
 doc/automake.texi   |  22 +++++++++
 lib/am/ltlibrary.am |   2 +-
 lib/am/program.am   |   2 +-
 m4/init.m4          |   1 +
 m4/jobserver.m4     |  29 ++++++++++++
 m4/local.mk         |   1 +
t/jobserver.sh | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 t/list-of-tests.mk  |   1 +
 10 files changed, 201 insertions(+), 2 deletions(-)

diff --git a/NEWS b/NEWS
index 2a7cb9c97..094b08e79 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,11 @@ New in 1.20 (????-??-??):
  * New features added
 +  - New configure option --enable-jobserver lets compilers and linkers
+    inherit GNU make's pipe jobserver, for example for GCC's
+    -flto=jobserver.  Dry-run, question, and touch modes still do not
+    run these commands.  (bug#45756)
+
   - New option delete-on-error.  It emits the .DELETE_ON_ERROR special
     target in the generated Makefile.in, instructing make to delete
     the target when its recipe fails after having modified it.  A failed
diff --git a/bin/automake.in b/bin/automake.in
index 5dc901f47..8ae981a30 100644
--- a/bin/automake.in
+++ b/bin/automake.in
@@ -1393,6 +1393,17 @@ sub handle_languages ()
          ? $verbose : verbose_nodep_flag ($lang->ccer || 'GEN');
        my $silent = silent_flag ();
 +        if ($rule_file eq 'depend2')
+          {
+            $verbose = '$(AM_JOBSERVER)' . $verbose;
+            # With depcomp, the compiler continues a recipe whose first
+            # line already has the prefix; do not insert another '+'.
+            $verbose_nodep = ($AMDEP eq 'FALSE') ? $verbose
+              : '$(AM_JOBSERVER' . subst ('am__nodep') . ')'
+                . $verbose_nodep;
+            define_variable ('AM_JOBSERVER_no', '', INTERNAL);
+          }
+
        my %transform = ('EXT'     => $ext,
                         'PFX'     => $pfx,
                         'FPFX'    => $fpfx,
diff --git a/doc/automake.texi b/doc/automake.texi
index 4036f6f5c..072d76409 100644
--- a/doc/automake.texi
+++ b/doc/automake.texi
@@ -5088,6 +5088,28 @@ third-party libraries. If you follow this rule, the default value of
 omit the other ones.
  +@cindex Jobserver, compiler and linker access
+@opindex --enable-jobserver
+@opindex --disable-jobserver
+@vindex AM_JOBSERVER
+To let compilers and linkers share GNU make's parallel job limit, users
+can configure a package with @option{--enable-jobserver}, then build it
+with @samp{make -j@var{N}}.  This is useful, for example, with GCC's
+@option{-flto=jobserver}.  The option requires GNU make and is disabled
+by default; @option{--disable-jobserver} explicitly disables it.
+
+When enabled, Automake prefixes object compilation and program and
+Libtool library linking recipes with @samp{+}, allowing them to inherit
+the file descriptors of a pipe-based jobserver.  The prefix is omitted
+when @command{make} is run with @option{-n}, @option{-q}, or @option{-t},
+so these modes do not execute the compiler or linker.  This also works
+with silent rules and dependency tracking.  It does not enable link-time
+optimization itself, nor does it change user-written recipes.
+
+The recipe prefix is supplied by @code{AM_JOBSERVER}.  After configuring
+with this option, use the same GNU make implementation for the build;
+set @code{MAKE} when running @command{configure} if necessary.
+
 @node Conditional Sources
 @subsection Conditional compilation of sources
 diff --git a/lib/am/ltlibrary.am b/lib/am/ltlibrary.am
index b67db5c26..33846d6b5 100644
--- a/lib/am/ltlibrary.am
+++ b/lib/am/ltlibrary.am
@@ -15,4 +15,4 @@
 ## along with this program.  If not, see <https://www.gnu.org/licenses/>.
%LTLIBRARY%: $(%XLTLIBRARY%_OBJECTS) $(%XLTLIBRARY%_DEPENDENCIES) $(EXTRA_%XLTLIBRARY%_DEPENDENCIES) %DIRSTAMP% - %VERBOSE%$(%XLINK%) %RPATH% $(%XLTLIBRARY%_OBJECTS) $(%XLTLIBRARY%_LIBADD) $(LIBS) + $(AM_JOBSERVER)%VERBOSE%$(%XLINK%) %RPATH% $(%XLTLIBRARY%_OBJECTS) $(%XLTLIBRARY%_LIBADD) $(LIBS)
diff --git a/lib/am/program.am b/lib/am/program.am
index b05795303..1254cc680 100644
--- a/lib/am/program.am
+++ b/lib/am/program.am
@@ -21,4 +21,4 @@
 ## Or maybe not... sadly, incremental linkers are rarer than losing
 ## systems.
        @rm -f %PROGRAM%%EXEEXT%
-       %VERBOSE%$(%XLINK%) $(%XPROGRAM%_OBJECTS) $(%XPROGRAM%_LDADD) $(LIBS)
+ $(AM_JOBSERVER)%VERBOSE%$(%XLINK%) $(%XPROGRAM%_OBJECTS) $(%XPROGRAM%_LDADD) $(LIBS)
diff --git a/m4/init.m4 b/m4/init.m4
index 61e911811..afd43b70a 100644
--- a/m4/init.m4
+++ b/m4/init.m4
@@ -136,6 +136,7 @@ fi
 AC_SUBST([CSCOPE])
  AC_REQUIRE([_AM_SILENT_RULES])dnl
+AC_REQUIRE([_AM_JOBSERVER])dnl
 dnl The testsuite driver may need to know about EXEEXT, so add the
 dnl 'am__EXEEXT' conditional if _AM_COMPILER_EXEEXT was seen.  This
 dnl macro is hooked onto _AC_COMPILER_EXEEXT early, see below.
diff --git a/m4/jobserver.m4 b/m4/jobserver.m4
new file mode 100644
index 000000000..582301657
--- /dev/null
+++ b/m4/jobserver.m4
@@ -0,0 +1,29 @@
+# Enable compiler access to GNU make's jobserver.       -*- Autoconf -*-
+# Copyright (C) 2026 Free Software Foundation, Inc.
+#
+# This file is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# _AM_JOBSERVER
+# -------------
+AC_DEFUN([_AM_JOBSERVER],
+[AC_ARG_ENABLE([jobserver],
+  [AS_HELP_STRING([--enable-jobserver],
+    [let compilers and linkers use the GNU make jobserver])],
+  [], [enable_jobserver=no])
+AM_JOBSERVER=
+AS_CASE([$enable_jobserver],
+  [yes], [
+ AS_IF([${MAKE-make} --version 2>/dev/null | grep 'GNU Make' >/dev/null],
+      [], [AC_MSG_ERROR([--enable-jobserver requires GNU make])])
+    dnl MAKEFLAGS begins with the single-letter flags, without a dash.
+    dnl Prefix a dash so firstword does not pick up a later option or
+    dnl variable assignment when there are no single-letter flags.
+    dnl Do not mark commands recursive under -n, -q, or -t.
+ AM_JOBSERVER='$(if $(findstring n,$(firstword -$(MAKEFLAGS)))$(findstring q,$(firstword -$(MAKEFLAGS)))$(findstring t,$(firstword -$(MAKEFLAGS))),,+)'
+  ],
+  [no], [],
+  [AC_MSG_ERROR([bad value '$enable_jobserver' for --enable-jobserver])])
+AC_SUBST([AM_JOBSERVER])
+])
diff --git a/m4/local.mk b/m4/local.mk
index 6b76fd2b9..60327d00d 100644
--- a/m4/local.mk
+++ b/m4/local.mk
@@ -35,6 +35,7 @@ dist_automake_ac_DATA = \
   %D%/gcj.m4 \
   %D%/init.m4 \
   %D%/install-sh.m4 \
+  %D%/jobserver.m4 \
   %D%/lead-dot.m4 \
   %D%/lex.m4 \
   %D%/lispdir.m4 \
diff --git a/t/jobserver.sh b/t/jobserver.sh
new file mode 100644
index 000000000..1c29fb02d
--- /dev/null
+++ b/t/jobserver.sh
@@ -0,0 +1,129 @@
+#! /bin/sh
+# Copyright (C) 2026 Free Software Foundation, Inc.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+# Compilers and linkers can inherit the pipe jobserver without running
+# under make -n, -q, or -t (bug#45756).
+
+required='cc GNUmake libtoolize'
+. test-init.sh
+
+cat >> configure.ac <<'END'
+AC_PROG_CC
+AM_PROG_AR
+LT_INIT
+AC_OUTPUT
+END
+
+cat > Makefile.am <<'END'
+bin_PROGRAMS = foo bar
+foo_SOURCES = foo.c
+bar_SOURCES = foo.c
+bar_CFLAGS = $(AM_CFLAGS)
+noinst_LTLIBRARIES = libfoo.la
+libfoo_la_SOURCES = foo.c
+libfoo_la_CFLAGS = $(AM_CFLAGS)
+END
+
+echo 'int main (void) { return 0; }' > foo.c
+
+# Check the descriptors themselves, independently of compiler LTO support.
+cat > check-jobserver.c <<'END'
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <fcntl.h>
+int main (void)
+{
+  const char *flags = getenv ("MAKEFLAGS");
+  const char *p;
+  int r, w;
+  if (!flags) return 1;
+  p = strstr (flags, "--jobserver-auth=");
+  if (!p) p = strstr (flags, "--jobserver-fds=");
+  if (!p || sscanf (strchr (p, '=') + 1, "%d,%d", &r, &w) != 2)
+    return 1;
+  return fcntl (r, F_GETFD) < 0 || fcntl (w, F_GETFD) < 0;
+}
+END
+$CC -o check-jobserver check-jobserver.c
+
+cat > cc-wrapper <<'END'
+#!/bin/sh
+./check-jobserver || exit 99
+echo invoked >> compiler.log
+exec "$@"
+END
+
+cat > lt-wrapper <<'END'
+#!/bin/sh
+./check-jobserver || exit 99
+echo invoked >> libtool.log
+exec "$@"
+END
+
+libtoolize
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE -a
+
+# GNU make 4.4 defaults to a FIFO, which does not need inherited fds.
+# Force the pipe jobserver there; older versions already use pipes.
+run_make -O -- --help
+jobserver_style=
+if grep 'jobserver-style' stdout; then
+  jobserver_style=--jobserver-style=pipe
+fi
+
+for deps in none fast slow; do
+  case $deps in
+    none) ./configure --enable-jobserver --disable-dependency-tracking;;
+    fast) ./configure --enable-jobserver --enable-dependency-tracking;;
+    slow) ./configure --enable-jobserver --enable-dependency-tracking \
+            am_cv_CC_dependencies_compiler_type=gcc;;
+  esac
+  for verbosity in 0 1; do
+    rm -f compiler.log libtool.log
+ run_make -M -j2 $jobserver_style V=$verbosity CC="$SHELL ./cc-wrapper $CC" \
+      LIBTOOL="$SHELL ./lt-wrapper $SHELL ./libtool"
+    test $(wc -l < compiler.log) -ge 5
+    test $(wc -l < libtool.log) -eq 4
+    run_make clean
+
+    for mode in -n -q -t -kn -kq -kt; do
+      rm -f compiler.log libtool.log
+      run_make -M -e IGNORE -j2 $jobserver_style $mode V=$verbosity \
+        CC="$SHELL ./cc-wrapper $CC" \
+        LIBTOOL="$SHELL ./lt-wrapper $SHELL ./libtool"
+      case $mode in
+        *q) test "$am_make_rc" -eq 1;;
+        *) test "$am_make_rc" -eq 0;;
+      esac
+      test ! -e libtool.log
+      test ! -e compiler.log
+      run_make clean
+    done
+  done
+done
+
+for option in '' --disable-jobserver; do
+  ./configure $option
+  # Default configuration leaves compiler recipes non-recursive.
+  run_make -M -e FAIL -j2 $jobserver_style CC="$SHELL ./cc-wrapper $CC"
+done
+
+./configure --enable-jobserver=invalid && exit 1
+
+:
diff --git a/t/list-of-tests.mk b/t/list-of-tests.mk
index 243818342..05775fc1a 100644
--- a/t/list-of-tests.mk
+++ b/t/list-of-tests.mk
@@ -603,6 +603,7 @@ t/javadir-undefined.sh \
 t/javaflags.sh \
 t/javaprim.sh \
 t/javasubst.sh \
+t/jobserver.sh \
 t/ldadd.sh \
 t/ldflags.sh \
 t/lex-args.sh \

Attachment: OpenPGP_0xC868F0B6DE38409D.asc
Description: OpenPGP public key

Attachment: OpenPGP_signature.asc
Description: OpenPGP digital signature

Reply via email to