NetBSD Problem Report #59962
From www@netbsd.org Thu Feb 5 02:40:29 2026
Return-Path: <www@netbsd.org>
Received: from mail.netbsd.org (mail.netbsd.org [199.233.217.200])
(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)
key-exchange X25519 server-signature RSA-PSS (2048 bits)
client-signature RSA-PSS (2048 bits))
(Client CN "mail.netbsd.org", Issuer "R13" (verified OK))
by mollari.NetBSD.org (Postfix) with ESMTPS id C3E731A923D
for <gnats-bugs@gnats.NetBSD.org>; Thu, 5 Feb 2026 02:40:29 +0000 (UTC)
Message-Id: <20260205024028.8976D1A923E@mollari.NetBSD.org>
Date: Thu, 5 Feb 2026 02:40:28 +0000 (UTC)
From: campbell+netbsd@mumble.net
Reply-To: campbell+netbsd@mumble.net
To: gnats-bugs@NetBSD.org
Subject: make(1): grouped target rules for batch recipes
X-Send-Pr-Version: www-1.0
X-From4GNATS: "campbell+netbsd@mumble.net via gnats" <gnats-admin@NetBSD.org>
>Number: 59962
>Category: bin
>Synopsis: make(1): grouped target rules for batch recipes
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: rillig
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Thu Feb 05 02:45:00 +0000 2026
>Last-Modified: Thu Feb 05 07:15:01 +0000 2026
>Originator: Taylor R Campbell
>Release: current, 11, 10, 9, ...
>Organization:
netbsd.c netbsd.h: foundation.y
>Environment:
>Description:
Tools like lex(1) and yacc(1) produce multiple output files
foo.c and foo.h from a single input file foo.l/.y. (Other
examples abound, like TeX, Heimdal compile_et, and so on.)
For _sequentiail_ make(1), this can be expressed with a rule
having multiple targets:
foo.tab.c foo.tab.h: foo.y
yacc -b foo foo.y
However, this doesn't work for _parallel_ make(1): it may
execute the same recipe twice for foo.tab.c and foo.tab.h
independently.
GNU make(1) has sprouted an alternative syntax `&:' to mean
that foo.tab.c and foo.tab.h are both produced simultaneously
by a single execution of the recipe (which, of course, can't
vary according to the target by using $@ or $* or similar), and
in parallel builds, it only executes the rule once for either
target:
foo.tab.c foo.tab.h &: foo.y
yacc -b foo foo.y
We should adopt this.
(I'm not entirely clear on why the traditional parallel
behaviour of multi-target `:' rules is useful, really, except
when it's actually a different recipe for each target because
it varies by ${.TARGET}.)
>How-To-Repeat:
$ cat Makefile
all: .PHONY
all: c
.if !make(clean)
.BEGIN:
echo 0 >counter
.END:
@case $$(cat counter) in \
0|1) echo ok;; \
*) echo -n clobbered: ''; cat counter; exit 1;; \
esac
.endif
clean: .PHONY
@-rm -f a b c
a b:
@exec 3>counter; flock 3; c=$$(cat counter); echo $$((c + 1)) >&3
echo hello >a
echo world >b
c: a b
echo done >c
$ make clean && make
echo 0 >counter
echo hello >a
echo world >b
echo done >c
ok
$ make clean && make -j4
echo 0 >counter
--- a ---
--- b ---
echo hello >a
echo world >b
--- a ---
echo hello >a
echo world >b
--- c ---
echo done >c
clobbered: 2
*** Error code 1
Stop.
make: stopped in /tmp/riastradh/20260204/test
$
>Fix:
Yes, please!
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: bin-bug-people->rillig
Responsible-Changed-By: riastradh@NetBSD.org
Responsible-Changed-When: Thu, 05 Feb 2026 03:14:20 +0000
Responsible-Changed-Why:
Can I interest you in this proposal?
From: Taylor R Campbell <riastradh@NetBSD.org>
To: gnats-bugs@NetBSD.org, netbsd-bugs@NetBSD.org
Cc: Roland Illig <rillig@NetBSD.org>
Subject: Re: bin/59962: make(1): grouped target rules for batch recipes
Date: Thu, 5 Feb 2026 04:16:39 +0000
Documentation for the GNU make grouped target rule syntax:
https://www.gnu.org/software/make/manual/html_node/Multiple-Targets.html#Ru=
les-with-Grouped-Targets
From: mlelstv@serpens.de (Michael van Elst)
To: gnats-bugs@netbsd.org
Cc:
Subject: Re: bin/59962: make(1): grouped target rules for batch recipes
Date: Thu, 5 Feb 2026 07:11:10 -0000 (UTC)
gnats-admin@NetBSD.org ("campbell+netbsd@mumble.net via gnats") writes:
> Tools like lex(1) and yacc(1) produce multiple output files
> foo.c and foo.h from a single input file foo.l/.y. (Other
> examples abound, like TeX, Heimdal compile_et, and so on.)
> For _sequentiail_ make(1), this can be expressed with a rule
> having multiple targets:
>foo.tab.c foo.tab.h: foo.y
> yacc -b foo foo.y
> However, this doesn't work for _parallel_ make(1): it may
> execute the same recipe twice for foo.tab.c and foo.tab.h
> independently.
make behaves the same for sequential and parallel runs.
A target list like:
a b: sources
make_a
make_b
is the same as
a: sources
make_a
make_b
b: sources
make_a
make_b
When done sequentially, b is created as a side effect of
building a, and building b is then skipped as the dependency
for b is already fulfilled.
When done in parallel, it's a race that is usually lost, and
the actions for both targets are executed in parallel.
A workaround is to specify an order like:
.ORDER: a b
a b: sources
make_a
make_b
Which removes the race.
It just looks like make would support a list of targets for
a rule while in reality it just knows single files.
>Unformatted:
(Contact us)
$NetBSD: query-full-pr,v 1.49 2026/05/14 01:52:41 riastradh Exp $
$NetBSD: gnats_config.sh,v 1.10 2026/05/13 22:00:09 riastradh Exp $
Copyright © 1994-2026
The NetBSD Foundation, Inc. ALL RIGHTS RESERVED.