diff --git a/tools/python/pywrapper_template.txt b/tools/python/pywrapper_template.txt index f4dbd02618c975..d38720ddfb4e82 100644 --- a/tools/python/pywrapper_template.txt +++ b/tools/python/pywrapper_template.txt @@ -15,18 +15,30 @@ die() { exit 1 } -# Make sure PATH is exported. If we're called with PATH unset, as happens when -# we're invoked as a tool during the build, the shell will initialize its own -# PATH but not necessarily export it. This would break our call to `which`. See -# https://github.com/bazelbuild/continuous-integration/issues/578 for more -# information. -export PATH +# We use `which` to locate the Python interpreter command on PATH. `command -v` +# is another option, but it doesn't check whether the file it finds has the +# executable bit. +# +# A tricky situation happens when this wrapper is invoked as part of running a +# tool, e.g. passing a py_binary target to `ctx.actions.run()`. Bazel will unset +# the PATH variable. Then the shell will see there's no PATH and initialize its +# own, sometimes without exporting it. This causes `which` to fail and this +# script to think there's no Python interpreter installed. To avoid this we +# explicitly pass PATH to each `which` invocation. We can't just export PATH +# because that would modify the environment seen by the final user Python +# program. +# +# See also: +# +# https://github.com/bazelbuild/continuous-integration/issues/578 +# https://github.com/bazelbuild/bazel/issues/8414 +# https://github.com/bazelbuild/bazel/issues/8415 # Try the "python%VERSION%" command name first, then fall back on "python". -PYTHON_BIN=`which python%VERSION% || echo ""` +PYTHON_BIN=`PATH="$PATH" which python%VERSION% || echo ""` USED_FALLBACK=0 if [ -z "${PYTHON_BIN:-}" ]; then - PYTHON_BIN=`which python || echo ""` + PYTHON_BIN=`PATH="$PATH" which python || echo ""` USED_FALLBACK=1 fi if [ -z "${PYTHON_BIN:-}" ]; then