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:

NetBSD Home
NetBSD PR Database Search

(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.