For the record, I've thought of a sort-of-solution to the "would you have Make
parse the shell command" question over the weekend. If the sub-make was called
through a function rather than a variable, the whole issue could be a lot more
contained. Having $(make, "<arguments passed to sub-make>") as the canonical
form of invoking other Make instances could guarantee that no other program
gets called when the -n switch is used. This way any elaborate multi-line
command containing $(MAKE) could more or less be fixed with a sed command to
completely eliminate this problem class.
Of course, one could still do something like $(make, $(shell
("some_reckless_command")), but it would be more obvious, and Make could output
an explicit warning about a shell being called together with the sub-make
invocation, or even refuse to execute said shell call. Since on Fri 18/03/2022
20:14, [email protected]<mailto:[email protected]> pointed out that this is also a
potential security problem, a future release could deprecate the $(MAKE)
variable and switch to the function-based invocation, with shell calls disabled
within it by default for the sake of that extra bit of security.
From: Martin Dorey <[email protected]>
Sent: 17 March 2022 19:27
To: Ambrus Sumegi <[email protected]>; [email protected]
Subject: Re: GNU Make bug report: broken dry-run functionality with sub-make
invocations
> the statement after the pipe also gets executed
Would you have Make parse the shell command, assuming that SHELL isn't eg
/usr/bin/perl, splitting off anything after | and maybe ; and && and, why not,
||, so it only dry-runs the part of the command that invoked $(MAKE)? The
current behavior is documented,
https://www.gnu.org/software/make/manual/html_node/MAKE-Variable.html#MAKE-Variable
saying:
>> whenever a recipe line of a rule contains the variable MAKE, the flags '-t',
>> '-n' and '-q' do not apply to that line
To put it another way: the Makefile needs to cope. Not doing the tee if the
directory doesn't exist would perhaps be most straightforward:
martind@sirius:~/tmp/ambrus-sumegi-2022-03-17$ diff -u Makefile{.orig,}
--- Makefile.orig 2022-03-17 11:13:46.000328340 -0700
+++ Makefile 2022-03-17 11:15:04.980482898 -0700
@@ -8,4 +8,4 @@
.PHONY: main_target
main_target: create_logdirs
- $(MAKE) external_target | tee logs/external_task.log
+ $(MAKE) external_target | { if test -d logs; then tee logs/external_task.log;
else cat; fi; }
martind@sirius:~/tmp/ambrus-sumegi-2022-03-17$
... though that means writing to the log with -n if the directory does exist,
which is perhaps undesirable. You could scrape the --dry-run flag out of
MAKEFLAGS, where it seems to get turned into n:
martind@sirius:~/tmp/ambrus-sumegi-2022-03-17$ diff -u Makefile{.orig,}
--- Makefile.orig 2022-03-17 11:13:46.000328340 -0700
+++ Makefile 2022-03-17 11:23:29.579910454 -0700
@@ -8,4 +8,4 @@
.PHONY: main_target
main_target: create_logdirs
- $(MAKE) external_target | tee logs/external_task.log
+ $(MAKE) external_target $(if $(findstring n,$(filter-out
--%,$(MAKEFLAGS))),,| tee logs/external_task.log)
martind@sirius:~/tmp/ambrus-sumegi-2022-03-17$
That coped with -nj --no-print-directory on the one version of Make that I
tested it with, but I don't know how portable that would prove.
Thank you for a nicely written up report with a minimal test case.
________________________________
From: Bug-make
<[email protected]<mailto:[email protected]>>
on behalf of Ambrus Sumegi
<[email protected]<mailto:[email protected]>>
Sent: Thursday, March 17, 2022 08:59
To: [email protected]<mailto:[email protected]>
<[email protected]<mailto:[email protected]>>
Subject: GNU Make bug report: broken dry-run functionality with sub-make
invocations
***** EXTERNAL EMAIL *****
Dear Devs,
I stumbled upon a rather rare case where Make produces a false error with the
--dry-run switch. I've attached a sample Makefile for reproduction.
The output of make main_target with this file is the following:
$ make main_target
mkdir logs
make external_target | tee logs/external_task.log
make[1]: Entering directory '/tmp/21176961.tmpdir/bugrepro'
This could be in a separate file somewhere
make[1]: Leaving directory '/tmp/21176961.tmpdir/bugrepro'
Nothing interesting there. But with the -n or --dry-run switch I get:
$ make main_target -n
mkdir logs
make external_target | tee logs/external_task.log
tee: logs/external_task.log: No such file or directory
make[1]: Entering directory '/tmp/21176961.tmpdir/bugrepro'
echo "This could be in a separate file somewhere"
make[1]: Leaving directory '/tmp/21176961.tmpdir/bugrepro'
make: *** [Makefile:11: main_target] Error 1
I get that the sub-make invocation gets executed with the switch passed to it
as well, and that is correct functionality. But then the statement after the
pipe also gets executed and throws an error about the missing log directory due
to the prerequisite target not having been run. This causes false failures in
release checks that use the --dry-run option of Make.
This behavior is the same in both versions of GNU make that I have access to on
the production system I'm using, 3.82 and 4.3
$ uname -r
3.10.0-693.21.1.el7.x86_64
$ make --version
GNU Make 3.82
Built for x86_64-redhat-linux-gnu
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
http://gnu.org/licenses/gpl.html<https://nam04.safelinks.protection.outlook.com/?url=http%3A%2F%2Fgnu.org%2Flicenses%2Fgpl.html&data=04%7C01%7CMartin.Dorey%40hitachivantara.com%7C4d9a04e9960e410518da08da083966b6%7C18791e1761594f52a8d4de814ca8284a%7C0%7C0%7C637831339882701632%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=KpSFe0FVFzsYlsMTYPDwYOxRRfw26gNyhcXRaXwdesI%3D&reserved=0>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
# (...) Loading other version
$ make --version
GNU Make 4.3
Built for x86_64-pc-linux-gnu
Copyright (C) 1988-2020 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
http://gnu.org/licenses/gpl.html<https://nam04.safelinks.protection.outlook.com/?url=http%3A%2F%2Fgnu.org%2Flicenses%2Fgpl.html&data=04%7C01%7CMartin.Dorey%40hitachivantara.com%7C4d9a04e9960e410518da08da083966b6%7C18791e1761594f52a8d4de814ca8284a%7C0%7C0%7C637831339882701632%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=KpSFe0FVFzsYlsMTYPDwYOxRRfw26gNyhcXRaXwdesI%3D&reserved=0>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
IMPORTANT NOTICE: The contents of this email and any attachments are
confidential and may also be privileged. If you are not the intended recipient,
please notify the sender immediately and do not disclose the contents to any
other person, use it for any purpose, or store or copy the information in any
medium. Thank you.
IMPORTANT NOTICE: The contents of this email and any attachments are
confidential and may also be privileged. If you are not the intended recipient,
please notify the sender immediately and do not disclose the contents to any
other person, use it for any purpose, or store or copy the information in any
medium. Thank you.