Subject: bug#25258: Bashisms in make rules

From: [email-masked]
Date: Sat, 16 May 2020 15:33:09 +0900

Resurrecting this, since it cause me significant grief, and is a simple
workaround which I believe is worth putting in the documentation. First, here
is a short summary of the problem:

Currently, some of our make rules contain bashisms. As of commit 408ae72c, this
ends up generating broken texinfo translations under doc/*.texi, eventually
failing with "@ref reference to nonexistent node..." errors.

From a pristine repository (e.g. after running `git clean -xfd'), running make
shows a bunch of errors from the broken rules, but since they happen to be
multi-line scripts, the errors fail to propogate up to make. Thus make leaves
around the broken texinfo files. The real kicker is that subsequent runs pick
up the broken files and make fails just as above, but without encountering or
showing the errors from the broken rules. This makes tracking down the error
significantly more painful and non-obvious.

Anyway, the source of the problem is a combination of our use of bashisms and
autoconf trying really hard to use the least-common-denominator shell.
Autoconf's configure script sets make's SHELL by first looking for /bin/sh and
only finding sh on PATH as a last resort. Thus, even when running under `guix
environment --pure guix' make will run with /bin/sh instead of
$GUIX_ENVIRONMENT/bin/sh.

On a Guix System this ends up running make with the sh of the system profile
which, at the moment, resolves to bash. However, on a foreign distribution,
/bin/sh often resolves to a non-bash shell; in particular, it is common these
days for it to be a symlink to dash. Hence, lots of pain.

Once we know the source of the error, the fix is simple. We can explicitly tell
make to run it's rules with bash:

    $ make SHELL=$(command -v bash)

In a guix environment, this should pick up the bash in $GUIX_ENVIRONMENT.
Better yet, we can do this once, by telling *configure* what shell to use:

    $ CONFIG_SHELL=$(command -v bash) ./configure

and all subsequent runs of make will Just Work from within the environment.

Does this make sense? Am I missing something obvious? If not, would it make
sense to include the above ./configure invocation in our documentation?

Ideally, we could modify Makefile.am or configure.ac in some way to
automatically fix the problem; however, if we want to support build exterior to
a guix build environment, I suspect the "most correct" course of action is to
simply remove our bashisms.

That said, we could tell automake to *not* explicity set make's SHELL by a
simple one-liner in `configure.ac':

    AM_SUBST_NOTMAKE([SHELL])

This will cause make to use it's baked-in default instead of the one autoconf
detects. Luckily, for guix builds make correctly references the profile's sh:

    $ strings $GUIX_ENVIRONMENT/bin/make | grep bin/sh
    /gnu/store/<hash>-bash-<version>/bin/sh

and non-guix make is likely to point to something relevant for that
distribution anyway. That said, I am sure automake and autoconf set make's
SHELL for a reason, so perhaps this solution is too heavy of a hammer.
Thoughts?

Anyway, this turned into a lot longer of an email than I anticipated. Thanks
for taking the time to read through it.