Thanks to visit codestin.com
Credit goes to github.com

Skip to content

fix(toolchains): use posix-compatible exec -a alternative #3010

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jun 20, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 7 additions & 6 deletions python/private/runtime_env_toolchain_interpreter.sh
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,15 @@ if [ -e "$self_dir/pyvenv.cfg" ] || [ -e "$self_dir/../pyvenv.cfg" ]; then
if [ ! -e "$PYTHON_BIN" ]; then
die "ERROR: Python interpreter does not exist: $PYTHON_BIN"
fi
# PYTHONEXECUTABLE is also used because `exec -a` doesn't fully trick the
# pyenv wrappers.
# PYTHONEXECUTABLE is also used because switching argv0 doesn't fully trick
# the pyenv wrappers.
# NOTE: The PYTHONEXECUTABLE envvar only works for non-Mac starting in Python 3.11
export PYTHONEXECUTABLE="$venv_bin"
# Python looks at argv[0] to determine sys.executable, so use exec -a
# to make it think it's the venv's binary, not the actual one invoked.
# NOTE: exec -a isn't strictly posix-compatible, but very widespread
exec -a "$venv_bin" "$PYTHON_BIN" "$@"
# Python looks at argv[0] to determine sys.executable, so set that to the venv
# binary, not the actual one invoked.
# NOTE: exec -a would be simpler, but isn't posix-compatible, and dash shell
# (Ubuntu/debian default) doesn't support it; see #3009.
exec sh -c "$PYTHON_BIN \$@" "$venv_bin" "$@"
else
exec "$PYTHON_BIN" "$@"
fi
23 changes: 23 additions & 0 deletions tests/runtime_env_toolchain/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,26 @@ py_reconfig_test(
tags = ["no-remote-exec"],
deps = ["//python/runfiles"],
)

py_reconfig_test(
name = "bootstrap_script_test",
srcs = ["toolchain_runs_test.py"],
bootstrap_impl = "script",
data = [
"//tests/support:current_build_settings",
],
extra_toolchains = [
"//python/runtime_env_toolchains:all",
# Necessary for RBE CI
CC_TOOLCHAIN,
],
main = "toolchain_runs_test.py",
# With bootstrap=script, the build version must match the runtime version
# because the venv has the version in the lib/site-packages dir name.
python_version = PYTHON_VERSION,
# Our RBE has Python 3.6, which is too old for the language features
# we use now. Using the runtime-env toolchain on RBE is pretty
# questionable anyways.
tags = ["no-remote-exec"],
deps = ["//python/runfiles"],
)
9 changes: 9 additions & 0 deletions tests/runtime_env_toolchain/toolchain_runs_test.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import json
import pathlib
import platform
import sys
import unittest

from python.runfiles import runfiles
Expand All @@ -23,6 +24,14 @@ def test_ran(self):
settings["interpreter"]["short_path"],
)

if settings["bootstrap_impl"] == "script":
# Verify we're running in a venv
self.assertNotEqual(sys.prefix, sys.base_prefix)
# .venv/ occurs for a build-time venv.
# For a runtime created venv, it goes into a temp dir, so
# look for the /bin/ dir as an indicator.
self.assertRegex(sys.executable, r"[.]venv/|/bin/")


if __name__ == "__main__":
unittest.main()
6 changes: 6 additions & 0 deletions tests/support/sh_py_run_test.bzl
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ def _current_build_settings_impl(ctx):
ctx.actions.write(
output = info,
content = json.encode({
"bootstrap_impl": ctx.attr._bootstrap_impl_flag[config_common.FeatureFlagInfo].value,
"interpreter": {
"short_path": runtime.interpreter.short_path if runtime.interpreter else None,
},
Expand All @@ -153,6 +154,11 @@ Writes information about the current build config to JSON for testing.
This is so tests can verify information about the build config used for them.
""",
implementation = _current_build_settings_impl,
attrs = {
"_bootstrap_impl_flag": attr.label(
default = "//python/config_settings:bootstrap_impl",
),
},
toolchains = [
TARGET_TOOLCHAIN_TYPE,
],
Expand Down