mirror of
https://github.com/Kitware/CMake.git
synced 2025-12-30 18:29:37 -06:00
FindPython*: Add capability to control virtual env handling.
Fixes: #19097
This commit is contained in:
5
Help/release/dev/FindPython-virtual-env.rst
Normal file
5
Help/release/dev/FindPython-virtual-env.rst
Normal file
@@ -0,0 +1,5 @@
|
||||
FindPython-virtual-env
|
||||
----------------------
|
||||
|
||||
* Modules :module:`FindPython3`, :module:`FindPython2` and :module:`FindPython`
|
||||
gain capability to control how virtual environments are handled.
|
||||
@@ -145,18 +145,30 @@ Hints
|
||||
* ``NEVER``: Never try to use registry.
|
||||
|
||||
``CMAKE_FIND_FRAMEWORK``
|
||||
On OS X the :variable:`CMAKE_FIND_FRAMEWORK` variable determine the order of
|
||||
On macOS the :variable:`CMAKE_FIND_FRAMEWORK` variable determine the order of
|
||||
preference between Apple-style and unix-style package components.
|
||||
|
||||
.. note::
|
||||
|
||||
Value ``ONLY`` is not supported so ``FIRST`` will be used instead.
|
||||
|
||||
.. note::
|
||||
``Python_FIND_VIRTUALENV``
|
||||
This variable defines the handling of virtual environments. It is meaningfull
|
||||
only when a virtual environment is active (i.e. the ``activate`` script has
|
||||
been evaluated). In this case, it takes precedence over
|
||||
``Python_FIND_REGISTRY`` and ``CMAKE_FIND_FRAMEWORK`` variables.
|
||||
The ``Python_FIND_VIRTUALENV`` variable can be set to empty or one of the
|
||||
following:
|
||||
|
||||
If a Python virtual environment is configured, set variable
|
||||
``Python_FIND_REGISTRY`` (Windows) or ``CMAKE_FIND_FRAMEWORK`` (macOS) with
|
||||
value ``LAST`` or ``NEVER`` to select it preferably.
|
||||
* ``FIRST``: The virtual environment is used before any other standard
|
||||
paths to look-up for the interpreter. This is the default.
|
||||
* ``ONLY``: Only the virtual environment is used to look-up for the
|
||||
interpreter.
|
||||
* ``STANDARD``: The virtual environment is not used to look-up for the
|
||||
interpreter. In this case, variable ``Python_FIND_REGISTRY`` (Windows)
|
||||
or ``CMAKE_FIND_FRAMEWORK`` (macOS) can be set with value ``LAST`` or
|
||||
``NEVER`` to select preferably the interpreter from the virtual
|
||||
environment.
|
||||
|
||||
Commands
|
||||
^^^^^^^^
|
||||
|
||||
@@ -298,6 +298,22 @@ else()
|
||||
set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST")
|
||||
endif()
|
||||
|
||||
# virtual environments handling
|
||||
if (DEFINED ENV{VIRTUAL_ENV})
|
||||
if (DEFINED ${_PYTHON_PREFIX}_FIND_VIRTUALENV)
|
||||
if (NOT ${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY|STANDARD)$")
|
||||
message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_VIRTUALENV}: invalid value for '${_PYTHON_PREFIX}_FIND_VIRTUALENV'. 'FIRST', 'ONLY' or 'IGNORE' expected.")
|
||||
set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV "FIRST")
|
||||
else()
|
||||
set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV ${${_PYTHON_PREFIX}_FIND_VIRTUALENV})
|
||||
endif()
|
||||
else()
|
||||
set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV FIRST)
|
||||
endif()
|
||||
else()
|
||||
set (_${_PYTHON_PREFIX}_FIND_VIRTUALENV STANDARD)
|
||||
endif()
|
||||
|
||||
|
||||
unset (_${_PYTHON_PREFIX}_REQUIRED_VARS)
|
||||
unset (_${_PYTHON_PREFIX}_CACHED_VARS)
|
||||
@@ -318,6 +334,30 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
|
||||
|
||||
_python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
|
||||
|
||||
# Virtual environments handling
|
||||
if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
|
||||
find_program (${_PYTHON_PREFIX}_EXECUTABLE
|
||||
NAMES python${_${_PYTHON_PREFIX}_VERSION}
|
||||
python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}
|
||||
python
|
||||
NAMES_PER_DIR
|
||||
HINTS ${_${_PYTHON_PREFIX}_HINTS}
|
||||
PATHS ENV VIRTUAL_ENV
|
||||
PATH_SUFFIXES bin Scripts
|
||||
NO_CMAKE_PATH
|
||||
NO_CMAKE_ENVIRONMENT_PATH
|
||||
NO_SYSTEM_ENVIRONMENT_PATH
|
||||
NO_CMAKE_SYSTEM_PATH)
|
||||
|
||||
_python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION})
|
||||
if (${_PYTHON_PREFIX}_EXECUTABLE)
|
||||
break()
|
||||
endif()
|
||||
if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY")
|
||||
continue()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Apple frameworks handling
|
||||
if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST")
|
||||
find_program (${_PYTHON_PREFIX}_EXECUTABLE
|
||||
@@ -423,7 +463,8 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
|
||||
endif()
|
||||
endforeach()
|
||||
|
||||
if (NOT ${_PYTHON_PREFIX}_EXECUTABLE)
|
||||
if (NOT ${_PYTHON_PREFIX}_EXECUTABLE AND
|
||||
NOT _${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY")
|
||||
# No specific version found. Retry with generic names
|
||||
# try using HINTS
|
||||
find_program (${_PYTHON_PREFIX}_EXECUTABLE
|
||||
@@ -685,18 +726,32 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
|
||||
# if python interpreter is found, use its location and version to ensure consistency
|
||||
# between interpreter and development environment
|
||||
unset (_${_PYTHON_PREFIX}_PREFIX)
|
||||
unset (_${_PYTHON_PREFIX}_EXEC_PREFIX)
|
||||
unset (_${_PYTHON_PREFIX}_BASE_EXEC_PREFIX)
|
||||
if (${_PYTHON_PREFIX}_Interpreter_FOUND)
|
||||
execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
|
||||
"import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.PREFIX)"
|
||||
"import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.EXEC_PREFIX)"
|
||||
RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
|
||||
OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PREFIX
|
||||
OUTPUT_VARIABLE _${_PYTHON_PREFIX}_EXEC_PREFIX
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if (_${_PYTHON_PREFIX}_RESULT)
|
||||
unset (_${_PYTHON_PREFIX}_PREFIX)
|
||||
unset (_${_PYTHON_PREFIX}_EXEC_PREFIX)
|
||||
endif()
|
||||
|
||||
if (NOT ${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "STANDARD")
|
||||
execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
|
||||
"import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.BASE_EXEC_PREFIX)"
|
||||
RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
|
||||
OUTPUT_VARIABLE _${_PYTHON_PREFIX}_BASE_EXEC_PREFIX
|
||||
ERROR_QUIET
|
||||
OUTPUT_STRIP_TRAILING_WHITESPACE)
|
||||
if (_${_PYTHON_PREFIX}_RESULT)
|
||||
unset (_${_PYTHON_PREFIX}_BASE_EXEC_PREFIX)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}" "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
|
||||
set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_EXEC_PREFIX}" "${_${_PYTHON_PREFIX}_BASE_EXEC_PREFIX}" "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
|
||||
|
||||
foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
|
||||
string (REPLACE "." "" _${_PYTHON_PREFIX}_VERSION_NO_DOTS ${_${_PYTHON_PREFIX}_VERSION})
|
||||
|
||||
@@ -153,11 +153,23 @@ Hints
|
||||
|
||||
Value ``ONLY`` is not supported so ``FIRST`` will be used instead.
|
||||
|
||||
.. note::
|
||||
``Python2_FIND_VIRTUALENV``
|
||||
This variable defines the handling of virtual environments. It is meaningfull
|
||||
only when a virtual environment is active (i.e. the ``activate`` script has
|
||||
been evaluated). In this case, it takes precedence over
|
||||
``Python2_FIND_REGISTRY`` and ``CMAKE_FIND_FRAMEWORK`` variables.
|
||||
The ``Python2_FIND_VIRTUALENV`` variable can be set to empty or one of the
|
||||
following:
|
||||
|
||||
If a Python virtual environment is configured, set variable
|
||||
``Python_FIND_REGISTRY`` (Windows) or ``CMAKE_FIND_FRAMEWORK`` (macOS) with
|
||||
value ``LAST`` or ``NEVER`` to select it preferably.
|
||||
* ``FIRST``: The virtual environment is used before any other standard
|
||||
paths to look-up for the interpreter. This is the default.
|
||||
* ``ONLY``: Only the virtual environment is used to look-up for the
|
||||
interpreter.
|
||||
* ``STANDARD``: The virtual environment is not used to look-up for the
|
||||
interpreter. In this case, variable ``Python2_FIND_REGISTRY`` (Windows)
|
||||
or ``CMAKE_FIND_FRAMEWORK`` (macOS) can be set with value ``LAST`` or
|
||||
``NEVER`` to select preferably the interpreter from the virtual
|
||||
environment.
|
||||
|
||||
Commands
|
||||
^^^^^^^^
|
||||
|
||||
@@ -137,7 +137,7 @@ Hints
|
||||
``Python3_FIND_REGISTRY``
|
||||
On Windows the ``Python3_FIND_REGISTRY`` variable determine the order
|
||||
of preference between registry and environment variables.
|
||||
the ``Python3_FIND_REGISTRY`` variable can be set to empty or one of the
|
||||
The ``Python3_FIND_REGISTRY`` variable can be set to empty or one of the
|
||||
following:
|
||||
|
||||
* ``FIRST``: Try to use registry before environment variables.
|
||||
@@ -146,18 +146,30 @@ Hints
|
||||
* ``NEVER``: Never try to use registry.
|
||||
|
||||
``CMAKE_FIND_FRAMEWORK``
|
||||
On OS X the :variable:`CMAKE_FIND_FRAMEWORK` variable determine the order of
|
||||
On macOS the :variable:`CMAKE_FIND_FRAMEWORK` variable determine the order of
|
||||
preference between Apple-style and unix-style package components.
|
||||
|
||||
.. note::
|
||||
|
||||
Value ``ONLY`` is not supported so ``FIRST`` will be used instead.
|
||||
|
||||
.. note::
|
||||
``Python3_FIND_VIRTUALENV``
|
||||
This variable defines the handling of virtual environments. It is meaningfull
|
||||
only when a virtual environment is active (i.e. the ``activate`` script has
|
||||
been evaluated). In this case, it takes precedence over
|
||||
``Python3_FIND_REGISTRY`` and ``CMAKE_FIND_FRAMEWORK`` variables.
|
||||
The ``Python3_FIND_VIRTUALENV`` variable can be set to empty or one of the
|
||||
following:
|
||||
|
||||
If a Python virtual environment is configured, set variable
|
||||
``Python_FIND_REGISTRY`` (Windows) or ``CMAKE_FIND_FRAMEWORK`` (macOS) with
|
||||
value ``LAST`` or ``NEVER`` to select it preferably.
|
||||
* ``FIRST``: The virtual environment is used before any other standard
|
||||
paths to look-up for the interpreter. This is the default.
|
||||
* ``ONLY``: Only the virtual environment is used to look-up for the
|
||||
interpreter.
|
||||
* ``STANDARD``: The virtual environment is not used to look-up for the
|
||||
interpreter. In this case, variable ``Python3_FIND_REGISTRY`` (Windows)
|
||||
or ``CMAKE_FIND_FRAMEWORK`` (macOS) can be set with value ``LAST`` or
|
||||
``NEVER`` to select preferably the interpreter from the virtual
|
||||
environment.
|
||||
|
||||
Commands
|
||||
^^^^^^^^
|
||||
|
||||
@@ -68,6 +68,17 @@ if(CMake_TEST_FindPython)
|
||||
--build-options ${build_options}
|
||||
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
|
||||
)
|
||||
|
||||
add_test(NAME FindPython.VirtualEnv COMMAND
|
||||
${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
|
||||
--build-and-test
|
||||
"${CMake_SOURCE_DIR}/Tests/FindPython/VirtualEnv"
|
||||
"${CMake_BINARY_DIR}/Tests/FindPython/VirtualEnv"
|
||||
${build_generator_args}
|
||||
--build-project TestVirtualEnv
|
||||
--build-options ${build_options}
|
||||
--test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
|
||||
)
|
||||
endif()
|
||||
|
||||
if(CMake_TEST_FindPython_NumPy)
|
||||
|
||||
42
Tests/FindPython/VirtualEnv/CMakeLists.txt
Normal file
42
Tests/FindPython/VirtualEnv/CMakeLists.txt
Normal file
@@ -0,0 +1,42 @@
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
project(TestVirtualEnv LANGUAGES NONE)
|
||||
|
||||
include(CTest)
|
||||
|
||||
find_package(Python3 REQUIRED COMPONENTS Interpreter)
|
||||
if (NOT Python3_FOUND)
|
||||
message (FATAL_ERROR "Fail to found Python 3")
|
||||
endif()
|
||||
|
||||
set (Python3_VIRTUAL_ENV "${CMAKE_CURRENT_BINARY_DIR}/py3venv")
|
||||
|
||||
execute_process (COMMAND "${Python3_EXECUTABLE}" -m venv "${Python3_VIRTUAL_ENV}"
|
||||
RESULT_VARIABLE result
|
||||
OUTPUT_VARIABLE outputs
|
||||
ERROR_VARIABLE outputs)
|
||||
if (result)
|
||||
message (FATAL_ERROR "Fail to create virtual environment: ${outputs}")
|
||||
endif()
|
||||
|
||||
add_test(NAME FindPython3.VirtualEnvDefault
|
||||
COMMAND "${CMAKE_COMMAND}" -E env --unset=PYTHONHOME
|
||||
"VIRTUAL_ENV=${Python3_VIRTUAL_ENV}"
|
||||
"${CMAKE_COMMAND}" "-DPYTHON3_VIRTUAL_ENV=${Python3_VIRTUAL_ENV}"
|
||||
-P "${CMAKE_CURRENT_LIST_DIR}/VirtualEnvDefault.cmake")
|
||||
|
||||
add_test(NAME FindPython3.VirtualEnvOnly
|
||||
COMMAND "${CMAKE_COMMAND}" -E env --unset=PYTHONHOME
|
||||
"VIRTUAL_ENV=${Python3_VIRTUAL_ENV}"
|
||||
"${CMAKE_COMMAND}" "-DPYTHON3_VIRTUAL_ENV=${Python3_VIRTUAL_ENV}"
|
||||
-P "${CMAKE_CURRENT_LIST_DIR}/VirtualEnvOnly.cmake")
|
||||
add_test(NAME FindPython3.UnsetVirtualEnvOnly
|
||||
COMMAND "${CMAKE_COMMAND}" -E env --unset=PYTHONHOME
|
||||
--unset=VIRTUAL_ENV
|
||||
"${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_LIST_DIR}/VirtualEnvOnly.cmake")
|
||||
|
||||
add_test(NAME FindPython3.VirtualEnvStandard
|
||||
COMMAND "${CMAKE_COMMAND}" -E env --unset=PYTHONHOME
|
||||
"VIRTUAL_ENV=${Python3_VIRTUAL_ENV}"
|
||||
"${CMAKE_COMMAND}" "-DPYTHON3_VIRTUAL_ENV=${Python3_VIRTUAL_ENV}"
|
||||
-P "${CMAKE_CURRENT_LIST_DIR}/VirtualEnvStandard.cmake")
|
||||
6
Tests/FindPython/VirtualEnv/VirtualEnvDefault.cmake
Normal file
6
Tests/FindPython/VirtualEnv/VirtualEnvDefault.cmake
Normal file
@@ -0,0 +1,6 @@
|
||||
|
||||
find_package (Python3 REQUIRED)
|
||||
|
||||
if (NOT Python3_EXECUTABLE MATCHES "^${PYTHON3_VIRTUAL_ENV}/.+")
|
||||
message (FATAL_ERROR "Fail to use virtual environment")
|
||||
endif()
|
||||
16
Tests/FindPython/VirtualEnv/VirtualEnvOnly.cmake
Normal file
16
Tests/FindPython/VirtualEnv/VirtualEnvOnly.cmake
Normal file
@@ -0,0 +1,16 @@
|
||||
|
||||
#
|
||||
# Virtual environment is defined for python3
|
||||
# Trying to find a python2 using only virtual environment
|
||||
# It is expecting to fail if a virtual environment is active and to success otherwise.
|
||||
#
|
||||
set (Python2_FIND_VIRTUALENV ONLY)
|
||||
find_package (Python2 QUIET)
|
||||
|
||||
if (PYTHON3_VIRTUAL_ENV AND Python2_FOUND)
|
||||
message (FATAL_ERROR "Python2 unexpectedly found.")
|
||||
endif()
|
||||
|
||||
if (NOT PYTHON3_VIRTUAL_ENV AND NOT Python2_FOUND)
|
||||
message (FATAL_ERROR "Fail to find Python2.")
|
||||
endif()
|
||||
7
Tests/FindPython/VirtualEnv/VirtualEnvStandard.cmake
Normal file
7
Tests/FindPython/VirtualEnv/VirtualEnvStandard.cmake
Normal file
@@ -0,0 +1,7 @@
|
||||
|
||||
set (Python3_FIND_VIRTUALENV STANDARD)
|
||||
find_package (Python3 REQUIRED)
|
||||
|
||||
if (Python3_EXECUTABLE MATCHES "^${PYTHON3_VIRTUAL_ENV}/.+")
|
||||
message (FATAL_ERROR "Python3 virtual env unexpectedly found.")
|
||||
endif()
|
||||
Reference in New Issue
Block a user