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`
|
## `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
|
Runs an executable by first preparing PATH so that the selected Python
|
||||||
version's `bin` directory is at the front.
|
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:
|
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`
|
## `pyenv root`
|
||||||
|
|
||||||
|
|||||||
@ -2,7 +2,17 @@
|
|||||||
#
|
#
|
||||||
# Summary: Run an executable with the selected Python version
|
# 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
|
# Runs an executable by first preparing PATH so that the selected Python
|
||||||
# version's `bin' directory is at the front.
|
# version's `bin' directory is at the front.
|
||||||
@ -18,9 +28,16 @@ set -e
|
|||||||
|
|
||||||
# Provide pyenv completions
|
# Provide pyenv completions
|
||||||
if [ "$1" = "--complete" ]; then
|
if [ "$1" = "--complete" ]; then
|
||||||
|
echo --environment
|
||||||
exec pyenv-shims --short
|
exec pyenv-shims --short
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
unset MODIFY_ENV
|
||||||
|
if [ "$1" = "-N" ] || [ "$1" = "--environment" ]; then
|
||||||
|
MODIFY_ENV=true
|
||||||
|
shift
|
||||||
|
fi
|
||||||
|
|
||||||
PYENV_VERSION="$(pyenv-version-name -f)"
|
PYENV_VERSION="$(pyenv-version-name -f)"
|
||||||
PYENV_COMMAND="$1"
|
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.
|
# Only add to $PATH for non-system version.
|
||||||
export PATH="${PYENV_BIN_PATH}:${PATH}"
|
export PATH="${PYENV_BIN_PATH}:${PATH}"
|
||||||
fi
|
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" "$@"
|
exec "$PYENV_COMMAND_PATH" "$@"
|
||||||
|
|||||||
@ -34,6 +34,7 @@ EOF
|
|||||||
assert_success
|
assert_success
|
||||||
assert_output <<OUT
|
assert_output <<OUT
|
||||||
--help
|
--help
|
||||||
|
--environment
|
||||||
fab
|
fab
|
||||||
python
|
python
|
||||||
OUT
|
OUT
|
||||||
@ -139,3 +140,53 @@ $envvarname=/unusual/shim/location:/another/shim/location
|
|||||||
_PYENV_SHIM_PATH=
|
_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