I doubt that this is safe now, just because it's so easy for code that won't 
work with those flags turned on to get written by accident in the absence of 
these flags.

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?


So as far as Automake-generated rules are concerned, I'd expect "errexit" to be 
generally safe to enable.

That is a first step. I would also guess that enabling "pipefail" should be 
similarly unproblematic. The problems are probably nounset and .ONESHELL, right?

I think that .ONESHELL is global, isn't it? Otherwise, I would mark only my own 
recipes with .ONESHELL, and Automake-generated recipes wouldn't be impacted.


However, "make this safe and turn it on by default when the shell supports it" 
seems like a desirable goal, and one I'd support for both Automake and Autoconf.
[...]

I do not think that this goal is worth pursuing. Scripts which do not check for 
errors are defective in my opinion.

If I do not set those flags globally, I have to set them in every recipe, and 
that is only really practicable with .ONESHELL if the rules have several lines. 
At the moment, I write Makefile.am recipes like this:

$(FILENAME_WITH_SORTED_LIST):
  set -o errexit && set -o nounset && set -o pipefail && \
  echo "Generating the list of filenames passed to the linker..." && \
  printf '%s\n' $(OBJECTS_USED_FOR_LINKING) >"$(FILENAME_WITH_UNSORTED_LIST)" 
&& \
  ..

But that is a pain, as you can easily forget "&& \" at the end of a line. I was 
hoping to avoid that in the future.

If I do not set those flags globally, or in every recipe, then I have to 
manually check whether each pipe redirection has failed, and I cannot really 
check whether all used shell variables have been defined.

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

I would add an option to Automake to simply require those "modern" flags and 
generate the shell code accordingly. But that is a lot of work, I do not know anything 
about the Automake internals myself, and such an endeavour probably wouldn't have enough 
traction.

Incidentally, I would guess that supporting .ONESHELL would make the generated 
makefiles much faster. Or does Automake already generate standard recipes in 
one single, possible very long, shell line?


The biggest problem with these options is that they are portability nightmares: the 
behaviour of "set -e / set -o errexit" is quite inconsistent between different 
shells (not to mention full of surprising gotchas if shell functions are used),

What you say about errexit is true, but unfortunately, there is no other 
practicable way. Without errexit, you are bound to miss too many possible 
errors.

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.

I personally use (and require) pipefail etc., lint with ShellCheck, and 
recommend using Bash. That is the most you can achieve in practice. It is not 
completely water tight, but is actually rather close. And it is portable enough 
nowadays.

Please copy me on any answers, as I am not subscribed to this mailing list.

Regards,
  rdiez

Reply via email to