Re: GNU Make bug report: broken dry-run functionality with sub-make invocations

2022-03-17 Thread Paul Smith
On Thu, 2022-03-17 at 18:27 +, Martin Dorey wrote:
> 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.

Modern versions of make guarantee a canonical format of MAKEFLAGS such
that you can parse them relatively easily, and with confidence.

The details are in the manual I believe but the short is:

 * All options that have "short" variants with no arguments (for
   example --dry-run -> -n) are converted to the short variants and put
   into the first word, with no leading "-"
 * All other options are added after that.
 * Short options have a single dash prefix and if they have an argument
   it's attached to the option
 * Long options have a double-dash prefix (obviously) and if they have
   an argument it's attached to the option with an "="
 * Options that have both short and long forms, prefer the short form.

So, for -n, you can use:

$(findstring n,$(word 1,$(MAKEFLAGS)))

and it will expand to "n" if dry run is enabled (regardless of which
form the option was given in), or empty if not.

So, the OP could use something like this:

DRYRUN = $(findstring n,$(word 1,$(MAKEFLAGS)))

 main_target: create_logdirs
 $(MAKE) external_target $(if $(DRYRUN),,| tee logs/external_task.log)

There are other alternatives. For example, you could add "+" as a
prefix to the recipe in the create_logdirs so that the directories are
created even when "-n" is given.


But ultimately Martin's comment is correct: this is not a bug in make
and there's no possible way that make could do anything "better" than
what it does. At some level, especially if you're writing recursive
makefile environments, your recipes have to be written to be resilient
to the possibility that make was invoked with "-n".



Re: GNU Make bug report: broken dry-run functionality with sub-make invocations

2022-03-17 Thread Martin Dorey
> 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  on behalf of 
Ambrus Sumegi 
Sent: Thursday, March 17, 2022 08:59
To: bug-make@gnu.org 
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

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 

GNU Make bug report: broken dry-run functionality with sub-make invocations

2022-03-17 Thread Ambrus Sumegi
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
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
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.


Makefile
Description: Makefile