Просмотр исходного кода

FindPython: Extend virtual environment handling by considering conda

- Add functionality to recognize and use CONDA_PREFIX environment variable
- Add tests for conda virtual environments
- Fixes: #20111
Sebastian Müller 6 лет назад
Родитель
Сommit
776d27d4a4

+ 5 - 0
Help/release/dev/FindPythonConda-module.rst

@@ -0,0 +1,5 @@
+FindPythonConda-module
+----------------------
+
+* The :module:`FindPython` module has learned to find Python components in active
+  virtual environments managed by ``conda``.

+ 6 - 6
Modules/FindPython.cmake

@@ -220,12 +220,12 @@ Hints
   variable will be used, if any.
 
 ``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:
+  This variable defines the handling of virtual environments managed by
+  ``virtualenv`` or ``conda``. It is meaningful 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:
 
   * ``FIRST``: The virtual environment is used before any other standard
     paths to look-up for the interpreter. This is the default.

+ 7 - 7
Modules/FindPython/Support.cmake

@@ -834,8 +834,8 @@ else()
   set (_${_PYTHON_PREFIX}_FIND_REGISTRY "FIRST")
 endif()
 
-# virtual environments handling
-if (DEFINED ENV{VIRTUAL_ENV})
+# virtual environments recognition
+if (DEFINED ENV{VIRTUAL_ENV} OR DEFINED ENV{CONDA_PREFIX})
   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 'STANDARD' expected. 'FIRST' will be used instead.")
@@ -930,7 +930,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
                         NAMES ${_${_PYTHON_PREFIX}_NAMES}
                         NAMES_PER_DIR
                         HINTS ${_${_PYTHON_PREFIX}_HINTS}
-                        PATHS ENV VIRTUAL_ENV
+                        PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX
                         PATH_SUFFIXES bin Scripts
                         NO_CMAKE_PATH
                         NO_CMAKE_ENVIRONMENT_PATH
@@ -1050,7 +1050,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
                         NAMES ${_${_PYTHON_PREFIX}_NAMES}
                         NAMES_PER_DIR
                         HINTS ${_${_PYTHON_PREFIX}_HINTS}
-                        PATHS ENV VIRTUAL_ENV
+                        PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX
                         PATH_SUFFIXES bin Scripts
                         NO_CMAKE_PATH
                         NO_CMAKE_ENVIRONMENT_PATH
@@ -1555,7 +1555,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
       set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
       unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS)
       if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
-        set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV)
+        set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX)
       endif()
       unset (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS)
 
@@ -1786,7 +1786,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
 
       unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS)
       if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
-        set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV)
+        set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX)
       endif()
 
       if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION")
@@ -2007,7 +2007,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
     if (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR)
       unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS)
       if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$")
-        set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV)
+        set (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS ENV VIRTUAL_ENV ENV CONDA_PREFIX)
       endif()
       unset (_${_PYTHON_PREFIX}_INCLUDE_HINTS)
 

+ 6 - 6
Modules/FindPython2.cmake

@@ -176,12 +176,12 @@ Hints
   variable will be used, if any.
 
 ``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:
+  This variable defines the handling of virtual environments managed by
+  ``virtualenv`` or ``conda``. It is meaningful 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:
 
   * ``FIRST``: The virtual environment is used before any other standard
     paths to look-up for the interpreter. This is the default.

+ 6 - 6
Modules/FindPython3.cmake

@@ -217,12 +217,12 @@ Hints
   variable will be used, if any.
 
 ``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:
+  This variable defines the handling of virtual environments managed by
+  ``virtualenv`` or ``conda``. It is meaningful 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:
 
   * ``FIRST``: The virtual environment is used before any other standard
     paths to look-up for the interpreter. This is the default.

+ 1 - 1
Tests/CMakeLists.txt

@@ -1449,7 +1449,7 @@ ${CMake_SOURCE_DIR}/Utilities/Release/push.bash --dir dev -- '${CMake_BUILD_NIGH
     add_subdirectory(GoogleTest)
   endif()
 
-  if(CMake_TEST_FindPython OR CMake_TEST_FindPython_NumPy)
+  if(CMake_TEST_FindPython OR CMake_TEST_FindPython_NumPy OR CMake_TEST_FindPython_Conda)
     add_subdirectory(FindPython)
   endif()
 

+ 13 - 0
Tests/FindPython/CMakeLists.txt

@@ -172,3 +172,16 @@ if(CMake_TEST_FindPython_NumPy)
     --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
   )
  endif()
+
+ if(CMake_TEST_FindPython_Conda)
+  add_test(NAME FindPython.VirtualEnvConda COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindPython/VirtualEnvConda"
+    "${CMake_BINARY_DIR}/Tests/FindPython/VirtualEnvConda"
+    ${build_generator_args}
+    --build-project TestVirtualEnvConda
+    --build-options ${build_options}
+    --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+    )
+ endif()

+ 4 - 0
Tests/FindPython/VirtualEnv/CMakeLists.txt

@@ -21,22 +21,26 @@ endif()
 
 add_test(NAME FindPython3.VirtualEnvDefault
          COMMAND "${CMAKE_COMMAND}" -E env --unset=PYTHONHOME
+                                           --unset=CONDA_PREFIX
                                            "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
+                                           --unset=CONDA_PREFIX
                                            "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
+                                           --unset=CONDA_PREFIX
                  "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_LIST_DIR}/VirtualEnvOnly.cmake")
 
 add_test(NAME FindPython3.VirtualEnvStandard
          COMMAND "${CMAKE_COMMAND}" -E env --unset=PYTHONHOME
+                                           --unset=CONDA_PREFIX
                                            "VIRTUAL_ENV=${Python3_VIRTUAL_ENV}"
                  "${CMAKE_COMMAND}" "-DPYTHON3_VIRTUAL_ENV=${Python3_VIRTUAL_ENV}"
                  -P "${CMAKE_CURRENT_LIST_DIR}/VirtualEnvStandard.cmake")

+ 46 - 0
Tests/FindPython/VirtualEnvConda/CMakeLists.txt

@@ -0,0 +1,46 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(TestVirtualEnvConda LANGUAGES NONE)
+
+include(CTest)
+
+find_program(CONDA_EXECUTABLE conda)
+if (CONDA_EXECUTABLE EQUAL NOTFOUND)
+  message (FATAL_ERROR "Fail to found Conda")
+endif()
+
+set (Python3_VIRTUAL_ENV "${CMAKE_CURRENT_BINARY_DIR}/condaenv")
+
+execute_process (COMMAND "${CONDA_EXECUTABLE}" create --no-default-packages --prefix "${Python3_VIRTUAL_ENV}" --yes python=3
+                 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.VirtualEnvDefaultConda
+         COMMAND "${CMAKE_COMMAND}" -E env --unset=PYTHONHOME
+                                           --unset=VIRTUAL_ENV
+                                           "CONDA_PREFIX=${Python3_VIRTUAL_ENV}"
+                 "${CMAKE_COMMAND}" "-DPYTHON3_VIRTUAL_ENV=${Python3_VIRTUAL_ENV}"
+                 -P "${CMAKE_CURRENT_LIST_DIR}/VirtualEnvDefault.cmake")
+
+add_test(NAME FindPython3.VirtualEnvOnlyConda
+         COMMAND "${CMAKE_COMMAND}" -E env --unset=PYTHONHOME
+                                           --unset=VIRTUAL_ENV
+                                           "CONDA_PREFIX=${Python3_VIRTUAL_ENV}"
+                 "${CMAKE_COMMAND}" "-DPYTHON3_VIRTUAL_ENV=${Python3_VIRTUAL_ENV}"
+                 -P "${CMAKE_CURRENT_LIST_DIR}/VirtualEnvOnly.cmake")
+add_test(NAME FindPython3.UnsetVirtualEnvOnlyConda
+         COMMAND "${CMAKE_COMMAND}" -E env --unset=PYTHONHOME
+                                           --unset=CONDA_PREFIX
+                                           --unset=VIRTUAL_ENV
+                 "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_LIST_DIR}/VirtualEnvOnly.cmake")
+
+add_test(NAME FindPython3.VirtualEnvStandardConda
+         COMMAND "${CMAKE_COMMAND}" -E env --unset=PYTHONHOME
+                                           --unset=VIRTUAL_ENV
+                                           "CONDA_PREFIX=${Python3_VIRTUAL_ENV}"
+                 "${CMAKE_COMMAND}" "-DPYTHON3_VIRTUAL_ENV=${Python3_VIRTUAL_ENV}"
+                 -P "${CMAKE_CURRENT_LIST_DIR}/VirtualEnvStandard.cmake")

+ 6 - 0
Tests/FindPython/VirtualEnvConda/VirtualEnvDefault.cmake

@@ -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 - 0
Tests/FindPython/VirtualEnvConda/VirtualEnvOnly.cmake

@@ -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 - 0
Tests/FindPython/VirtualEnvConda/VirtualEnvStandard.cmake

@@ -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()