What do you mean by "I doubt that this is safe now"? Do you mean that
Automake will probably generate standard recipes which break if I turn
those flags on? Or do you only mean that it is easy for me to write
unsafe code in my own makefile recipes?
[...]
I *also* mean that it would be easy for you to write unsafe code in your own
recipes.
Like I said, I have the opposite opinion: not turning on errexit, nounset and
pipefail in your recipes maximises chances of writing unsafe (non robust) code.
Or maybe you are conflating 'unsafe' and 'portable', which I wouldn't, see
below.
My code does not have to be that portable, Bash is available all over
the place, and reasonable shells should have supported those flags
since many years now, much earlier than POSIX Issue 8. I would rather
lose some portability than write brittle scripts and effectively say
"if the shell does not support it, then silently ignore any eventual
errors".
"lose some portability" is not what we do in auto*.
I do not believe that robustness should fall victim to portability.
It is perfectly possible to write robust shell code without those options, as I already
wrote: "A code generator may be able to generate code to check every possible error,
but when writing shell scripts manually, that is unfeasible. It would make the code too
long and hard to maintain."
That is, Automake could generate robust shell code which does not use those
flags. I mean, Automake can generate extra code to check all exit codes from
all commands (line errexit does automatically), and in all pipeline stages
(like pipefail does automatically), using standard, old POSIX features.
Automake could also generate code which checks that all variables are properly
defined before using them (like nounset does automatically), but that would
only be necessary for variables which come from outside (if any), as the code
that Automake generates should always be correct and not forget to set a
necessary variable before using it. I would still check often, at least in
debug builds, to make developing Automake easier. Using erroneously unset
variables (like a misspelling in a variable name) is a common source of bugs.
I suspect Automake does not currently generate such robust shell code, especially if Automake uses ";
\" instead of "&& \" at the end of each line. I hope you can at least confirm the
current state of affairs.
"turn the options on whenever possible" gets you the benefits you want
in contexts where they work, and degrades gracefully in contexts where
they don't; that's what we do in auto*.
I do not think that "degrading gracefully" properly conveys the situation here. You can degrade image quality,
execution speed, floating-point precision, etc., but you not degrade concepts likes "robustness" or
"correctness". In this case, your code is not "degraded", but no longer robust, which is a more serious
problem. The situation is more like "Automake generates more or less brittle code, depending on the shell you use, without
documenting with which shells or shell versions the generated code is somewhat less brittle".
I wouldn't waste time in making Automake generate code which is less brittle if
you turn on errexit etc. Instead, I would make Automake generate robust shell
code no matter what.
Basically, I see the following alternatives:
Alternative 1) Automake should generate really robust shell code which always
runs without errexit, etc., like in the past. Always having the same flags (all
3 off) would simplify the Automake implementation.
Alternative 2) Place the following in the documentation:
WARNING: The code which Automake generates is only robust if you globally turn
on flags errexit, nounset and pipefail.
And/or at least print something like this at runtime:
WARNING: The current shell does not have error-detection features, so this
makefile is not robust in the face of errors. After each error, you should
restart the build from scratch in order to guarantee a reliable build outcome.
The trouble is, both alternatives would mean changing Automake: For (1) it
means generating really robust code without those flags (which I think it is
not the case now, is it?), and for (2) it means generating code which does not
break with those global flags set (which is not certain now).
In any case, Automake should allow the user to globally set errexit, etc. for
his own, manually-written recipes. Otherwise, it is a pain for the user who
wants to write robust code.
If not, the Automake documentation should at least refrain of giving examples of brittle
recipe code, and instead encourage setting errexit etc. in each and every user recipe.
Here is an example from "14.3 The dist Hook":
rm -rf `find $(distdir)/doc -type d -name RCS`
What if 'find' fails with a non-zero exit code? Maybe my container does not
have 'find' installed, and then this recipe will silently not do its job
correctly.
There is much valid criticism of the Autotools, but in my view, this tolerance of brittle
code is the worst of all. Or have I perhaps missed some honest "CAVEATS"
section where this lack of robustness is explained? I understand that open-source
projects often lack the necessary resources to improve the software or fix its issues,
but documenting such known problems in the readme should be doable.
does Automake already generate standard recipes in one single,
possible very long, shell line?
Yes it does (split with "; \" across many physical file lines); in many
cases that's necessary because the standard recipes need to use shell
variables.
Well, in this case, turning on .ONESHELL globally shouldn't be a problem as far
as Automake is concerned, should it?
The "only" things left to do would then be: 1) verify that claim, 2) maybe add
some test cases for it, and 3) mention in the documentation that .ONESHELL does not break
Automake-generated makefiles.
Or at the very least add "Ensure .ONESHELL does not break Automake-generated makefiles"
to the "future goals" list, even if it never gets implemented. That would at least stop
the searching and questioning.
Regards,
rdiez