| #!/bin/sh | |
| # Don't set -e because we don't have robust trapping and printing of errors. | |
| set -u | |
| # We use /bin/sh rather than /bin/bash for portability. See discussion here: | |
| # https://groups.google.com/forum/?nomobile=true#!topic/bazel-dev/4Ql_7eDcLC0 | |
| # We do lose the ability to set -o pipefail. | |
| STRICT="%STRICT%" | |
| if [ "$STRICT" = "1" ]; then | |
| FAILURE_HEADER="\ | |
| Error occurred while attempting to use the default Python toolchain \ | |
| (@rules_python//python:autodetecting_toolchain)." | |
| else | |
| FAILURE_HEADER="\ | |
| Error occurred while attempting to use the non-strict autodetecting Python \ | |
| toolchain (@rules_python//python:autodetecting_toolchain_nonstrict)." | |
| fi | |
| die() { | |
| echo "$FAILURE_HEADER" 1>&2 | |
| echo "$1" 1>&2 | |
| exit 1 | |
| } | |
| # 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="$(PATH="$PATH" which python%VERSION% 2> /dev/null)" | |
| USED_FALLBACK="0" | |
| if [ -z "${PYTHON_BIN:-}" ]; then | |
| PYTHON_BIN="$(PATH="$PATH" which python 2>/dev/null)" | |
| USED_FALLBACK="1" | |
| fi | |
| if [ -z "${PYTHON_BIN:-}" ]; then | |
| die "Neither 'python%VERSION%' nor 'python' were found on the target \ | |
| platform's PATH, which is: | |
| $PATH | |
| Please ensure an interpreter is available on this platform (and marked \ | |
| executable), or else register an appropriate Python toolchain as per the \ | |
| documentation for py_runtime_pair \ | |
| (https://github.com/bazelbuild/rules_python/blob/master/docs/python.md#py_runtime_pair)." | |
| fi | |
| if [ "$STRICT" = "1" ]; then | |
| # Verify that we grabbed an interpreter with the right version. | |
| VERSION_STR="$("$PYTHON_BIN" -V 2>&1)" \ | |
| || die "Could not get interpreter version via '$PYTHON_BIN -V'" | |
| if ! echo "$VERSION_STR" | grep -q " %VERSION%\." ; then | |
| die "According to '$PYTHON_BIN -V', version is '$VERSION_STR', but we \ | |
| need version %VERSION%. PATH is: | |
| $PATH | |
| Please ensure an interpreter with version %VERSION% is available on this \ | |
| platform as 'python%VERSION%' or 'python', or else register an appropriate \ | |
| Python toolchain as per the documentation for py_runtime_pair \ | |
| (https://github.com/bazelbuild/rules_python/blob/master/docs/python.md#py_runtime_pair). | |
| Note that prior to Bazel 0.27, there was no check to ensure that the \ | |
| interpreter's version matched the version declared by the target (#4815). If \ | |
| your build worked prior to Bazel 0.27, and you're sure your targets do not \ | |
| require Python %VERSION%, you can opt out of this version check by using the \ | |
| non-strict autodetecting toolchain instead of the standard autodetecting \ | |
| toolchain. This can be done by passing the flag \ | |
| \`--extra_toolchains=@rules_python//python:autodetecting_toolchain_nonstrict\` \ | |
| on the command line or adding it to your bazelrc." | |
| fi | |
| fi | |
| exec "$PYTHON_BIN" "$@" |