소스 검색

FindPython*: New implementation for Python stuff

Fixes: #16142
Marc Chevrier 7 년 전
부모
커밋
352baee207

+ 2 - 0
Help/manual/cmake-developer.7.rst

@@ -644,6 +644,8 @@ Documentation`_ section above.
 
 
 
+.. _`CMake Developer Standard Variable Names`:
+
 Standard Variable Names
 ^^^^^^^^^^^^^^^^^^^^^^^
 

+ 3 - 0
Help/manual/cmake-modules.7.rst

@@ -196,6 +196,9 @@ All Modules
    /module/FindPostgreSQL
    /module/FindProducer
    /module/FindProtobuf
+   /module/FindPython
+   /module/FindPython2
+   /module/FindPython3
    /module/FindPythonInterp
    /module/FindPythonLibs
    /module/FindQt3

+ 1 - 0
Help/module/FindPython.rst

@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/FindPython.cmake

+ 1 - 0
Help/module/FindPython2.rst

@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/FindPython2.cmake

+ 1 - 0
Help/module/FindPython3.rst

@@ -0,0 +1 @@
+.. cmake-module:: ../../Modules/FindPython3.cmake

+ 5 - 0
Help/release/dev/FindPython-new-implementation.rst

@@ -0,0 +1,5 @@
+FindPython(2|3)
+---------------
+
+* The new :module:`FindPython3` and :module:`FindPython2` modules, as well as
+  :module:`FindPython`, provide a new way to locate python environments.

+ 180 - 0
Modules/FindPython.cmake

@@ -0,0 +1,180 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindPython
+----------
+
+Find Python interpreter, compiler and development environment (include
+directories and libraries).
+
+Three components are supported:
+
+* ``Interpreter``: search for Python interpreter.
+* ``Compiler``: search for Python compiler. Only offered by IronPython.
+* ``Development``: search for development artifacts (include directories and
+  libraries).
+
+If no ``COMPONENTS`` is specified, ``Interpreter`` is assumed.
+
+To ensure consistent versions between components ``Interpreter``, ``Compiler``
+and ``Development``, specify all components at the same time::
+
+  find_package (Python COMPONENTS Interpreter Development)
+
+This module looks preferably for version 3 of Python. If not found, version 2
+is searched.
+To manage concurrent versions 3 and 2 of Python, use :module:`FindPython3` and
+:module:`FindPython2` modules rather than this one.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module defines the following :ref:`Imported Targets <Imported Targets>`:
+
+``Python::Interpreter``
+  Python interpreter. Target defined if component ``Interpreter`` is found.
+``Python::Compiler``
+  Python compiler. Target defined if component ``Compiler`` is found.
+``Python::Python``
+  Python library. Target defined if component ``Development`` is found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module will set the following variables in your project
+(see :ref:`Standard Variable Names <CMake Developer Standard Variable Names>`):
+
+``Python_FOUND``
+  System has the Python requested components.
+``Python_Interpreter_FOUND``
+  System has the Python interpreter.
+``Python_EXECUTABLE``
+  Path to the Python interpreter.
+``Python_INTERPRETER_ID``
+  A short string unique to the interpreter. Possible values include:
+    * Python
+    * ActivePython
+    * Anaconda
+    * Canopy
+    * IronPython
+``Python_STDLIB``
+  Standard platform independent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=True)``.
+``Python_STDARCH``
+  Standard platform dependent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=True)``.
+``Python_SITELIB``
+  Third-party platform independent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False)``.
+``Python_SITEARCH``
+  Third-party platform dependent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``.
+``Python_Compiler_FOUND``
+  System has the Python compiler.
+``Python_COMPILER``
+  Path to the Python compiler. Only offered by IronPython.
+``Python_COMPILER_ID``
+  A short string unique to the compiler. Possible values include:
+    * IronPython
+``Python_Development_FOUND``
+  System has the Python development artifacts.
+``Python_INCLUDE_DIRS``
+  The Python include directories.
+``Python_LIBRARIES``
+  The Python libraries.
+``Python_LIBRARY_DIRS``
+  The Python library directories.
+``Python_RUNTIME_LIBRARY_DIRS``
+  The Python runtime library directories.
+``Python_VERSION``
+  Python version.
+``Python_VERSION_MAJOR``
+  Python major version.
+``Python_VERSION_MINOR``
+  Python minor version.
+``Python_VERSION_PATCH``
+  Python patch version.
+
+Hints
+^^^^^
+
+``Python_ROOT_DIR``
+  Define the root directory of a Python installation.
+
+``Python_USE_STATIC_LIBS``
+  * If not defined, search for shared libraries and static libraries in that
+    order.
+  * If set to TRUE, search **only** for static libraries.
+  * If set to FALSE, search **only** for shared libraries.
+
+Commands
+^^^^^^^^
+
+This module defines the command ``Python_add_library`` which have the same
+semantic as :command:`add_library` but take care of Python module naming rules
+(only applied if library is of type ``MODULE``) and add dependency to target
+``Python::Python``::
+
+  Python_add_library (my_module MODULE src1.cpp)
+
+If library type is not specified, ``MODULE`` is assumed.
+#]=======================================================================]
+
+
+set (_PYTHON_PREFIX Python)
+
+if (DEFINED Python_FIND_VERSION)
+  set (_Python_REQUIRED_VERSION_MAJOR ${Python_FIND_VERSION_MAJOR})
+
+  include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake)
+else()
+  # iterate over versions in quiet and NOT required modes to avoid multiple
+  # "Found" messages and prematurally failure.
+  set (_Python_QUIETLY ${Python_FIND_QUIETLY})
+  set (_Python_REQUIRED ${Python_FIND_REQUIRED})
+  set (Python_FIND_QUIETLY TRUE)
+  set (Python_FIND_REQUIRED FALSE)
+
+  foreach (_Python_REQUIRED_VERSION_MAJOR IN ITEMS 3 2)
+    set (Python_FIND_VERSION ${_Python_REQUIRED_VERSION_MAJOR})
+    include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake)
+    if (Python_FOUND)
+      break()
+    endif()
+    # clean-up some CACHE variables to ensure look-up restart from scratch
+    foreach (_Python_ITEM IN ITEMS EXECUTABLE COMPILER
+                                   LIBRARY_RELEASE RUNTIME_LIBRARY_RELEASE
+                                   LIBRARY_DEBUG RUNTIME_LIBRARY_DEBUG
+                                   INCLUDE_DIR)
+      unset (Python_${_Python_ITEM} CACHE)
+    endforeach()
+  endforeach()
+
+  unset (Python_FIND_VERSION)
+
+  set (Python_FIND_QUIETLY ${_Python_QUIETLY})
+  set (Python_FIND_REQUIRED ${_Python_REQUIRED})
+  if (Python_FIND_REQUIRED OR NOT Python_FIND_QUIETLY)
+    # call again validation command to get "Found" or error message
+    find_package_handle_standard_args (Python HANDLE_COMPONENTS
+                                              REQUIRED_VARS ${_Python_REQUIRED_VARS}
+                                              VERSION_VAR Python_VERSION)
+  endif()
+endif()
+
+if (COMMAND __Python_add_library)
+  macro (Python_add_library)
+    __Python_add_library (Python ${ARGV})
+  endmacro()
+endif()
+
+unset (_PYTHON_PREFIX)

+ 843 - 0
Modules/FindPython/Support.cmake

@@ -0,0 +1,843 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#
+# This file is a "template" file used by various FindPython modules.
+#
+
+cmake_policy (VERSION 3.7)
+
+#
+# Initial configuration
+#
+if (NOT DEFINED _PYTHON_PREFIX)
+  message (FATAL_ERROR "FindPython: INTERNAL ERROR")
+endif()
+if (NOT DEFINED _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+  message (FATAL_ERROR "FindPython: INTERNAL ERROR")
+endif()
+if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL 3)
+  set(_${_PYTHON_PREFIX}_VERSIONS 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0)
+elseif (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR EQUAL 2)
+  set(_${_PYTHON_PREFIX}_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0)
+else()
+  message (FATAL_ERROR "FindPython: INTERNAL ERROR")
+endif()
+
+
+#
+# helper commands
+#
+macro (_PYTHON_DISPLAY_FAILURE _PYTHON_MSG)
+  if (${_PYTHON_PREFIX}_FIND_REQUIRED)
+    message (FATAL_ERROR "${_PYTHON_MSG}")
+  else()
+    if (NOT ${_PYTHON_PREFIX}_FIND_QUIETLY)
+      message(STATUS "${_PYTHON_MSG}")
+    endif ()
+  endif()
+
+  set (${_PYTHON_PREFIX}_FOUND FALSE)
+  string (TOUPPER "${_PYTHON_PREFIX}" _${_PYTHON_PREFIX}_UPPER_PREFIX)
+  set (${_PYTHON_UPPER_PREFIX}_FOUND FALSE)
+  return()
+endmacro()
+
+
+function (_PYTHON_GET_FRAMEWORKS _PYTHON_PGF_FRAMEWORK_PATHS _PYTHON_VERSION)
+  set (_PYTHON_FRAMEWORK_PATHS)
+  foreach (_PYTHON_FRAMEWORK IN LISTS Python_FRAMEWORKS)
+    list (APPEND _PYTHON_FRAMEWORK_PATHS
+          "${_PYTHON_FRAMEWORK}/Versions/${_PYTHON_VERSION}")
+  endforeach()
+  set (${_PYTHON_PGF_FRAMEWORK_PATHS} ${_PYTHON_FRAMEWORK_PATHS} PARENT_SCOPE)
+endfunction()
+
+
+function (_PYTHON_FIND_RUNTIME_LIBRARY _PYTHON_LIB)
+  string (REPLACE "_RUNTIME" "" _PYTHON_LIB "${_PYTHON_LIB}")
+  # look at runtime part on systems supporting it
+  if (CMAKE_SYSTEM_NAME STREQUAL "Windows" OR
+      (CMAKE_SYSTEM_NAME MATCHES "MSYS|CYGWIN"
+        AND ${_PYTHON_LIB} MATCHES "${CMAKE_IMPORT_LIBRARY_SUFFIX}$"))
+    set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_SHARED_LIBRARY_SUFFIX})
+    # MSYS has a special syntax for runtime libraries
+    if (CMAKE_SYSTEM_NAME MATCHES "MSYS")
+      list (APPEND CMAKE_FIND_LIBRARY_PREFIXES "msys-")
+    endif()
+    find_library (${ARGV})
+  endif()
+endfunction()
+
+
+function (_PYTHON_SET_LIBRARY_DIRS _PYTHON_SLD_RESULT)
+  unset (_PYTHON_DIRS)
+  set (_PYTHON_LIBS ${ARGV})
+  list (REMOVE_AT _PYTHON_LIBS 0)
+  foreach (_PYTHON_LIB IN LISTS _PYTHON_LIBS)
+    if (${_PYTHON_LIB})
+      get_filename_component (_PYTHON_DIR "${${_PYTHON_LIB}}" DIRECTORY)
+      list (APPEND _PYTHON_DIRS "${_PYTHON_DIR}")
+    endif()
+  endforeach()
+  if (_PYTHON_DIRS)
+    list (REMOVE_DUPLICATES _PYTHON_DIRS)
+  endif()
+  set (${_PYTHON_SLD_RESULT} ${_PYTHON_DIRS} PARENT_SCOPE)
+endfunction()
+
+
+# If major version is specified, it must be the same as internal major version
+if (DEFINED ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR
+    AND NOT ${_PYTHON_PREFIX}_FIND_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+  _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Wrong major version specified is \"${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}\", but expected major version is \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"")
+endif()
+
+
+# handle components
+if (NOT ${_PYTHON_PREFIX}_FIND_COMPONENTS)
+  set (${_PYTHON_PREFIX}_FIND_COMPONENTS Interpreter)
+  set (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter TRUE)
+endif()
+foreach (_${_PYTHON_PREFIX}_COMPONENT IN LISTS ${_PYTHON_PREFIX}_FIND_COMPONENTS)
+  set (${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_FOUND FALSE)
+endforeach()
+unset (_${_PYTHON_PREFIX}_FIND_VERSIONS)
+
+# Set versions to search
+## default: search any version
+set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSIONS})
+
+if (${_PYTHON_PREFIX}_FIND_VERSION_COUNT GREATER 1)
+  if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT)
+    set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_FIND_VERSION_MAJOR}.${${_PYTHON_PREFIX}_FIND_VERSION_MINOR})
+  else()
+    unset (_${_PYTHON_PREFIX}_FIND_VERSIONS)
+    # add all compatible versions
+    foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_VERSIONS)
+      if (_${_PYTHON_PREFIX}_VERSION VERSION_GREATER_EQUAL ${_PYTHON_PREFIX}_FIND_VERSION)
+        list (APPEND _${_PYTHON_PREFIX}_FIND_VERSIONS ${_${_PYTHON_PREFIX}_VERSION})
+      endif()
+    endforeach()
+  endif()
+endif()
+
+# Anaconda distribution: define which architectures can be used
+if (CMAKE_SIZEOF_VOID_P)
+  # In this case, search only for 64bit or 32bit
+  math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
+  set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH})
+else()
+  # architecture unknown, search for both 64bit and 32bit
+  set (_${_PYTHON_PREFIX}_ARCH 64)
+  set (_${_PYTHON_PREFIX}_ARCH2 32)
+endif()
+
+# IronPython support
+if (CMAKE_SIZEOF_VOID_P)
+  # In this case, search only for 64bit or 32bit
+  math (EXPR _${_PYTHON_PREFIX}_ARCH "${CMAKE_SIZEOF_VOID_P} * 8")
+  set (_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES ipy${_${_PYTHON_PREFIX}_ARCH} ipy)
+else()
+  # architecture unknown, search for natural interpreter
+  set (_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES ipy)
+endif()
+
+# Apple frameworks handling
+include (${CMAKE_CURRENT_LIST_DIR}/../CMakeFindFrameworks.cmake)
+cmake_find_frameworks (Python)
+
+# Save CMAKE_FIND_FRAMEWORK
+if (DEFINED CMAKE_FIND_FRAMEWORK)
+  set (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK})
+else()
+  unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
+endif()
+# To avoid picking up the system elements pre-maturely.
+set (CMAKE_FIND_FRAMEWORK LAST)
+
+
+unset (${_PYTHON_PREFIX}_VERSION_MAJOR)
+unset (${_PYTHON_PREFIX}_VERSION_MINOR)
+unset (${_PYTHON_PREFIX}_VERSION_PATCH)
+
+unset (_${_PYTHON_PREFIX}_REQUIRED_VARS)
+
+
+# first step, search for the interpreter
+if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
+  if (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter)
+    list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_EXECUTABLE)
+  endif()
+
+  set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
+
+  # look-up for various versions and locations
+  foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
+    string (REPLACE "." "" _${_PYTHON_PREFIX}_VERSION_NO_DOTS ${_${_PYTHON_PREFIX}_VERSION})
+
+    _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
+
+    # try using HINTS
+    find_program (${_PYTHON_PREFIX}_EXECUTABLE
+                  NAMES python${_${_PYTHON_PREFIX}_VERSION}
+                  NAMES_PER_DIR
+                  HINTS ${_${_PYTHON_PREFIX}_HINTS}
+                  PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+                  PATH_SUFFIXES bin
+                  NO_SYSTEM_ENVIRONMENT_PATH
+                  NO_CMAKE_SYSTEM_PATH)
+    # try using registry
+    if (WIN32)
+      find_program (${_PYTHON_PREFIX}_EXECUTABLE
+                    NAMES python${_${_PYTHON_PREFIX}_VERSION} python
+                          ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
+                    NAMES_PER_DIR
+                    HINTS ${_${_PYTHON_PREFIX}_HINTS}
+                    PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                          [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                          [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
+                          [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                          [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                          [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH2}\\InstallPath]
+                          [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                    PATH_SUFFIXES bin
+                    NO_SYSTEM_ENVIRONMENT_PATH
+                    NO_CMAKE_SYSTEM_PATH)
+    endif()
+    # try in standard paths
+    find_program (${_PYTHON_PREFIX}_EXECUTABLE
+                  NAMES python${_${_PYTHON_PREFIX}_VERSION})
+
+    if (${_PYTHON_PREFIX}_EXECUTABLE)
+      break()
+    endif()
+  endforeach()
+
+  # try more generic names
+  find_program (${_PYTHON_PREFIX}_EXECUTABLE
+                NAMES python${${_PYTHON_PREFIX}_VERSION_MAJOR} python
+                      ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}
+                HINTS ${_${_PYTHON_PREFIX}_HINTS}
+                PATH_SUFFIXES bin)
+
+  # retrieve exact version of executable found
+  if (${_PYTHON_PREFIX}_EXECUTABLE)
+    execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
+                             "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))"
+                     RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                     OUTPUT_VARIABLE ${_PYTHON_PREFIX}_VERSION
+                     ERROR_QUIET
+                     OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (NOT _${_PYTHON_PREFIX}_RESULT)
+      string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${${_PYTHON_PREFIX}_VERSION}")
+      list (GET _${_PYTHON_PREFIX}_VERSIONS 0 ${_PYTHON_PREFIX}_VERSION_MAJOR)
+      list (GET _${_PYTHON_PREFIX}_VERSIONS 1 ${_PYTHON_PREFIX}_VERSION_MINOR)
+      list (GET _${_PYTHON_PREFIX}_VERSIONS 2 ${_PYTHON_PREFIX}_VERSION_PATCH)
+    else()
+      # Interpreter is not usable
+      set (${_PYTHON_PREFIX}_EXECUTABLE ${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND CACHE INTERNAL "" FORCE)
+      unset (${_PYTHON_PREFIX}_VERSION)
+    endif()
+  endif()
+
+  if (${_PYTHON_PREFIX}_EXECUTABLE
+      AND ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+    set (${_PYTHON_PREFIX}_Interpreter_FOUND TRUE)
+    # Use interpreter version for future searchs to ensure consistency
+    set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
+  endif()
+
+  if (${_PYTHON_PREFIX}_Interpreter_FOUND)
+    # retrieve interpreter identity
+    execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -V
+                     RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                     OUTPUT_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID
+                     ERROR_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID)
+    if (NOT _${_PYTHON_PREFIX}_RESULT)
+      if (${_PYTHON_PREFIX}_INTERPRETER_ID MATCHES "Anaconda")
+        set (${_PYTHON_PREFIX}_INTERPRETER_ID "Anaconda")
+      elseif (${_PYTHON_PREFIX}_INTERPRETER_ID MATCHES "Enthought")
+        set (${_PYTHON_PREFIX}_INTERPRETER_ID "Canopy")
+      else()
+        string (REGEX REPLACE "^([^ ]+).*" "\\1" ${_PYTHON_PREFIX}_INTERPRETER_ID "${${_PYTHON_PREFIX}_INTERPRETER_ID}")
+        if (${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "Python")
+          # try to get a more precise ID
+          execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.copyright)"
+                           RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                           OUTPUT_VARIABLE ${_PYTHON_PREFIX}_COPYRIGHT
+                           ERROR_QUIET)
+          if (${_PYTHON_PREFIX}_COPYRIGHT MATCHES "ActiveState")
+            set (${_PYTHON_PREFIX}_INTERPRETER_ID "ActivePython")
+          endif()
+        endif()
+      endif()
+    else()
+      set (${_PYTHON_PREFIX}_INTERPRETER_ID Python)
+    endif()
+  else()
+    unset (${_PYTHON_PREFIX}_INTERPRETER_ID)
+  endif()
+
+  # retrieve various package installation directories
+  execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig;sys.stdout.write(';'.join([sysconfig.get_python_lib(plat_specific=False,standard_lib=True),sysconfig.get_python_lib(plat_specific=True,standard_lib=True),sysconfig.get_python_lib(plat_specific=False,standard_lib=False),sysconfig.get_python_lib(plat_specific=True,standard_lib=False)]))"
+
+                   RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                   OUTPUT_VARIABLE _${_PYTHON_PREFIX}_LIBPATHS
+                   ERROR_QUIET)
+  if (NOT _${_PYTHON_PREFIX}_RESULT)
+    list (GET _${_PYTHON_PREFIX}_LIBPATHS 0 ${_PYTHON_PREFIX}_STDLIB)
+    list (GET _${_PYTHON_PREFIX}_LIBPATHS 1 ${_PYTHON_PREFIX}_STDARCH)
+    list (GET _${_PYTHON_PREFIX}_LIBPATHS 2 ${_PYTHON_PREFIX}_SITELIB)
+    list (GET _${_PYTHON_PREFIX}_LIBPATHS 3 ${_PYTHON_PREFIX}_SITEARCH)
+  else()
+    unset (${_PYTHON_PREFIX}_STDLIB)
+    unset (${_PYTHON_PREFIX}_STDARCH)
+    unset (${_PYTHON_PREFIX}_SITELIB)
+    unset (${_PYTHON_PREFIX}_SITEARCH)
+  endif()
+
+  mark_as_advanced (${_PYTHON_PREFIX}_EXECUTABLE)
+endif()
+
+
+# second step, search for compiler (IronPython)
+if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
+  if (${_PYTHON_PREFIX}_FIND_REQUIRED_Compiler)
+    list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_COMPILER)
+  endif()
+
+  # IronPython specific artifacts
+  # If IronPython interpreter is found, use its path
+  unset (_${_PYTHON_PREFIX}_IRON_ROOT)
+  if (${_PYTHON_PREFIX}_Interpreter_FOUND AND ${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "IronPython")
+    get_filename_component (_${_PYTHON_PREFIX}_IRON_ROOT "${${_PYTHON_PREFIX}_EXECUTABLE}" DIRECTORY)
+  endif()
+
+  # try using root dir and registry
+  foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
+    find_program (${_PYTHON_PREFIX}_COMPILER
+                  NAMES ipyc
+                  HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS}
+                  PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                  NO_SYSTEM_ENVIRONMENT_PATH
+                  NO_CMAKE_SYSTEM_PATH)
+    if (${_PYTHON_PREFIX}_COMPILER)
+      break()
+    endif()
+  endforeach()
+  # try in standard paths
+  find_program (${_PYTHON_PREFIX}_COMPILER
+                NAMES ipyc)
+
+  if (${_PYTHON_PREFIX}_COMPILER)
+    # retrieve python environment version from compiler
+    set (_${_PYTHON_PREFIX}_VERSION_DIR "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir")
+    file (WRITE "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))\n")
+    execute_process (COMMAND "${${_PYTHON_PREFIX}_COMPILER}" /target:exe /embed "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py"
+                     WORKING_DIRECTORY "${_${_PYTHON_PREFIX}_VERSION_DIR}"
+                     OUTPUT_QUIET
+                     ERROR_QUIET)
+    execute_process (COMMAND "${_${_PYTHON_PREFIX}_VERSION_DIR}/version"
+                     WORKING_DIRECTORY "${_${_PYTHON_PREFIX}_VERSION_DIR}"
+                     RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                     OUTPUT_VARIABLE _${_PYTHON_PREFIX}_VERSION
+                     ERROR_QUIET)
+    if (NOT _${_PYTHON_PREFIX}_RESULT)
+      string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${_${_PYTHON_PREFIX}_VERSION}")
+      list (GET _${_PYTHON_PREFIX}_VERSIONS 0 _${_PYTHON_PREFIX}_VERSION_MAJOR)
+      list (GET _${_PYTHON_PREFIX}_VERSIONS 1 _${_PYTHON_PREFIX}_VERSION_MINOR)
+      list (GET _${_PYTHON_PREFIX}_VERSIONS 2 _${_PYTHON_PREFIX}_VERSION_PATCH)
+
+      if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND)
+        # set public version information
+        set (${_PYTHON_PREFIX}_VERSION ${_${_PYTHON_PREFIX}_VERSION})
+        set (${_PYTHON_PREFIX}_VERSION_MAJOR ${_${_PYTHON_PREFIX}_VERSION_MAJOR})
+        set (${_PYTHON_PREFIX}_VERSION_MINOR ${_${_PYTHON_PREFIX}_VERSION_MINOR})
+        set (${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_VERSION_PATCH})
+      endif()
+    else()
+      # compiler not usable
+      set (${_PYTHON_PREFIX}_COMPILER ${_PYTHON_PREFIX}_COMPILER-NOTFOUND CACHE INTERNAL "" FORCE)
+    endif()
+    file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}")
+  endif()
+
+  if (${_PYTHON_PREFIX}_COMPILER)
+    if (${_PYTHON_PREFIX}_Interpreter_FOUND)
+      # Compiler must be compatible with interpreter
+      if (${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR} VERSION_EQUAL ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
+        set (${_PYTHON_PREFIX}_Compiler_FOUND TRUE)
+      endif()
+    elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+      set (${_PYTHON_PREFIX}_Compiler_FOUND TRUE)
+    # Use compiler version for future searchs to ensure consistency
+    set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
+    endif()
+  endif()
+
+  if (${_PYTHON_PREFIX}_Compiler_FOUND)
+    set (${_PYTHON_PREFIX}_COMPILER_ID IronPython)
+  else()
+    unset (${_PYTHON_PREFIX}_COMPILER_ID)
+  endif()
+
+  mark_as_advanced (${_PYTHON_PREFIX}_COMPILER)
+endif()
+
+
+# third step, search for the development artifacts
+## Development environment is not compatible with IronPython interpreter
+if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+    AND NOT ${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "IronPython")
+  if (${_PYTHON_PREFIX}_FIND_REQUIRED_Development)
+    list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_LIBRARY
+                                                  ${_PYTHON_PREFIX}_INCLUDE_DIR)
+  endif()
+
+  # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES
+  unset (_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES)
+  if (DEFINED ${_PYTHON_PREFIX}_USE_STATIC_LIBS AND NOT WIN32)
+    set(_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_FIND_LIBRARY_SUFFIXES})
+    if(${_PYTHON_PREFIX}_USE_STATIC_LIBS)
+      set (CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
+    else()
+      list (REMOVE_ITEM CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX})
+    endif()
+  else()
+  endif()
+
+  # if python interpreter is found, use its location and version to ensure consistency
+  # between interpreter and development environment
+  unset (_${_PYTHON_PREFIX}_PREFIX)
+  if (${_PYTHON_PREFIX}_Interpreter_FOUND)
+    execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
+                             "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.PREFIX)"
+                     RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                     OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PREFIX
+                     ERROR_QUIET
+                     OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (_${_PYTHON_PREFIX}_RESULT)
+      unset (_${_PYTHON_PREFIX}_PREFIX)
+    endif()
+  endif()
+  set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_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})
+
+    # try to use pythonX.Y-config tool
+    find_program (_${_PYTHON_PREFIX}_CONFIG
+                  NAMES python${_${_PYTHON_PREFIX}_VERSION}-config
+                  HINTS ${_${_PYTHON_PREFIX}_HINTS}
+                  PATH_SUFFIXES bin)
+
+    if (NOT _${_PYTHON_PREFIX}_CONFIG)
+      continue()
+    endif()
+
+    # retrieve root install directory
+    execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --prefix
+                     RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                     OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PREFIX
+                     ERROR_QUIET
+                     OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (_${_PYTHON_PREFIX}_RESULT)
+      # python-config is not usable
+      unset (_${_PYTHON_PREFIX}_CONFIG CACHE)
+      continue()
+    endif()
+    set (_${_PYTHON_PREFIX}_HINTS "${_${_PYTHON_PREFIX}_PREFIX}" "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR)
+
+    # retrieve library
+    execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --ldflags
+                     RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                     OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS
+                     ERROR_QUIET
+                     OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (NOT _${_PYTHON_PREFIX}_RESULT)
+      # retrieve library directory
+      string (REGEX MATCHALL "-L[^ ]+" _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_FLAGS}")
+      string (REPLACE "-L" "" _${_PYTHON_PREFIX}_LIB_DIRS "${_${_PYTHON_PREFIX}_LIB_DIRS}")
+      list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_LIB_DIRS)
+      # retrieve library name
+      string (REGEX MATCHALL "-lpython[^ ]+" _${_PYTHON_PREFIX}_LIB_NAMES "${_${_PYTHON_PREFIX}_FLAGS}")
+      string (REPLACE "-l" "" _${_PYTHON_PREFIX}_LIB_NAMES "${_${_PYTHON_PREFIX}_LIB_NAMES}")
+      list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_LIB_NAMES)
+
+      find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE
+                    NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
+                    NAMES_PER_DIR
+                    HINTS ${_${_PYTHON_PREFIX}_HINTS} ${_${_PYTHON_PREFIX}_LIB_DIRS}
+                    PATH_SUFFIXES lib
+                    NO_SYSTEM_ENVIRONMENT_PATH
+                    NO_CMAKE_SYSTEM_PATH)
+       # retrieve runtime library
+       if (${_PYTHON_PREFIX}_LIBRARY_RELEASE)
+         get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
+         _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE
+                                       NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES}
+                                       NAMES_PER_DIR
+                                       HINTS ${_${_PYTHON_PREFIX}_PATH} ${_${_PYTHON_PREFIX}_HINTS}
+                                       PATH_SUFFIXES bin
+                                       NO_SYSTEM_ENVIRONMENT_PATH
+                                       NO_CMAKE_SYSTEM_PATH)
+       endif()
+    endif()
+
+    # retrieve include directory
+    execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --includes
+                     RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                     OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS
+                     ERROR_QUIET
+                     OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (NOT _${_PYTHON_PREFIX}_RESULT)
+      # retrieve include directory
+      string (REGEX MATCHALL "-I[^ ]+" _${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_FLAGS}")
+      string (REPLACE "-I" "" _${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_INCLUDE_DIRS}")
+      list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_INCLUDE_DIRS)
+
+      find_path (${_PYTHON_PREFIX}_INCLUDE_DIR
+                 NAMES Python.h
+                 HINTS ${_${_PYTHON_PREFIX}_INCLUDE_DIRS}
+                 NO_SYSTEM_ENVIRONMENT_PATH
+                 NO_CMAKE_SYSTEM_PATH)
+    endif()
+
+    if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_INCLUDE_DIR)
+      break()
+    endif()
+  endforeach()
+
+  # Rely on HINTS and standard paths if config tool failed to locate artifacts
+  if (NOT (${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG) OR NOT ${_PYTHON_PREFIX}_INCLUDE_DIR)
+    foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS)
+      string (REPLACE "." "" _${_PYTHON_PREFIX}_VERSION_NO_DOTS ${_${_PYTHON_PREFIX}_VERSION})
+
+      _python_get_frameworks (_${_PYTHON_PREFIX}_FRAMEWORK_PATHS ${_${_PYTHON_PREFIX}_VERSION})
+
+      find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE
+                    NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}
+                          python${_${_PYTHON_PREFIX}_VERSION}mu
+                          python${_${_PYTHON_PREFIX}_VERSION}m
+                          python${_${_PYTHON_PREFIX}_VERSION}u
+                          python${_${_PYTHON_PREFIX}_VERSION}
+                    NAMES_PER_DIR
+                    HINTS ${_${_PYTHON_PREFIX}_HINTS}
+                    PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+                          [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                          [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                          [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                          [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                    PATH_SUFFIXES lib libs
+                                  lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}mu
+                                  lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}m
+                                  lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}u
+                                  lib/python${_${_PYTHON_PREFIX}_VERSION}/config-${_${_PYTHON_PREFIX}_VERSION}
+                                  lib/python${_${_PYTHON_PREFIX}_VERSION}/config)
+      # retrieve runtime library
+      if (${_PYTHON_PREFIX}_LIBRARY_RELEASE)
+         get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
+        _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE
+                                      NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}
+                                            python${_${_PYTHON_PREFIX}_VERSION}mu
+                                            python${_${_PYTHON_PREFIX}_VERSION}m
+                                            python${_${_PYTHON_PREFIX}_VERSION}u
+                                            python${_${_PYTHON_PREFIX}_VERSION}
+                                      NAMES_PER_DIR
+                                      HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
+                                      PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+                                            [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                                            [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                                            [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                                            [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                                      PATH_SUFFIXES bin)
+      endif()
+
+      if (WIN32)
+        # search for debug library
+        if (${_PYTHON_PREFIX}_LIBRARY_RELEASE)
+          # use library location as a hint
+          get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY)
+          find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG
+                      NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
+                      NAMES_PER_DIR
+                      HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
+                      NO_DEFAULT_PATH)
+        else()
+          find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG
+                        NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
+                        NAMES_PER_DIR
+                        HINTS ${_${_PYTHON_PREFIX}_HINTS}
+                        PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                              [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                              [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                              [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                        PATH_SUFFIXES lib libs)
+        endif()
+        if (${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+         get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}" DIRECTORY)
+          _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG
+                                        NAMES python${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}_d
+                                        NAMES_PER_DIR
+                                        HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS}
+                                        PATHS [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                                              [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                                              [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                                              [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                                        PATH_SUFFIXES bin)
+        endif()
+      endif()
+
+      # Don't search for include dir until library location is known
+      if (${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+        unset (_${_PYTHON_PREFIX}_INCLUDE_HINTS)
+        foreach (_${_PYTHON_PREFIX}_LIB IN ITEMS ${_PYTHON_PREFIX}_LIBRARY_RELEASE ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+          if (${_${_PYTHON_PREFIX}_LIB})
+            # Use the library's install prefix as a hint
+            if (${_${_PYTHON_PREFIX}_LIB} MATCHES "^(.+/Frameworks/Python.framework/Versions/[0-9.]+)")
+              list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}")
+            elseif (${_${_PYTHON_PREFIX}_LIB} MATCHES "^(.+)/lib(64|32)?/python[0-9.]+/config")
+              list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}")
+            else()
+              # assume library is in a directory under root
+              get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${${_${_PYTHON_PREFIX}_LIB}}" DIRECTORY)
+              get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${_${_PYTHON_PREFIX}_PREFIX}" DIRECTORY)
+              list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${_${_PYTHON_PREFIX}_PREFIX}")
+            endif()
+          endif()
+        endforeach()
+        list (REMOVE_DUPLICATES _${_PYTHON_PREFIX}_INCLUDE_HINTS)
+
+        find_path (${_PYTHON_PREFIX}_INCLUDE_DIR
+                   NAMES Python.h
+                   HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS}
+                   PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS}
+                         [HKEY_CURRENT_USER\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                         [HKEY_CURRENT_USER\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                         [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath]
+                         [HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\ContinuumAnalytics\\Anaconda${_${_PYTHON_PREFIX}_VERSION_NO_DOTS}-${_${_PYTHON_PREFIX}_ARCH}\\InstallPath]
+                   PATH_SUFFIXES include/python${_${_PYTHON_PREFIX}_VERSION}mu
+                                 include/python${_${_PYTHON_PREFIX}_VERSION}m
+                                 include/python${_${_PYTHON_PREFIX}_VERSION}u
+                                 include/python${_${_PYTHON_PREFIX}_VERSION}
+                                 include
+                   NO_SYSTEM_ENVIRONMENT_PATH
+                   NO_CMAKE_SYSTEM_PATH)
+      endif()
+
+      if ((${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG) AND ${_PYTHON_PREFIX}_INCLUDE_DIR)
+        break()
+      endif()
+    endforeach()
+
+    # search header file in standard locations
+    find_path (${_PYTHON_PREFIX}_INCLUDE_DIR
+               NAMES Python.h)
+  endif()
+
+  if (${_PYTHON_PREFIX}_INCLUDE_DIR)
+    # retrieve version from header file
+    file (STRINGS "${${_PYTHON_PREFIX}_INCLUDE_DIR}/patchlevel.h" _${_PYTHON_PREFIX}_VERSION
+          REGEX "^#define[ \t]+PY_VERSION[ \t]+\"[^\"]+\"")
+    string (REGEX REPLACE "^#define[ \t]+PY_VERSION[ \t]+\"([^\"]+)\".*" "\\1"
+                          _${_PYTHON_PREFIX}_VERSION "${_${_PYTHON_PREFIX}_VERSION}")
+    string (REGEX MATCHALL "[0-9]+" _${_PYTHON_PREFIX}_VERSIONS "${_${_PYTHON_PREFIX}_VERSION}")
+    list (GET _${_PYTHON_PREFIX}_VERSIONS 0 _${_PYTHON_PREFIX}_VERSION_MAJOR)
+    list (GET _${_PYTHON_PREFIX}_VERSIONS 1 _${_PYTHON_PREFIX}_VERSION_MINOR)
+    list (GET _${_PYTHON_PREFIX}_VERSIONS 2 _${_PYTHON_PREFIX}_VERSION_PATCH)
+
+    if (NOT ${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT ${_PYTHON_PREFIX}_Compiler_FOUND)
+      # set public version information
+      set (${_PYTHON_PREFIX}_VERSION ${_${_PYTHON_PREFIX}_VERSION})
+      set (${_PYTHON_PREFIX}_VERSION_MAJOR ${_${_PYTHON_PREFIX}_VERSION_MAJOR})
+      set (${_PYTHON_PREFIX}_VERSION_MINOR ${_${_PYTHON_PREFIX}_VERSION_MINOR})
+      set (${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_VERSION_PATCH})
+    endif()
+  endif()
+
+  # define public variables
+  include (${CMAKE_CURRENT_LIST_DIR}/../SelectLibraryConfigurations.cmake)
+  select_library_configurations (${_PYTHON_PREFIX})
+  if (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE)
+    set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}")
+  elseif (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG)
+    set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}")
+  else()
+    set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY "$${_PYTHON_PREFIX}_RUNTIME_LIBRARY-NOTFOUND")
+  endif()
+
+  _python_set_library_dirs (${_PYTHON_PREFIX}_LIBRARY_DIRS
+                            ${_PYTHON_PREFIX}_LIBRARY_RELEASE ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+  if (UNIX)
+    if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$"
+        OR ${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$")
+      set (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DIRS ${${_PYTHON_PREFIX}_LIBRARY_DIRS})
+    endif()
+  else()
+      _python_set_library_dirs (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DIRS
+                                ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG)
+  endif()
+
+  set (${_PYTHON_PREFIX}_INCLUDE_DIRS "${${_PYTHON_PREFIX}_INCLUDE_DIR}")
+
+  mark_as_advanced (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE
+                    ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG
+                    ${_PYTHON_PREFIX}_INCLUDE_DIR)
+
+  if ((${_PYTHON_PREFIX}_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+      AND ${_PYTHON_PREFIX}_INCLUDE_DIR)
+    if (${_PYTHON_PREFIX}_Interpreter_FOUND OR ${_PYTHON_PREFIX}_Compiler_FOUND)
+      # devlopment environment must be compatible with interpreter/compiler
+      if (${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR} VERSION_EQUAL ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR})
+        set (${_PYTHON_PREFIX}_Development_FOUND TRUE)
+      endif()
+    elseif (${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+      set (${_PYTHON_PREFIX}_Development_FOUND TRUE)
+    endif()
+  endif()
+
+  # Restore the original find library ordering
+  if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES)
+    set (CMAKE_FIND_LIBRARY_SUFFIXES ${_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES})
+  endif()
+endif()
+
+# final validation
+if (${_PYTHON_PREFIX}_VERSION_MAJOR AND
+    NOT ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
+  _python_display_failure ("Could NOT find ${_PYTHON_PREFIX}: Found unsuitable major version \"${${_PYTHON_PREFIX}_VERSION_MAJOR}\", but required major version is exact version \"${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}\"")
+endif()
+
+include (${CMAKE_CURRENT_LIST_DIR}/../FindPackageHandleStandardArgs.cmake)
+find_package_handle_standard_args (${_PYTHON_PREFIX}
+                                   REQUIRED_VARS ${_${_PYTHON_PREFIX}_REQUIRED_VARS}
+                                   VERSION_VAR ${_PYTHON_PREFIX}_VERSION
+                                   HANDLE_COMPONENTS)
+
+# Create imported targets and helper functions
+if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+    AND ${_PYTHON_PREFIX}_Interpreter_FOUND
+    AND NOT TARGET ${_PYTHON_PREFIX}::Interpreter)
+  add_executable (${_PYTHON_PREFIX}::Interpreter IMPORTED)
+  set_property (TARGET ${_PYTHON_PREFIX}::Interpreter
+                PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_EXECUTABLE}")
+endif()
+
+if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+    AND ${_PYTHON_PREFIX}_Compiler_FOUND
+    AND NOT TARGET ${_PYTHON_PREFIX}::Compiler)
+  add_executable (${_PYTHON_PREFIX}::Compiler IMPORTED)
+  set_property (TARGET ${_PYTHON_PREFIX}::Compiler
+                PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_COMPILER}")
+endif()
+
+if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
+    AND ${_PYTHON_PREFIX}_Development_FOUND AND NOT TARGET ${_PYTHON_PREFIX}::Python)
+
+  if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$"
+      OR ${_PYTHON_PREFIX}_LIBRARY_DEBUG MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}$"
+      OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE OR ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG)
+    set (_${_PYTHON_PREFIX}_LIBRARY_TYPE SHARED)
+  else()
+    set (_${_PYTHON_PREFIX}_LIBRARY_TYPE STATIC)
+  endif()
+
+  add_library (${_PYTHON_PREFIX}::Python ${_${_PYTHON_PREFIX}_LIBRARY_TYPE} IMPORTED)
+
+  set_property (TARGET ${_PYTHON_PREFIX}::Python
+                PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIR}")
+
+  if ((${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE)
+      OR (${_PYTHON_PREFIX}_LIBRARY_DEBUG AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG))
+    # System manage shared libraries in two parts: import and runtime
+    if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+      set_property (TARGET ${_PYTHON_PREFIX}::Python PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG)
+      set_target_properties (${_PYTHON_PREFIX}::Python
+                             PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
+                                        IMPORTED_IMPLIB_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}"
+                                        IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE}")
+      set_target_properties (${_PYTHON_PREFIX}::Python
+                             PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
+                                        IMPORTED_IMPLIB_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}"
+                                        IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG}")
+    else()
+      set_target_properties (${_PYTHON_PREFIX}::Python
+                             PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+                                        IMPORTED_IMPLIB "${${_PYTHON_PREFIX}_LIBRARY}"
+                                        IMPORTED_LOCATION "${${_PYTHON_PREFIX}_RUNTIME_LIBRARY}")
+    endif()
+  else()
+    if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_LIBRARY_DEBUG)
+      set_property (TARGET ${_PYTHON_PREFIX}::Python PROPERTY IMPORTED_CONFIGURATIONS RELEASE DEBUG)
+      set_target_properties (${_PYTHON_PREFIX}::Python
+                             PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_RELEASE "C"
+                                        IMPORTED_LOCATION_RELEASE "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}")
+      set_target_properties (${_PYTHON_PREFIX}::Python
+                             PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES_DEBUG "C"
+                                        IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}")
+    else()
+      set_target_properties (${_PYTHON_PREFIX}::Python
+                             PROPERTIES IMPORTED_LINK_INTERFACE_LANGUAGES "C"
+                                        IMPORTED_LOCATION "${${_PYTHON_PREFIX}_LIBRARY}")
+    endif()
+  endif()
+
+  if (_${_PYTHON_PREFIX}_CONFIG AND _${_PYTHON_PREFIX}_LIBRARY_TYPE STREQUAL "STATIC")
+    # extend link information with dependent libraries
+    execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --ldflags
+                     RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+                     OUTPUT_VARIABLE _${_PYTHON_PREFIX}_FLAGS
+                     ERROR_QUIET
+                     OUTPUT_STRIP_TRAILING_WHITESPACE)
+    if (NOT _${_PYTHON_PREFIX}_RESULT)
+      string (REGEX MATCHALL "-[Ll][^ ]+" _${_PYTHON_PREFIX}_LINK_LIBRARIES "${_${_PYTHON_PREFIX}_FLAGS}")
+      # remove elements relative to python library itself
+      list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-lpython")
+      foreach (_${_PYTHON_PREFIX}_DIR IN LISTS ${_PYTHON_PREFIX}_LIBRARY_DIRS)
+        list (FILTER _${_PYTHON_PREFIX}_LINK_LIBRARIES EXCLUDE REGEX "-L${${_PYTHON_PREFIX}_DIR}")
+      endforeach()
+      set_property (TARGET ${_PYTHON_PREFIX}::Python
+                    PROPERTY INTERFACE_LINK_LIBRARIES ${_${_PYTHON_PREFIX}_LINK_LIBRARIES})
+    endif()
+  endif()
+
+  #
+  # PYTHON_ADD_LIBRARY (<name> [STATIC|SHARED|MODULE] src1 src2 ... srcN)
+  # It is used to build modules for python.
+  #
+  function (__${_PYTHON_PREFIX}_ADD_LIBRARY prefix name)
+    cmake_parse_arguments (PARSE_ARGV 2 PYTHON_ADD_LIBRARY
+                           "STATIC;SHARED;MODULE" "" "")
+
+    unset (type)
+    if (NOT (PYTHON_ADD_LIBRARY_STATIC
+          OR PYTHON_ADD_LIBRARY_SHARED
+          OR PYTHON_ADD_LIBRARY_MODULE))
+      set (type MODULE)
+    endif()
+    add_library (${name} ${type} ${ARGN})
+    target_link_libraries (${name} PRIVATE ${prefix}::Python)
+
+    # customize library name to follow module name rules
+    get_property (type TARGET ${name} PROPERTY TYPE)
+    if (type STREQUAL "MODULE_LIBRARY")
+      set_property (TARGET ${name} PROPERTY PREFIX "")
+      if(CMAKE_SYSTEM_NAME STREQUAL "Windows")
+        set_property (TARGET ${name} PROPERTY SUFFIX ".pyd")
+      endif()
+    endif()
+  endfunction()
+endif()
+
+# final clean-up
+
+# Restore CMAKE_FIND_FRAMEWORK
+if (DEFINED _${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
+  set (CMAKE_FIND_FRAMEWORK ${_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK})
+  unset (_${_PYTHON_PREFIX}_CMAKE_FIND_FRAMEWORK)
+else()
+  unset (CMAKE_FIND_FRAMEWORK)
+endif()
+
+unset (_${_PYTHON_PREFIX}_CONFIG CACHE)

+ 146 - 0
Modules/FindPython2.cmake

@@ -0,0 +1,146 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindPython2
+-----------
+
+Find Python 2 interpreter, compiler and development environment (include
+directories and libraries).
+
+Three components are supported:
+
+* ``Interpreter``: search for Python 2 interpreter
+* ``Compiler``: search for Python 2 compiler. Only offered by IronPython.
+* ``Development``: search for development artifacts (include directories and
+  libraries)
+
+If no ``COMPONENTS`` is specified, ``Interpreter`` is assumed.
+
+To ensure consistent versions between components ``Interpreter``, ``Compiler``
+and ``Development``, specify all components at the same time::
+
+  find_package (Python2 COMPONENTS Interpreter Development)
+
+This module looks only for version 2 of Python. This module can be used
+concurrently with :module:`FindPython3` module to use both Python versions.
+
+The :module:`FindPython` module can be used if Python version does not matter
+for you.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module defines the following :ref:`Imported Targets <Imported Targets>`:
+
+``Python2::Interpreter``
+  Python 2 interpreter. Target defined if component ``Interpreter`` is found.
+``Python2::Compiler``
+  Python 2 compiler. Target defined if component ``Compiler`` is found.
+``Python2::Python``
+  Python 2 library. Target defined if component ``Development`` is found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module will set the following variables in your project
+(see :ref:`Standard Variable Names <CMake Developer Standard Variable Names>`):
+
+``Python2_FOUND``
+  System has the Python 2 requested components.
+``Python2_Interpreter_FOUND``
+  System has the Python 2 interpreter.
+``Python2_EXECUTABLE``
+  Path to the Python 2 interpreter.
+``Python2_INTERPRETER_ID``
+  A short string unique to the interpreter. Possible values include:
+    * Python
+    * ActivePython
+    * Anaconda
+    * Canopy
+    * IronPython
+``Python2_STDLIB``
+  Standard platform independent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=True)``.
+``Python2_STDARCH``
+  Standard platform dependent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=True)``.
+``Python2_SITELIB``
+  Third-party platform independent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False)``.
+``Python2_SITEARCH``
+  Third-party platform dependent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``.
+``Python2_Compiler_FOUND``
+  System has the Python 2 compiler.
+``Python2_COMPILER``
+  Path to the Python 2 compiler. Only offered by IronPython.
+``Python2_COMPILER_ID``
+  A short string unique to the compiler. Possible values include:
+    * IronPython
+``Python2_Development_FOUND``
+  System has the Python 2 development artifacts.
+``Python2_INCLUDE_DIRS``
+  The Python 2 include directories.
+``Python2_LIBRARIES``
+  The Python 2 libraries.
+``Python2_LIBRARY_DIRS``
+  The Python 2 library directories.
+``Python2_RUNTIME_LIBRARY_DIRS``
+  The Python 2 runtime library directories.
+``Python2_VERSION``
+  Python 2 version.
+``Python2_VERSION_MAJOR``
+  Python 2 major version.
+``Python2_VERSION_MINOR``
+  Python 2 minor version.
+``Python2_VERSION_PATCH``
+  Python 2 patch version.
+
+Hints
+^^^^^
+
+``Python2_ROOT_DIR``
+  Define the root directory of a Python 2 installation.
+
+``Python2_USE_STATIC_LIBS``
+  * If not defined, search for shared libraries and static libraries in that
+    order.
+  * If set to TRUE, search **only** for static libraries.
+  * If set to FALSE, search **only** for shared libraries.
+
+Commands
+^^^^^^^^
+
+This module defines the command ``Python2_add_library`` which have the same
+semantic as :command:`add_library` but take care of Python module naming rules
+(only applied if library is of type ``MODULE``) and add dependency to target
+``Python2::Python``::
+
+  Python2_add_library (my_module MODULE src1.cpp)
+
+If library type is not specified, ``MODULE`` is assumed.
+#]=======================================================================]
+
+
+set (_PYTHON_PREFIX Python2)
+
+set (_Python2_REQUIRED_VERSION_MAJOR 2)
+
+include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake)
+
+if (COMMAND __Python2_add_library)
+  macro (Python2_add_library)
+    __Python2_add_library (Python2 ${ARGV})
+  endmacro()
+endif()
+
+unset (_PYTHON_PREFIX)

+ 146 - 0
Modules/FindPython3.cmake

@@ -0,0 +1,146 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#[=======================================================================[.rst:
+FindPython3
+-----------
+
+Find Python 3 interpreter, compiler and development environment (include
+directories and libraries).
+
+Three components are supported:
+
+* ``Interpreter``: search for Python 3 interpreter
+* ``Compiler``: search for Python 3 compiler. Only offered by IronPython.
+* ``Development``: search for development artifacts (include directories and
+  libraries)
+
+If no ``COMPONENTS`` is specified, ``Interpreter`` is assumed.
+
+To ensure consistent versions between components ``Interpreter``, ``Compiler``
+and ``Development``, specify all components at the same time::
+
+  find_package (Python3 COMPONENTS Interpreter Development)
+
+This module looks only for version 3 of Python. This module can be used
+concurrently with :module:`FindPython2` module to use both Python versions.
+
+The :module:`FindPython` module can be used if Python version does not matter
+for you.
+
+Imported Targets
+^^^^^^^^^^^^^^^^
+
+This module defines the following :ref:`Imported Targets <Imported Targets>`:
+
+``Python3::Interpreter``
+  Python 3 interpreter. Target defined if component ``Interpreter`` is found.
+``Python3::Compiler``
+  Python 3 compiler. Target defined if component ``Compiler`` is found.
+``Python3::Python``
+  Python 3 library. Target defined if component ``Development`` is found.
+
+Result Variables
+^^^^^^^^^^^^^^^^
+
+This module will set the following variables in your project
+(see :ref:`Standard Variable Names <CMake Developer Standard Variable Names>`):
+
+``Python3_FOUND``
+  System has the Python 3 requested components.
+``Python3_Interpreter_FOUND``
+  System has the Python 3 interpreter.
+``Python3_EXECUTABLE``
+  Path to the Python 3 interpreter.
+``Python3_INTERPRETER_ID``
+  A short string unique to the interpreter. Possible values include:
+    * Python
+    * ActivePython
+    * Anaconda
+    * Canopy
+    * IronPython
+``Python3_STDLIB``
+  Standard platform independent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=True)``.
+``Python3_STDARCH``
+  Standard platform dependent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=True)``.
+``Python3_SITELIB``
+  Third-party platform independent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False)``.
+``Python3_SITEARCH``
+  Third-party platform dependent installation directory.
+
+  Information returned by
+  ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``.
+``Python3_Compiler_FOUND``
+  System has the Python 3 compiler.
+``Python3_COMPILER``
+  Path to the Python 3 compiler. Only offered by IronPython.
+``Python3_COMPILER_ID``
+  A short string unique to the compiler. Possible values include:
+    * IronPython
+``Python3_Development_FOUND``
+  System has the Python 3 development artifacts.
+``Python3_INCLUDE_DIRS``
+  The Python 3 include directories.
+``Python3_LIBRARIES``
+  The Python 3 libraries.
+``Python3_LIBRARY_DIRS``
+  The Python 3 library directories.
+``Python3_RUNTIME_LIBRARY_DIRS``
+  The Python 3 runtime library directories.
+``Python3_VERSION``
+  Python 3 version.
+``Python3_VERSION_MAJOR``
+  Python 3 major version.
+``Python3_VERSION_MINOR``
+  Python 3 minor version.
+``Python3_VERSION_PATCH``
+  Python 3 patch version.
+
+Hints
+^^^^^
+
+``Python3_ROOT_DIR``
+  Define the root directory of a Python 3 installation.
+
+``Python3_USE_STATIC_LIBS``
+  * If not defined, search for shared libraries and static libraries in that
+    order.
+  * If set to TRUE, search **only** for static libraries.
+  * If set to FALSE, search **only** for shared libraries.
+
+Commands
+^^^^^^^^
+
+This module defines the command ``Python3_add_library`` which have the same
+semantic as :command:`add_library` but take care of Python module naming rules
+(only applied if library is of type ``MODULE``) and add dependency to target
+``Python3::Python``::
+
+  Python3_add_library (my_module MODULE src1.cpp)
+
+If library type is not specified, ``MODULE`` is assumed.
+#]=======================================================================]
+
+
+set (_PYTHON_PREFIX Python3)
+
+set (_Python3_REQUIRED_VERSION_MAJOR 3)
+
+include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake)
+
+if (COMMAND __Python3_add_library)
+  macro (Python3_add_library)
+    __Python3_add_library (Python3 ${ARGV})
+  endmacro()
+endif()
+
+unset (_PYTHON_PREFIX)

+ 4 - 0
Modules/FindPythonInterp.cmake

@@ -7,6 +7,10 @@
 #
 # Find python interpreter
 #
+# .. deprecated:: 3.12
+#
+#   Use :module:`FindPython3`, :module:`FindPython2` or :module:`FindPython` instead.
+#
 # This module finds if Python interpreter is installed and determines
 # where the executables are.  This code sets the following variables:
 #

+ 4 - 0
Modules/FindPythonLibs.cmake

@@ -7,6 +7,10 @@
 #
 # Find python libraries
 #
+# .. deprecated:: 3.12
+#
+#   Use :module:`FindPython3`, :module:`FindPython2` or :module:`FindPython` instead.
+#
 # This module finds if Python is installed and determines where the
 # include files and libraries are.  It also determines what the name of
 # the library is.  This code sets the following variables:

+ 4 - 0
Tests/CMakeLists.txt

@@ -1427,6 +1427,10 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
     add_subdirectory(FindXercesC)
   endif()
 
+  if(CMake_TEST_FindPython)
+    add_subdirectory(FindPython)
+  endif()
+
   add_subdirectory(FindThreads)
 
   # Matlab module

+ 69 - 0
Tests/FindPython/CMakeLists.txt

@@ -0,0 +1,69 @@
+add_test(NAME FindPython.Python2 COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindPython/Python2"
+  "${CMake_BINARY_DIR}/Tests/FindPython/Python2"
+  ${build_generator_args}
+  --build-project TestPython2
+  --build-options ${build_options}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
+
+add_test(NAME FindPython.Python2Fail COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindPython/Python2Fail"
+  "${CMake_BINARY_DIR}/Tests/FindPython/Python2Fail"
+  ${build_generator_args}
+  --build-project TestPython2Fail
+  --build-options ${build_options}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
+set_tests_properties(FindPython.Python2Fail PROPERTIES
+  PASS_REGULAR_EXPRESSION "Could NOT find Python2 \\(missing: foobar\\)")
+
+add_test(NAME FindPython.Python3 COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindPython/Python3"
+  "${CMake_BINARY_DIR}/Tests/FindPython/Python3"
+  ${build_generator_args}
+  --build-project TestPython3
+  --build-options ${build_options}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
+
+add_test(NAME FindPython.Python3Fail COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindPython/Python3Fail"
+  "${CMake_BINARY_DIR}/Tests/FindPython/Python3Fail"
+  ${build_generator_args}
+  --build-project TestPython3Fail
+  --build-options ${build_options}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
+set_tests_properties(FindPython.Python3Fail PROPERTIES
+  PASS_REGULAR_EXPRESSION "Could NOT find Python3 \\(missing: foobar\\)")
+
+add_test(NAME FindPython.Python COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindPython/Python"
+  "${CMake_BINARY_DIR}/Tests/FindPython/Python"
+  ${build_generator_args}
+  --build-project TestPython
+  --build-options ${build_options}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
+
+add_test(NAME FindPython.MultiplePackages COMMAND
+  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+  --build-and-test
+  "${CMake_SOURCE_DIR}/Tests/FindPython/MultiplePackages"
+  "${CMake_BINARY_DIR}/Tests/FindPython/MultiplePackages"
+  ${build_generator_args}
+  --build-project TestMultiplePackages
+  --build-options ${build_options}
+  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )

+ 33 - 0
Tests/FindPython/MultiplePackages/CMakeLists.txt

@@ -0,0 +1,33 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(TestMultiplePackages C)
+
+find_package (Python2 REQUIRED COMPONENTS Interpreter Development)
+find_package (Python3 REQUIRED COMPONENTS Interpreter Development)
+
+# Must find Python 3
+find_package (Python REQUIRED)
+
+if (NOT Python3_EXECUTABLE STREQUAL Python_EXECUTABLE)
+  message (FATAL_ERROR
+    "Python interpreters do not match:\n"
+    "  Python_EXECUTABLE='${Python_EXECUTABLE}'\n"
+    "  Python3_EXECUTABLE='${Python3_EXECUTABLE}'\n"
+    )
+endif()
+
+
+Python2_add_library (spam2 MODULE ../spam.c)
+target_compile_definitions (spam2 PRIVATE PYTHON2)
+
+Python3_add_library (spam3 MODULE ../spam.c)
+target_compile_definitions (spam3 PRIVATE PYTHON3)
+
+
+add_test (NAME python2_spam2
+          COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam3>"
+          "${Python2_EXECUTABLE}" -c "import spam2; spam2.system(\"cd\")")
+
+add_test (NAME python3_spam3
+          COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam3>"
+          "${Python3_EXECUTABLE}" -c "import spam3; spam3.system(\"cd\")")

+ 17 - 0
Tests/FindPython/Python/CMakeLists.txt

@@ -0,0 +1,17 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython C)
+
+include(CTest)
+
+find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
+if (NOT Python_FOUND)
+  message (FATAL_ERROR "Fail to found Python 3")
+endif()
+
+Python_add_library (spam3 MODULE ../spam.c)
+target_compile_definitions (spam3 PRIVATE PYTHON3)
+
+add_test (NAME python_spam3
+          COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam3>"
+          "${Python_EXECUTABLE}" -c "import spam3; spam3.system(\"cd\")")

+ 22 - 0
Tests/FindPython/Python2/CMakeLists.txt

@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython2 C)
+
+include(CTest)
+
+find_package(Python2 3 QUIET)
+if (Python2_FOUND)
+  message (FATAL_ERROR "Wrong python version found: ${Python2_VERSION}")
+endif()
+
+find_package(Python2 REQUIRED COMPONENTS Interpreter Development)
+if (NOT Python2_FOUND)
+  message (FATAL_ERROR "Fail to found Python 2")
+endif()
+
+Python2_add_library (spam2 MODULE ../spam.c)
+target_compile_definitions (spam2 PRIVATE PYTHON2)
+
+add_test (NAME python2_spam2
+          COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam2>"
+          "${Python2_EXECUTABLE}" -c "import spam2; spam2.system(\"cd\")")

+ 14 - 0
Tests/FindPython/Python2Fail/CMakeLists.txt

@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython2Fail C)
+
+include(CTest)
+
+find_package(Python2 REQUIRED COMPONENTS Interpreter Development foobar)
+
+Python2_add_library (spam2 MODULE ../spam.c)
+target_compile_definitions (spam2 PRIVATE PYTHON2)
+
+add_test (NAME python2_spam2
+          COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam2>"
+          "${Python2_EXECUTABLE}" -c "import spam2; spam2.system(\"cd\")")

+ 22 - 0
Tests/FindPython/Python3/CMakeLists.txt

@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython3 C)
+
+include(CTest)
+
+find_package(Python3 2 QUIET)
+if (Python3_FOUND)
+  message (FATAL_ERROR "Wrong python version found: ${Python3_VERSION}")
+endif()
+
+find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
+if (NOT Python3_FOUND)
+  message (FATAL_ERROR "Fail to found Python 3")
+endif()
+
+Python3_add_library (spam3 MODULE ../spam.c)
+target_compile_definitions (spam3 PRIVATE PYTHON3)
+
+add_test (NAME python3_spam3
+          COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam3>"
+          "${Python3_EXECUTABLE}" -c "import spam3; spam3.system(\"cd\")")

+ 14 - 0
Tests/FindPython/Python3Fail/CMakeLists.txt

@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(TestPython3Fail C)
+
+include(CTest)
+
+find_package(Python3 REQUIRED COMPONENTS Interpreter Development foobar)
+
+Python3_add_library (spam3 MODULE ../spam.c)
+target_compile_definitions (spam3 PRIVATE PYTHON3)
+
+add_test (NAME python3_spam3
+          COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:spam3>"
+          "${Python3_EXECUTABLE}" -c "import spam3; spam3.system(\"cd\")")

+ 41 - 0
Tests/FindPython/spam.c

@@ -0,0 +1,41 @@
+
+#include <Python.h>
+
+static PyObject* spam_system(PyObject* self, PyObject* args)
+{
+  const char* command;
+  int sts;
+
+  if (!PyArg_ParseTuple(args, "s", &command))
+    return NULL;
+  sts = system(command);
+  /* return PyLong_FromLong(sts); */
+  return Py_BuildValue("i", sts);
+}
+
+static PyMethodDef SpamMethods[] = {
+  { "system", spam_system, METH_VARARGS, "Execute a shell command." },
+  { NULL, NULL, 0, NULL } /* Sentinel */
+};
+
+#if defined(PYTHON2)
+PyMODINIT_FUNC initspam2(void)
+{
+  (void)Py_InitModule("spam2", SpamMethods);
+}
+#endif
+
+#if defined(PYTHON3)
+static struct PyModuleDef spammodule = {
+  PyModuleDef_HEAD_INIT, "spam3", /* name of module */
+  NULL,                           /* module documentation, may be NULL */
+  -1, /* size of per-interpreter state of the module,
+         or -1 if the module keeps state in global variables. */
+  SpamMethods
+};
+
+PyMODINIT_FUNC PyInit_spam3(void)
+{
+  return PyModule_Create(&spammodule);
+}
+#endif

+ 1 - 1
Tests/RunCMake/UseSWIG/CMakeLists.txt

@@ -1,3 +1,3 @@
-cmake_minimum_required(VERSION 2.8.4)
+cmake_minimum_required(VERSION 3.1)
 project(${RunCMake_TEST} CXX)
 include(${RunCMake_TEST}.cmake)

+ 26 - 0
Tests/RunCMake/UseSWIG/MultiplePython.cmake

@@ -0,0 +1,26 @@
+
+find_package(SWIG REQUIRED)
+include(${SWIG_USE_FILE})
+
+find_package(Python2 REQUIRED COMPONENTS Development)
+find_package(Python3 REQUIRED COMPONENTS Development)
+
+unset(CMAKE_SWIG_FLAGS)
+
+set (CMAKE_INCLUDE_CURRENT_DIR ON)
+
+set_property(SOURCE example.i PROPERTY CPLUSPLUS ON)
+set_property(SOURCE example.i PROPERTY COMPILE_OPTIONS -includeall)
+
+swig_add_library(example1
+                 LANGUAGE python
+                 OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/Python2"
+                 SOURCES example.i example.cxx)
+target_link_libraries(example1 PRIVATE Python2::Python)
+
+# re-use sample interface file for another plugin
+swig_add_library(example2
+                 LANGUAGE python
+                 OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}/Python3"
+                 SOURCES example.i example.cxx)
+target_link_libraries(example2 PRIVATE Python3::Python)

+ 5 - 1
Tests/RunCMake/UseSWIG/RunCMakeTest.cmake

@@ -10,8 +10,11 @@ function(run_SWIG test)
   set(RunCMake_TEST_NO_CLEAN 1)
   file(REMOVE_RECURSE "${RunCMake_TEST_BINARY_DIR}")
   file(MAKE_DIRECTORY "${RunCMake_TEST_BINARY_DIR}")
+  if (NOT RunCMake_GENERATOR_IS_MULTI_CONFIG)
+    set (RunCMake_TEST_OPTIONS -DCMAKE_BUILD_TYPE=Release)
+  endif()
   run_cmake(${test})
-  run_cmake_command(${test}-test ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} ${_SWIG_TEST_TARGET})
+  run_cmake_command(${test}-test ${CMAKE_COMMAND} --build ${RunCMake_TEST_BINARY_DIR} --config Release ${_SWIG_TEST_TARGET})
 endfunction()
 
 run_SWIG(LegacyPython TARGET RunTest)
@@ -21,3 +24,4 @@ run_SWIG(BasicPython TARGET RunTest)
 run_SWIG(BasicPerl TARGET RunTest)
 
 run_SWIG(MultipleModules)
+run_SWIG(MultiplePython)