55if [[ -n " ${RULES_PYTHON_BOOTSTRAP_VERBOSE:- } " ]]; then
66 set -x
77fi
8- set -x
8+ # # set -x
99
1010# runfiles-relative path
1111STAGE2_BOOTSTRAP=" %stage2_bootstrap%"
1212
1313# runfiles-relative path to python interpreter to use.
14- # This is the `bin/python3` file in the binary's venv.
14+ # This is the `bin/python3` path in the binary's venv.
1515PYTHON_BINARY=' %python_binary%'
1616# The path that PYTHON_BINARY should symlink to.
1717# runfiles-relative path, absolute path, or single word.
@@ -147,6 +147,7 @@ if [[ "$IS_ZIPFILE" == "1" ]]; then
147147 mkdir -p " $( dirname $python_exe ) "
148148 ln -s " $symlink_to " " $python_exe "
149149elif [[ " $RECREATE_VENV_AT_RUNTIME " == " 1" ]]; then
150+ runfiles_venv=" $RUNFILES_DIR /$( dirname $( dirname $PYTHON_BINARY ) ) "
150151
151152 if [[ -n " $RULES_PYTHON_EXTRACT_ROOT " ]]; then
152153 use_exec=1
@@ -164,64 +165,71 @@ elif [[ "$RECREATE_VENV_AT_RUNTIME" == "1" ]]; then
164165 fi
165166 fi
166167
167- if [[ " $PYTHON_BINARY_ACTUAL " == /* ]]; then
168- # An absolute path, i.e. platform runtime, e.g. /usr/bin/python3
169- symlink_to=$PYTHON_BINARY_ACTUAL
170- elif [[ " $PYTHON_BINARY_ACTUAL " == * /* ]]; then
171- # A runfiles-relative path
172- symlink_to=" $RUNFILES_DIR /$PYTHON_BINARY_ACTUAL "
173- else
174- # A plain word, e.g. "python3". Symlink to where PATH leads
175- symlink_to=$( which $PYTHON_BINARY_ACTUAL )
176- # Guard against trying to symlink to an empty value
177- if [[ $? -ne 0 ]]; then
178- echo >&2 " ERROR: Python to use not found on PATH: $PYTHON_BINARY_ACTUAL "
179- exit 1
180- fi
181- fi
168+ # Match the basename; some tools, e.g. pyvenv key off the executable name
169+ venv_py_exe=" $venv /bin/$( basename $PYTHON_BINARY_ACTUAL ) "
182170
183- runfiles_venv=" $RUNFILES_DIR /$( dirname $( dirname $PYTHON_BINARY ) ) "
171+ if [[ ! -e " $venv_py_exe " ]]; then
172+ if [[ " $PYTHON_BINARY_ACTUAL " == /* ]]; then
173+ # An absolute path, i.e. platform runtime, e.g. /usr/bin/python3
174+ symlink_to=$PYTHON_BINARY_ACTUAL
175+ elif [[ " $PYTHON_BINARY_ACTUAL " == * /* ]]; then
176+ # A runfiles-relative path
177+ symlink_to=" $RUNFILES_DIR /$PYTHON_BINARY_ACTUAL "
178+ else
179+ # A plain word, e.g. "python3". Symlink to where PATH leads
180+ symlink_to=$( which $PYTHON_BINARY_ACTUAL )
181+ # Guard against trying to symlink to an empty value
182+ if [[ $? -ne 0 ]]; then
183+ echo >&2 " ERROR: Python to use not found on PATH: $PYTHON_BINARY_ACTUAL "
184+ exit 1
185+ fi
186+ fi
184187
185- # If the interpreter is a wrapper script that invokes Python, and
186- # is prior to Python 3.11 (PYTHONEXECUTABLE environment variable), then
187- # we can only trigger venv behavior by symlinking to the actual underlying
188- # interpreter.
189- # Additionally, if the build-time lib/pythonX.Y/site-packages path doesn't
190- # match what the runtime interpreter is looking for (i.e. version mismatch
191- # between build vs runtime), then pretend the version mismatch is OK :D,
192- # and create the desired path in the temporary venv.
193- if [[ " $RESOLVE_PYTHON_BINARY_AT_RUNTIME " == " 1" ]]; then
194- {
195- read -r resolved_py_exe
196- read -r resolved_site_packages
197- } < <( " $symlink_to " -I << EOF
188+ # When RESOLVE_PYTHON_BINARY_AT_RUNTIME is true, it means the toolchain
189+ # has thrown two complications at us:
190+ # 1. The build-time assumption of the Python version may not match the
191+ # runtime Python version. The site-packages directory path includes the
192+ # Python version, so when the versions don't match, the runtime won't
193+ # find it.
194+ # 2. The interpreter might be a wrapper script, which interferes with Python's
195+ # ability to detect when it's within a venv. Starting in Python 3.11,
196+ # the PYTHONEXECUTABLE environment variable can fix this, but due to (1),
197+ # we don't know if that is supported without running Python.
198+ # To fix (1), we symlink the desired site-packages path to the build-time
199+ # directory. Hopefully the version mismatch is OK :D.
200+ # To fix (2), we determine the actual underlying interpreter and symlink
201+ # to that.
202+ if [[ " $RESOLVE_PYTHON_BINARY_AT_RUNTIME " == " 1" ]]; then
203+ {
204+ read -r resolved_py_exe
205+ read -r resolved_site_packages
206+ } < <( " $symlink_to " -I << EOF
198207import sys, site, os
199208print(sys.executable)
200209print(site.getsitepackages(["$venv "])[-1])
201210EOF
202211)
203- symlink_to=" $resolved_py_exe "
204- runfiles_venv_site_packages=$runfiles_venv /$VENV_REL_SITE_PACKAGES
205- venv_site_packages=" $resolved_site_packages "
206- else
207- # For simplicity, just symlink to the whole lib directory.
208- runfiles_venv_site_packages=$runfiles_venv /lib
209- venv_site_packages=$venv /lib
210- fi
212+ symlink_to=" $resolved_py_exe "
213+ runfiles_venv_site_packages=$runfiles_venv /$VENV_REL_SITE_PACKAGES
214+ venv_site_packages=" $resolved_site_packages "
215+ else
216+ # For simplicity, just symlink to the whole lib directory.
217+ runfiles_venv_site_packages=$runfiles_venv /lib
218+ venv_site_packages=$venv /lib
219+ fi
211220
212- # Match the basename; some tools, e.g. pyvenv key off the executable name
213- python_exe=" $venv /bin/$( basename $PYTHON_BINARY_ACTUAL ) "
214- if [[ ! -e " $python_exe " ]]; then
215221 mkdir -p " $venv /bin"
216222 ln -s " $symlink_to " " $python_exe "
223+
224+ if [[ ! -e " $venv_site_packages " ]]; then
225+ mkdir -p $( dirname $venv_site_packages )
226+ ln -s " $runfiles_venv_site_packages " " $venv_site_packages "
227+ fi
217228 fi
229+
218230 if [[ ! -e " $venv /pyvenv.cfg" ]]; then
219231 ln -s " $runfiles_venv /pyvenv.cfg" " $venv /pyvenv.cfg"
220232 fi
221- if [[ ! -e " $venv_site_packages " ]]; then
222- mkdir -p $( dirname $venv_site_packages )
223- ln -s " $runfiles_venv_site_packages " " $venv_site_packages "
224- fi
225233
226234else
227235 use_exec=1
0 commit comments