use portable "command -v" to detect installed programs, part 2

The "which" utility is not guaranteed to be installed either, and if it
is, its behavior is not portable either. This means that when various
programs are installed, the `which` check will report a fatal error
because the which tool did not exist and the shell returned a nonzero
status when attempting to fork+exec. If it did exist, it might not be an
implementation of `which` that returns nonzero when commands do not
exist.

The general scripting suggestion is to use the "command -v" shell
builtin; this is required to exist in all POSIX 2008 compliant shells,
and is thus guaranteed to work everywhere.

For some in-depth discussions on the topic, see:
- https://mywiki.wooledge.org/BashFAQ/081
- https://unix.stackexchange.com/questions/85249/why-not-use-which-what-to-use-then/85250#85250

Examples of open-source shells likely to be installed as /bin/sh on
Linux, which implement the 15-year-old standard: ash, bash, busybox,
dash, ksh, mksh and zsh.

This commit updates the build system to configure and build correctly on
systems without `which`.

Change-Id: I23dbde5c7f104dd610fd5f78c82bf9a7d0cc1930
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/160663
Tested-by: Jenkins
Tested-by: Ilmari Lauhakangas <ilmari.lauhakangas@libreoffice.org>
Reviewed-by: Ilmari Lauhakangas <ilmari.lauhakangas@libreoffice.org>
This commit is contained in:
Eli Schwartz 2023-12-13 00:01:39 -05:00 committed by Ilmari Lauhakangas
parent a1c854fffe
commit 71fed56e4a
5 changed files with 17 additions and 17 deletions

View file

@ -104,7 +104,7 @@ if [ ! -d "${INSTDIR}" -o ! -d "${WORKDIR}" ]; then
echo "INSTDIR or WORKDIR not present - script expects calling after full build"
exit 1
fi
which symstore.exe > /dev/null 2>&1 || {
command -v symstore.exe > /dev/null 2>&1 || {
echo "symstore.exe is expected in the PATH"
exit 1
}

View file

@ -225,7 +225,7 @@ add_warning()
if test "$have_WARNINGS" = "no"; then
echo "*************************************" > "$WARNINGS_FILE"
have_WARNINGS="yes"
if which tput >/dev/null && test "`tput colors 2>/dev/null || echo 0`" -ge 8; then
if command -v tput >/dev/null && test "`tput colors 2>/dev/null || echo 0`" -ge 8; then
dnl <esc> as actual byte (U+1b), [ escaped using quadrigraph @<:@
COLORWARN='*@<:@1;33;40m WARNING @<:@0m:'
else
@ -246,13 +246,13 @@ mac_sanitize_path()
mac_path="$LODE_HOME/opt/bin:/usr/bin:/bin:/usr/sbin:/sbin"
dnl a common but nevertheless necessary thing that may be in a fancy
dnl path location is git, so make sure we have it
mac_git_path=`which git 2>/dev/null`
mac_git_path=`command -v git`
if test -n "$mac_git_path" -a -x "$mac_git_path" -a "$mac_git_path" != "/usr/bin/git" ; then
mac_path="$mac_path:`dirname $mac_git_path`"
fi
dnl a not so common but nevertheless quite helpful thing that may be in a fancy
dnl path location is gpg, so make sure we find it
mac_gpg_path=`which gpg 2>/dev/null`
mac_gpg_path=`command -v gpg`
if test -n "$mac_gpg_path" -a -x "$mac_gpg_path" -a "$mac_gpg_path" != "/usr/bin/gpg" ; then
mac_path="$mac_path:`dirname $mac_gpg_path`"
fi
@ -567,13 +567,13 @@ for a in "$MAKE" "$GNUMAKE" make gmake gnumake; do
if test $? -eq 0; then
if test "$build_os" = "cygwin"; then
if test -n "$($a -v | grep 'Built for Windows')" ; then
GNUMAKE="$(cygpath -m "$(which "$(cygpath -u $a)")")"
GNUMAKE="$(cygpath -m "$(command -v "$(cygpath -u $a)")")"
GNUMAKE_WIN_NATIVE="TRUE"
else
GNUMAKE=`which $a`
GNUMAKE=`command -v $a`
fi
else
GNUMAKE=`which $a`
GNUMAKE=`command -v $a`
fi
break
fi
@ -1406,7 +1406,7 @@ if test "$_os" = "Emscripten"; then
fi
EMSCRIPTEN_ERROR=0
if ! which emconfigure >/dev/null 2>&1; then
if ! command -v emconfigure >/dev/null 2>&1; then
AC_MSG_WARN([emconfigure must be in your \$PATH])
EMSCRIPTEN_ERROR=1
fi
@ -3465,7 +3465,7 @@ if test "$_os" != "WINNT"; then
fi
else
GCC_HOME=`which gcc | $SED -e s,/bin/gcc,,`
GCC_HOME=`command -v gcc | $SED -e s,/bin/gcc,,`
GCC_HOME_SET="false"
fi
else
@ -9221,7 +9221,7 @@ if test "$enable_epm" = "yes"; then
if test -z "$RPM"; then
AC_MSG_ERROR([not found])
elif "$RPM" --help 2>&1 | $EGREP buildroot >/dev/null; then
RPM_PATH=`which $RPM`
RPM_PATH=`command -v $RPM`
AC_MSG_RESULT([$RPM_PATH])
SCPDEFS="$SCPDEFS -DWITH_RPM"
else
@ -9567,7 +9567,7 @@ or get and install one from https://www.nasm.us/
Then re-run autogen.sh
Note: autogen.sh will try to use /opt/lo/bin/nasm if the environment variable NASM is not already defined.
Alternatively, you can install the 'new' nasm where ever you want and make sure that \`which nasm\` finds it.
Alternatively, you can install the 'new' nasm where ever you want and make sure that \`command -v nasm\` finds it.
_EOS
else
@ -14214,7 +14214,7 @@ CURL=
if test "$enable_fetch_external" != "no"; then
CURL=`which curl 2>/dev/null`
CURL=`command -v curl`
for i in wget /usr/bin/wget /usr/local/bin/wget /usr/sfw/bin/wget /opt/sfw/bin/wget /opt/local/bin/wget; do
# wget new enough?
@ -14803,7 +14803,7 @@ dnl this avoids a dozen javac's ganging up on your laptop to kill it.
dnl ===================================================================
AC_MSG_CHECKING([whether to use icerun wrapper])
ICECREAM_RUN=
if test "$enable_icecream" = "yes" && which icerun >/dev/null 2>&1 ; then
if test "$enable_icecream" = "yes" && command -v icerun >/dev/null ; then
ICECREAM_RUN=icerun
AC_MSG_RESULT([yes])
else
@ -15274,7 +15274,7 @@ Copy it to the Cygwin /opt/lo/bin directory as make.exe
Then re-run autogen.sh
Note: autogen.sh will try to use /opt/lo/bin/make if the environment variable GNUMAKE is not already defined.
Alternatively, you can install the 'new' make where ever you want and make sure that `which make` finds it.
Alternatively, you can install the 'new' make where ever you want and make sure that `command -v make` finds it.
_EOS
fi

View file

@ -11,7 +11,7 @@ $(eval $(call gb_CustomTarget_CustomTarget,solenv/gbuildtesttools))
$(call gb_CustomTarget_get_target,solenv/gbuildtesttools) :
echo -n "{ \"MAKE\": \"$(if $(filter WNT,$(OS)),$(shell cygpath -u $(MAKE)),$(MAKE))\"" > $@
echo -n ", \"BASH\": \"$(if $(filter WNT,$(OS)),$(shell cygpath -m `which bash`),bash)\"" >> $@
echo -n ", \"BASH\": \"$(if $(filter WNT,$(OS)),$(shell cygpath -m `command -v bash`),bash)\"" >> $@
echo -n ", \"GBUILDTOJSON\": \"$(call gb_Executable_get_target,gbuildtojson)\" }" >> $@
# vim: set noet sw=4 ts=4:

View file

@ -13,7 +13,7 @@ EXECUTABLE=${1}
COREDIR=${2}
EXITCODE=${3}
if test -n "$(which gdb)"
if command -v gdb >/dev/null
then
found=
for COREFILE in "$COREDIR"/core*

View file

@ -94,7 +94,7 @@ function check_cmd {
found=0; cmd=
for cmd_needed in $cmds_needed; do
which $cmd_needed > /dev/null 2>&1 && { found=1; cmd=$cmd_needed; }
command -v $cmd_needed > /dev/null && { found=1; cmd=$cmd_needed; }
done
if [ $found = 0 ]; then
echo "$error_msg" >&2