mirror of
https://github.com/pyenv/pyenv.git
synced 2026-10-02 23:41:06 +09:00
pyenv-exec: add the --environment option for programs that embed libpython without a path (#3537)
--------- Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com> Co-authored-by: native-api <vano@mail.mipt.ru>
This commit is contained in:
parent
6ff25c51d3
commit
f8b1d7ae09
15
COMMANDS.md
15
COMMANDS.md
@ -315,7 +315,7 @@ Lists all Python versions with the given command installed.
|
||||
|
||||
## `pyenv exec`
|
||||
|
||||
Usage: pyenv exec <command> [arg1 arg2...]
|
||||
Usage: pyenv exec [-N|--environment] <command> [arg1 arg2...]
|
||||
|
||||
Runs an executable by first preparing PATH so that the selected Python
|
||||
version's `bin` directory is at the front.
|
||||
@ -326,7 +326,18 @@ For example, if the currently selected Python version is 3.9.7:
|
||||
|
||||
is equivalent to:
|
||||
|
||||
PATH="$PYENV_ROOT/versions/3.9.7/bin:$PATH" pip install -r requirements.txt
|
||||
PYENV_VERSION="3.9.7" PATH="$PYENV_ROOT/versions/3.9.7/bin:$PATH" pip install -r requirements.txt
|
||||
|
||||
The `--environment` option sets `PYTHONHOME` and `LD_LIBRARY_PATH` (`DYLD_LIBRARY_PATH` in macOS) in the program's environment.
|
||||
This is needed to run programs that embed Python by loading `libpython` without specifying rpath or an explicit path.
|
||||
This breaks linking for programs that expect to link to a different `libpython` with the same name as one
|
||||
in selected Python -- thus it's not done by default.
|
||||
|
||||
In macOS, System Integrity Protection (SIP) removes `DYLD_LIBRARY_PATH` from a process' environment
|
||||
upon `exec` (not `fork`) if the executable being run is protected. The protection covers preinstalled system software
|
||||
(including preinstalled shells) and does not cover user-installed apps and 3rd-party software. See
|
||||
[About System Integrity Protection on your Mac - Apple Support](https://support.apple.com/en-us/102149)
|
||||
for details.
|
||||
|
||||
## `pyenv root`
|
||||
|
||||
|
||||
@ -2,7 +2,17 @@
|
||||
#
|
||||
# Summary: Run an executable with the selected Python version
|
||||
#
|
||||
# Usage: pyenv exec <command> [arg1 arg2...]
|
||||
# Usage: pyenv exec [-N|--environment] <command> [arg1 arg2...]
|
||||
#
|
||||
# -N/--environment Set PYTHONHOME and LD_LIBRARY_PATH (DYLD_LIBRARY_PATH in macOS)
|
||||
# envvars for the running command.
|
||||
# This allows to run programs that embed Python without using rpath or
|
||||
# exact library path to libpython.
|
||||
# WARNING: For the running command and its child processes, this will
|
||||
# break linkage for programs that expect to be linked to a different
|
||||
# libpython instance with the same name!
|
||||
# WARNING: In macOS, DYLD_LIBRARY_PATH will be unset by the system for
|
||||
# processes covered by System Integrity Protection.
|
||||
#
|
||||
# Runs an executable by first preparing PATH so that the selected Python
|
||||
# version's `bin' directory is at the front.
|
||||
@ -18,9 +28,16 @@ set -e
|
||||
|
||||
# Provide pyenv completions
|
||||
if [ "$1" = "--complete" ]; then
|
||||
echo --environment
|
||||
exec pyenv-shims --short
|
||||
fi
|
||||
|
||||
unset MODIFY_ENV
|
||||
if [ "$1" = "-N" ] || [ "$1" = "--environment" ]; then
|
||||
MODIFY_ENV=true
|
||||
shift
|
||||
fi
|
||||
|
||||
PYENV_VERSION="$(pyenv-version-name -f)"
|
||||
PYENV_COMMAND="$1"
|
||||
|
||||
@ -54,4 +71,27 @@ if [ "${PYENV_BIN_PATH#${PYENV_ROOT}}" != "${PYENV_BIN_PATH}" ]; then
|
||||
# Only add to $PATH for non-system version.
|
||||
export PATH="${PYENV_BIN_PATH}:${PATH}"
|
||||
fi
|
||||
if [ -n "$MODIFY_ENV" ]; then
|
||||
|
||||
# Check if multiple Python versions are selected
|
||||
VERSIONS=$(pyenv-prefix)
|
||||
if [[ "$VERSIONS" == *:* ]]; then
|
||||
VERSION="${VERSIONS%%:*}"
|
||||
echo "pyenv: Warning: multiple Python versions are selected." \
|
||||
"Setting environment variables for the first one, (${VERSION#$PYENV_ROOT})" >&2
|
||||
else
|
||||
VERSION="$VERSIONS"
|
||||
fi
|
||||
|
||||
# Assign the correct version of PYTHONHOME
|
||||
export PYTHONHOME="$VERSION"
|
||||
case "$(uname -s)" in
|
||||
Darwin)
|
||||
export DYLD_LIBRARY_PATH="${PYTHONHOME}/lib${DYLD_LIBRARY_PATH:+:${DYLD_LIBRARY_PATH}}"
|
||||
;;
|
||||
*)
|
||||
export LD_LIBRARY_PATH="${PYTHONHOME}/lib${LD_LIBRARY_PATH:+:${LD_LIBRARY_PATH}}"
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
exec "$PYENV_COMMAND_PATH" "$@"
|
||||
|
||||
@ -34,6 +34,7 @@ EOF
|
||||
assert_success
|
||||
assert_output <<OUT
|
||||
--help
|
||||
--environment
|
||||
fab
|
||||
python
|
||||
OUT
|
||||
@ -139,3 +140,53 @@ $envvarname=/unusual/shim/location:/another/shim/location
|
||||
_PYENV_SHIM_PATH=
|
||||
!
|
||||
}
|
||||
|
||||
@test "--environment sets envvars in Linux" {
|
||||
export PYENV_VERSION="test"
|
||||
create_alt_executable print_env <<!
|
||||
#!$BASH
|
||||
echo PYTHONHOME="\$PYTHONHOME"
|
||||
echo LD_LIBRARY_PATH="\$LD_LIBRARY_PATH"
|
||||
!
|
||||
create_path_executable uname "echo Linux"
|
||||
|
||||
LD_LIBRARY_PATH= run pyenv-exec -N print_env
|
||||
assert_output_glob <<!
|
||||
PYTHONHOME=*/test
|
||||
LD_LIBRARY_PATH=*/test/lib
|
||||
!
|
||||
|
||||
LD_LIBRARY_PATH=/foo/bar run pyenv-exec -N print_env
|
||||
assert_output_glob <<!
|
||||
PYTHONHOME=*/test
|
||||
LD_LIBRARY_PATH=*/test/lib:/foo/bar
|
||||
!
|
||||
}
|
||||
|
||||
@test "--environment sets envvars in macOS" {
|
||||
if [[ $(uname -s) == "Darwin" && $BASH == "/bin/bash" \
|
||||
&& $(LC_ALL=C csrutil status) == *"enabled." ]]; then
|
||||
skip "macOS with Bash covered by SIP"
|
||||
fi
|
||||
|
||||
export PYENV_VERSION="test"
|
||||
create_alt_executable print_env <<!
|
||||
#!$BASH
|
||||
echo PYTHONHOME="\$PYTHONHOME"
|
||||
echo DYLD_LIBRARY_PATH="\$DYLD_LIBRARY_PATH"
|
||||
!
|
||||
create_path_executable uname "echo Darwin"
|
||||
|
||||
DYLD_LIBRARY_PATH= run pyenv-exec -N print_env
|
||||
assert_output_glob <<!
|
||||
PYTHONHOME=*/test
|
||||
DYLD_LIBRARY_PATH=*/test/lib
|
||||
!
|
||||
|
||||
|
||||
DYLD_LIBRARY_PATH=/foo/bar run pyenv-exec -N print_env
|
||||
assert_output_glob <<!
|
||||
PYTHONHOME=*/test
|
||||
DYLD_LIBRARY_PATH=*/test/lib:/foo/bar
|
||||
!
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user