From 06d9e67fbd2b2dfc9cba12327866b2f73eab8a18 Mon Sep 17 00:00:00 2001 From: Marc Chevrier Date: Thu, 15 Aug 2019 09:19:43 +0200 Subject: FindPython: Add capability to specify directly artifacts Fixes: #19492 --- Help/release/dev/FindPython-specify_artifacts.rst | 5 + Modules/FindPython.cmake | 50 +++ Modules/FindPython/Support.cmake | 497 ++++++++++++--------- Modules/FindPython2.cmake | 38 ++ Modules/FindPython3.cmake | 38 ++ Tests/FindPython/CMakeLists.txt | 13 + Tests/FindPython/RequiredArtifacts/CMakeLists.txt | 110 +++++ .../RequiredArtifacts/Check/CMakeLists.txt | 41 ++ 8 files changed, 587 insertions(+), 205 deletions(-) create mode 100644 Help/release/dev/FindPython-specify_artifacts.rst create mode 100644 Tests/FindPython/RequiredArtifacts/CMakeLists.txt create mode 100644 Tests/FindPython/RequiredArtifacts/Check/CMakeLists.txt diff --git a/Help/release/dev/FindPython-specify_artifacts.rst b/Help/release/dev/FindPython-specify_artifacts.rst new file mode 100644 index 0000000..7032f8b --- /dev/null +++ b/Help/release/dev/FindPython-specify_artifacts.rst @@ -0,0 +1,5 @@ +FindPython-specify_artifacts +---------------------------- + +* Modules :module:`FindPython3`, :module:`FindPython2` and :module:`FindPython` + gain the capability to specify directly artifacts. diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake index 2056e93..3cc08a1 100644 --- a/Modules/FindPython.cmake +++ b/Modules/FindPython.cmake @@ -243,6 +243,44 @@ Hints recommended to also include the component ``Interpreter`` to get expected result. +Artifacts Specification +^^^^^^^^^^^^^^^^^^^^^^^ + +To solve special cases, it is possible to specify directly the artifacts by +setting the following variables: + +``Python_EXECUTABLE`` + The path to the interpreter. + +``Python_COMPILER`` + The path to the compiler. + +``Python_LIBRARY`` + The path to the library. It will be used to compute the + variables ``Python_LIBRARIES``, ``Python_LIBRAY_DIRS`` and + ``Python_RUNTIME_LIBRARY_DIRS``. + +``Python_INCLUDE_DIR`` + The path to the directory of the ``Python`` headers. It will be used to + compute the variable ``Python_INCLUDE_DIRS``. + +``Python_NumPy_INCLUDE_DIR`` + The path to the directory of the ``NumPy`` headers. It will be used to + compute the variable ``Python_NumPy_INCLUDE_DIRS``. + +.. note:: + + All paths must be absolute. Any artifact specified with a relative path + will be ignored. + +.. note:: + + When an artifact is specified, all ``HINTS`` will be ignored and no search + will be performed for this artifact. + + If more than one artifact is specified, it is the user's responsability to + ensure the consistency of the various artifacts. + Commands ^^^^^^^^ @@ -275,6 +313,14 @@ else() set (_Python_REQUIRED_VERSIONS 3 2) set (_Python_REQUIRED_VERSION_LAST 2) + unset (_Python_INPUT_VARS) + foreach (_Python_ITEM IN ITEMS Python_EXECUTABLE Python_COMPILER Python_LIBRARY + Python_INCLUDE_DIR Python_NumPy_INCLUDE_DIR) + if (NOT DEFINED ${_Python_ITEM}) + list (APPEND _Python_INPUT_VARS ${_Python_ITEM}) + endif() + endforeach() + foreach (_Python_REQUIRED_VERSION_MAJOR IN LISTS _Python_REQUIRED_VERSIONS) set (Python_FIND_VERSION ${_Python_REQUIRED_VERSION_MAJOR}) include (${CMAKE_CURRENT_LIST_DIR}/FindPython/Support.cmake) @@ -282,6 +328,10 @@ else() _Python_REQUIRED_VERSION_MAJOR EQUAL _Python_REQUIRED_VERSION_LAST) break() endif() + # clean-up INPUT variables not set by the user + foreach (_Python_ITEM IN LISTS _Python_INPUT_VARS) + unset (${_Python_ITEM}) + endforeach() # clean-up some CACHE variables to ensure look-up restart from scratch foreach (_Python_ITEM IN LISTS _Python_CACHED_VARS) unset (${_Python_ITEM} CACHE) diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index efaf9ea..b67d563 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -268,9 +268,9 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) endif() endif() - if (${_PYTHON_PREFIX}_EXECUTABLE AND NOT CMAKE_CROSSCOMPILING) + if (_${_PYTHON_PREFIX}_EXECUTABLE AND NOT CMAKE_CROSSCOMPILING) if (NAME STREQUAL "PREFIX") - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(';'.join([sysconfig.PREFIX,sysconfig.EXEC_PREFIX,sysconfig.BASE_EXEC_PREFIX]))" + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(';'.join([sysconfig.PREFIX,sysconfig.EXEC_PREFIX,sysconfig.BASE_EXEC_PREFIX]))" RESULT_VARIABLE _result OUTPUT_VARIABLE _values ERROR_QUIET @@ -281,7 +281,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) list (REMOVE_DUPLICATES _values) endif() elseif (NAME STREQUAL "INCLUDES") - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(';'.join([sysconfig.get_python_inc(plat_specific=True),sysconfig.get_python_inc(plat_specific=False)]))" + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(';'.join([sysconfig.get_python_inc(plat_specific=True),sysconfig.get_python_inc(plat_specific=False)]))" RESULT_VARIABLE _result OUTPUT_VARIABLE _values ERROR_QUIET @@ -294,7 +294,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) if (NAME STREQUAL "CONFIGDIR") set (config_flag "LIBPL") endif() - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_config_var('${config_flag}'))" + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; from distutils import sysconfig; sys.stdout.write(sysconfig.get_config_var('${config_flag}'))" RESULT_VARIABLE _result OUTPUT_VARIABLE _values ERROR_QUIET @@ -336,14 +336,14 @@ function (_PYTHON_GET_VERSION) if (_PGV_LIBRARY) # retrieve version and abi from library name - if (${_PYTHON_PREFIX}_LIBRARY_RELEASE) + if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE) # extract version from library name - if (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "python([23])([0-9]+)") + if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "python([23])([0-9]+)") set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE) set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE) set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE) set (${_PGV_PREFIX}ABI "" PARENT_SCOPE) - elseif (${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "python([23])\\.([0-9]+)([dmu]*)") + elseif (_${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "python([23])\\.([0-9]+)([dmu]*)") set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE) set (${_PGV_PREFIX}VERSION_MINOR "${CMAKE_MATCH_2}" PARENT_SCOPE) set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}.${CMAKE_MATCH_2}" PARENT_SCOPE) @@ -351,9 +351,9 @@ function (_PYTHON_GET_VERSION) endif() endif() else() - if (${_PYTHON_PREFIX}_INCLUDE_DIR) + if (_${_PYTHON_PREFIX}_INCLUDE_DIR) # retrieve version from header file - file (STRINGS "${${_PYTHON_PREFIX}_INCLUDE_DIR}/patchlevel.h" version + file (STRINGS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}/patchlevel.h" version REGEX "^#define[ \t]+PY_VERSION[ \t]+\"[^\"]+\"") string (REGEX REPLACE "^#define[ \t]+PY_VERSION[ \t]+\"([^\"]+)\".*" "\\1" version "${version}") @@ -369,7 +369,7 @@ function (_PYTHON_GET_VERSION) # compute ABI flags if (version_major VERSION_GREATER 2) - file (STRINGS "${${_PYTHON_PREFIX}_INCLUDE_DIR}/pyconfig.h" config REGEX "(Py_DEBUG|WITH_PYMALLOC|Py_UNICODE_SIZE|MS_WIN32)") + file (STRINGS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}/pyconfig.h" config REGEX "(Py_DEBUG|WITH_PYMALLOC|Py_UNICODE_SIZE|MS_WIN32)") set (abi) if (config MATCHES "#[ ]*define[ ]+MS_WIN32") # ABI not used on Windows @@ -396,20 +396,26 @@ endfunction() function (_PYTHON_VALIDATE_INTERPRETER) - if (NOT ${_PYTHON_PREFIX}_EXECUTABLE) + if (NOT _${_PYTHON_PREFIX}_EXECUTABLE) return() endif() - cmake_parse_arguments (PARSE_ARGV 0 _PVI "EXACT" "" "") + cmake_parse_arguments (PARSE_ARGV 0 _PVI "EXACT;CHECK_EXISTS" "" "") if (_PVI_UNPARSED_ARGUMENTS) set (expected_version ${_PVI_UNPARSED_ARGUMENTS}) else() unset (expected_version) endif() + if (_PVI_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_EXECUTABLE}") + # interpreter does not exist anymore + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "_${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + return() + endif() + # validate ABI compatibility if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI) - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write(sys.abiflags)" RESULT_VARIABLE result OUTPUT_VARIABLE abi @@ -421,16 +427,16 @@ function (_PYTHON_VALIDATE_INTERPRETER) endif() if (NOT abi IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # incompatible ABI - set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "_${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() endif() - get_filename_component (python_name "${${_PYTHON_PREFIX}_EXECUTABLE}" NAME) + get_filename_component (python_name "${_${_PYTHON_PREFIX}_EXECUTABLE}" NAME) if (expected_version AND NOT python_name STREQUAL "python${expected_version}${abi}${CMAKE_EXECUTABLE_SUFFIX}") # executable found must have a specific version - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))" RESULT_VARIABLE result OUTPUT_VARIABLE version @@ -438,14 +444,14 @@ function (_PYTHON_VALIDATE_INTERPRETER) OUTPUT_STRIP_TRAILING_WHITESPACE) if (result OR (_PVI_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version)) # interpreter not usable or has wrong major version - set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "_${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() else() if (NOT python_name STREQUAL "python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}${CMAKE_EXECUTABLE_SUFFIX}") # executable found do not have version in name # ensure major version is OK - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write(str(sys.version_info[0]))" RESULT_VARIABLE result OUTPUT_VARIABLE version @@ -453,7 +459,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) OUTPUT_STRIP_TRAILING_WHITESPACE) if (result OR NOT version EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) # interpreter not usable or has wrong major version - set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "_${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() endif() @@ -462,7 +468,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) if (CMAKE_SIZEOF_VOID_P AND "Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND NOT CMAKE_CROSSCOMPILING) # In this case, interpreter must have same architecture as environment - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys, struct; sys.stdout.write(str(struct.calcsize(\"P\")))" RESULT_VARIABLE result OUTPUT_VARIABLE size @@ -470,7 +476,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) OUTPUT_STRIP_TRAILING_WHITESPACE) if (result OR NOT size EQUAL CMAKE_SIZEOF_VOID_P) # interpreter not usable or has wrong architecture - set_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "_${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") return() endif() endif() @@ -478,11 +484,11 @@ endfunction() function (_PYTHON_VALIDATE_COMPILER expected_version) - if (NOT ${_PYTHON_PREFIX}_COMPILER) + if (NOT _${_PYTHON_PREFIX}_COMPILER) return() endif() - cmake_parse_arguments (_PVC "EXACT" "" "" ${ARGN}) + cmake_parse_arguments (_PVC "EXACT;CHECK_EXISTS" "" "" ${ARGN}) if (_PVC_UNPARSED_ARGUMENTS) set (major_version FALSE) set (expected_version ${_PVC_UNPARSED_ARGUMENTS}) @@ -492,6 +498,12 @@ function (_PYTHON_VALIDATE_COMPILER expected_version) set (_PVC_EXACT TRUE) endif() + if (_PVC_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_COMPILER}") + # Compiler does not exist anymore + set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "_${_PYTHON_PREFIX}_COMPILER-NOTFOUND") + return() + endif() + # retrieve python environment version from compiler set (working_dir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir") if (major_version) @@ -500,7 +512,7 @@ function (_PYTHON_VALIDATE_COMPILER expected_version) else() file (WRITE "${working_dir}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:2]]))\n") endif() - execute_process (COMMAND "${${_PYTHON_PREFIX}_COMPILER}" /target:exe /embed "${working_dir}/version.py" + execute_process (COMMAND "${_${_PYTHON_PREFIX}_COMPILER}" /target:exe /embed "${working_dir}/version.py" WORKING_DIRECTORY "${working_dir}" OUTPUT_QUIET ERROR_QUIET @@ -514,78 +526,96 @@ function (_PYTHON_VALIDATE_COMPILER expected_version) if (result OR (_PVC_EXACT AND NOT version VERSION_EQUAL expected_version) OR (version VERSION_LESS expected_version)) # Compiler not usable or has wrong version - set_property (CACHE ${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") + set_property (CACHE _${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "_${_PYTHON_PREFIX}_COMPILER-NOTFOUND") endif() endfunction() function (_PYTHON_VALIDATE_LIBRARY) - if (NOT ${_PYTHON_PREFIX}_LIBRARY_RELEASE) + if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) return() endif() - cmake_parse_arguments (PARSE_ARGV 0 _PVL "EXACT" "" "") + cmake_parse_arguments (PARSE_ARGV 0 _PVL "EXACT;CHECK_EXISTS" "" "") if (_PVL_UNPARSED_ARGUMENTS) set (expected_version ${_PVL_UNPARSED_ARGUMENTS}) else() unset (expected_version) endif() + if (_PVL_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}") + # library does not exist anymore + set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") + if (WIN32) + set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND") + endif() + set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") + return() + endif() + # retrieve version and abi from library name _python_get_version (LIBRARY PREFIX lib_) if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT lib_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # incompatible ABI - set_property (CACHE ${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") + set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") else() if (expected_version) if ((_PVL_EXACT AND NOT lib_VERSION VERSION_EQUAL expected_version) OR (lib_VERSION VERSION_LESS expected_version)) # library has wrong version - set_property (CACHE ${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") + set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") endif() else() if (NOT lib_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) # library has wrong major version - set_property (CACHE ${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") + set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") endif() endif() endif() - if (NOT ${_PYTHON_PREFIX}_LIBRARY_RELEASE) - set_property (CACHE ${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND") - set_property (CACHE ${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") + if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) + if (WIN32) + set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_DEBUG PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND") + endif() + set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") endif() endfunction() function (_PYTHON_VALIDATE_INCLUDE_DIR) - if (NOT ${_PYTHON_PREFIX}_INCLUDE_DIR) + if (NOT _${_PYTHON_PREFIX}_INCLUDE_DIR) return() endif() - cmake_parse_arguments (PARSE_ARGV 0 _PVID "EXACT" "" "") + cmake_parse_arguments (PARSE_ARGV 0 _PVID "EXACT;CHECK_EXISTS" "" "") if (_PVID_UNPARSED_ARGUMENTS) set (expected_version ${_PVID_UNPARSED_ARGUMENTS}) else() unset (expected_version) endif() + if (_PVID_CHECK_EXISTS AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") + # include file does not exist anymore + set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") + return() + endif() + # retrieve version from header file _python_get_version (INCLUDE PREFIX inc_) if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT inc_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # incompatible ABI - set_property (CACHE ${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") + set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") else() if (expected_version) if ((_PVID_EXACT AND NOT inc_VERSION VERSION_EQUAL expected_version) OR (inc_VERSION VERSION_LESS expected_version)) # include dir has wrong version - set_property (CACHE ${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") + set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") endif() else() if (NOT inc_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) # include dir has wrong major version - set_property (CACHE ${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") + set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") endif() endif() endif() @@ -610,8 +640,7 @@ endfunction() function (_PYTHON_SET_LIBRARY_DIRS _PYTHON_SLD_RESULT) unset (_PYTHON_DIRS) - set (_PYTHON_LIBS ${ARGV}) - list (REMOVE_AT _PYTHON_LIBS 0) + set (_PYTHON_LIBS ${ARGN}) foreach (_PYTHON_LIB IN LISTS _PYTHON_LIBS) if (${_PYTHON_LIB}) get_filename_component (_PYTHON_DIR "${${_PYTHON_LIB}}" DIRECTORY) @@ -811,28 +840,31 @@ unset (_${_PYTHON_PREFIX}_CACHED_VARS) # first step, search for the interpreter if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS ${_PYTHON_PREFIX}_EXECUTABLE) + list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_EXECUTABLE) if (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter) list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_EXECUTABLE) endif() - if (DEFINED ${_PYTHON_PREFIX}_EXECUTABLE) + if (DEFINED ${_PYTHON_PREFIX}_EXECUTABLE + AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_EXECUTABLE}") + set (_${_PYTHON_PREFIX}_EXECUTABLE "${${_PYTHON_PREFIX}_EXECUTABLE}" CACHE INTERNAL "") + elseif (DEFINED _${_PYTHON_PREFIX}_EXECUTABLE) # compute interpreter signature and check validity of definition - string (MD5 __${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${${_PYTHON_PREFIX}_EXECUTABLE}") + string (MD5 __${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_EXECUTABLE}") if (__${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE) # check version validity if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT) - _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT) + _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT CHECK_EXISTS) else() - _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) + _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION} CHECK_EXISTS) endif() else() - unset (${_PYTHON_PREFIX}_EXECUTABLE CACHE) + unset (_${_PYTHON_PREFIX}_EXECUTABLE CACHE) unset (_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE CACHE) endif() endif() - if (NOT ${_PYTHON_PREFIX}_EXECUTABLE) + if (NOT _${_PYTHON_PREFIX}_EXECUTABLE) set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) if (_${_PYTHON_PREFIX}_FIND_STRATEGY STREQUAL "LOCATION") @@ -859,7 +891,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) while (TRUE) # Virtual environments handling if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} @@ -871,7 +903,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_CMAKE_SYSTEM_PATH) _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() if (NOT _${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY") @@ -881,7 +913,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # Apple frameworks handling if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} @@ -892,13 +924,13 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() endif() # Windows registry if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} NAMES_PER_DIR @@ -908,13 +940,13 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() endif() # try using HINTS - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} NAMES_PER_DIR @@ -923,36 +955,36 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() # try using standard paths - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} NAMES_PER_DIR PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}) _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() # Apple frameworks handling if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} NAMES_PER_DIR PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} PATH_SUFFIXES bin NO_DEFAULT_PATH) _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() endif() # Windows registry if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} NAMES_PER_DIR @@ -960,7 +992,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) PATH_SUFFIXES bin ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} NO_DEFAULT_PATH) _python_validate_interpreter (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() endif() @@ -979,7 +1011,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # Virtual environments handling if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV MATCHES "^(FIRST|ONLY)$") - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} @@ -990,7 +1022,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() if (_${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY") @@ -1000,7 +1032,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # Apple frameworks handling if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} @@ -1014,7 +1046,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # Windows registry if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} NAMES_PER_DIR @@ -1027,12 +1059,12 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endif() _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() # try using HINTS - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} NAMES_PER_DIR @@ -1041,7 +1073,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() # try using standard paths. @@ -1051,22 +1083,22 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # for version 3.*. So looking for names per dir will find, potentially, # systematically 'python' (i.e. version 2) even if version 3 is searched. if (CMAKE_HOST_WIN32) - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} python ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}) else() - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES}) endif() _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() # Apple frameworks handling if (CMAKE_HOST_APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "LAST") - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} NAMES_PER_DIR PATHS ${_${_PYTHON_PREFIX}_FRAMEWORK_PATHS} @@ -1076,7 +1108,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # Windows registry if (CMAKE_HOST_WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES ${_${_PYTHON_PREFIX}_NAMES} ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES} NAMES_PER_DIR @@ -1087,12 +1119,12 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endif() _python_validate_interpreter (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (${_PYTHON_PREFIX}_EXECUTABLE) + if (_${_PYTHON_PREFIX}_EXECUTABLE) break() endif() endforeach() - if (NOT ${_PYTHON_PREFIX}_EXECUTABLE AND + if (NOT _${_PYTHON_PREFIX}_EXECUTABLE AND NOT _${_PYTHON_PREFIX}_FIND_VIRTUALENV STREQUAL "ONLY") # No specific version found. Retry with generic names and standard paths. # NAMES_PER_DIR is not defined on purpose to have a chance to find @@ -1100,7 +1132,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # For example, typical systems have 'python' for version 2.* and 'python3' # for version 3.*. So looking for names per dir will find, potentially, # systematically 'python' (i.e. version 2) even if version 3 is searched. - find_program (${_PYTHON_PREFIX}_EXECUTABLE + find_program (_${_PYTHON_PREFIX}_EXECUTABLE NAMES python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python ${_${_PYTHON_PREFIX}_IRON_PYTHON_NAMES}) @@ -1109,32 +1141,35 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endif() endif() + set (${_PYTHON_PREFIX}_EXECUTABLE "${_${_PYTHON_PREFIX}_EXECUTABLE}") + # retrieve exact version of executable found - if (${_PYTHON_PREFIX}_EXECUTABLE) - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c + 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) + set (_${_PYTHON_PREFIX}_EXECUTABLE_USABLE TRUE) 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_property (CACHE ${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + set (_${_PYTHON_PREFIX}_EXECUTABLE_USABLE FALSE) unset (${_PYTHON_PREFIX}_VERSION) endif() endif() - if (${_PYTHON_PREFIX}_EXECUTABLE + if (_${_PYTHON_PREFIX}_EXECUTABLE AND _${_PYTHON_PREFIX}_EXECUTABLE_USABLE AND ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR) set (${_PYTHON_PREFIX}_Interpreter_FOUND TRUE) # Use interpreter version and ABI for future searches to ensure consistency set (_${_PYTHON_PREFIX}_FIND_VERSIONS ${${_PYTHON_PREFIX}_VERSION_MAJOR}.${${_PYTHON_PREFIX}_VERSION_MINOR}) - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write(sys.abiflags)" + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write(sys.abiflags)" RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE _${_PYTHON_PREFIX}_ABIFLAGS ERROR_QUIET @@ -1147,12 +1182,12 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) if (${_PYTHON_PREFIX}_Interpreter_FOUND) # compute and save interpreter signature - string (MD5 __${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${${_PYTHON_PREFIX}_EXECUTABLE}") + string (MD5 __${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_EXECUTABLE}") set (_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE "${__${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}" CACHE INTERNAL "") if (NOT CMAKE_SIZEOF_VOID_P) # determine interpreter architecture - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.maxsize > 2**32)" + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.maxsize > 2**32)" RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE ${_PYTHON_PREFIX}_IS64BIT ERROR_VARIABLE ${_PYTHON_PREFIX}_IS64BIT) @@ -1168,7 +1203,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endif() # retrieve interpreter identity - execute_process (COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -V + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -V RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID ERROR_VARIABLE ${_PYTHON_PREFIX}_INTERPRETER_ID) @@ -1181,7 +1216,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) 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)" + execute_process (COMMAND "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; print(sys.copyright)" RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE ${_PYTHON_PREFIX}_COPYRIGHT ERROR_QUIET) @@ -1195,7 +1230,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) 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)]))" + 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 @@ -1216,35 +1251,38 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) unset (${_PYTHON_PREFIX}_INTERPRETER_ID) endif() - mark_as_advanced (${_PYTHON_PREFIX}_EXECUTABLE + mark_as_advanced (_${_PYTHON_PREFIX}_EXECUTABLE _${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE) endif() # second step, search for compiler (IronPython) if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) - list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS ${_PYTHON_PREFIX}_COMPILER) + list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_COMPILER) if (${_PYTHON_PREFIX}_FIND_REQUIRED_Compiler) list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_COMPILER) endif() - if (DEFINED ${_PYTHON_PREFIX}_COMPILER) + if (DEFINED ${_PYTHON_PREFIX}_COMPILER + AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_COMPILER}") + set (_${_PYTHON_PREFIX}_COMPILER "${${_PYTHON_PREFIX}_COMPILER}" CACHE INTERNAL "") + elseif (DEFINED _${_PYTHON_PREFIX}_COMPILER) # compute compiler signature and check validity of definition - string (MD5 __${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${${_PYTHON_PREFIX}_COMPILER}") + string (MD5 __${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_COMPILER}") if (__${_PYTHON_PREFIX}_COMPILER_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_COMPILER_SIGNATURE) # check version validity if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT) - _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT) + _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT CHECK_EXISTS) else() - _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION}) + _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION} CHECK_EXISTS) endif() else() - unset (${_PYTHON_PREFIX}_COMPILER CACHE) + unset (_${_PYTHON_PREFIX}_COMPILER CACHE) unset (_${_PYTHON_PREFIX}_COMPILER_SIGNATURE CACHE) endif() endif() - if (NOT ${_PYTHON_PREFIX}_COMPILER) + if (NOT _${_PYTHON_PREFIX}_COMPILER) # IronPython specific artifacts # If IronPython interpreter is found, use its path unset (_${_PYTHON_PREFIX}_IRON_ROOT) @@ -1263,7 +1301,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) while (TRUE) if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_program (${_PYTHON_PREFIX}_COMPILER + find_program (_${_PYTHON_PREFIX}_COMPILER NAMES ipyc HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} @@ -1271,24 +1309,24 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (${_PYTHON_PREFIX}_COMPILER) + if (_${_PYTHON_PREFIX}_COMPILER) break() endif() endif() - find_program (${_PYTHON_PREFIX}_COMPILER + find_program (_${_PYTHON_PREFIX}_COMPILER NAMES ipyc HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) _python_validate_compiler (${${_PYTHON_PREFIX}_FIND_VERSION}) - if (${_PYTHON_PREFIX}_COMPILER) + if (_${_PYTHON_PREFIX}_COMPILER) break() endif() if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") - find_program (${_PYTHON_PREFIX}_COMPILER + find_program (_${_PYTHON_PREFIX}_COMPILER NAMES ipyc PATHS ${_${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} @@ -1301,7 +1339,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # try using root dir and registry foreach (_${_PYTHON_PREFIX}_VERSION IN LISTS _${_PYTHON_PREFIX}_FIND_VERSIONS) if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_program (${_PYTHON_PREFIX}_COMPILER + 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] @@ -1309,48 +1347,50 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) _python_validate_compiler (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (${_PYTHON_PREFIX}_COMPILER) + if (_${_PYTHON_PREFIX}_COMPILER) break() endif() endif() - find_program (${_PYTHON_PREFIX}_COMPILER + find_program (_${_PYTHON_PREFIX}_COMPILER NAMES ipyc HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} NO_SYSTEM_ENVIRONMENT_PATH NO_CMAKE_SYSTEM_PATH) _python_validate_compiler (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (${_PYTHON_PREFIX}_COMPILER) + if (_${_PYTHON_PREFIX}_COMPILER) break() endif() if (_${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "LAST") - find_program (${_PYTHON_PREFIX}_COMPILER + find_program (_${_PYTHON_PREFIX}_COMPILER NAMES ipyc PATHS [HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython\\${_${_PYTHON_PREFIX}_VERSION}\\InstallPath] PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES} NO_DEFAULT_PATH) _python_validate_compiler (${_${_PYTHON_PREFIX}_VERSION} EXACT) - if (${_PYTHON_PREFIX}_COMPILER) + if (_${_PYTHON_PREFIX}_COMPILER) break() endif() endif() endforeach() # no specific version found, re-try in standard paths - find_program (${_PYTHON_PREFIX}_COMPILER + find_program (_${_PYTHON_PREFIX}_COMPILER NAMES ipyc HINTS ${_${_PYTHON_PREFIX}_IRON_ROOT} ${_${_PYTHON_PREFIX}_HINTS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_IRON_PYTHON_PATH_SUFFIXES}) endif() endif() - if (${_PYTHON_PREFIX}_COMPILER) + set (${_PYTHON_PREFIX}_COMPILER "${_${_PYTHON_PREFIX}_COMPILER}") + + 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" + 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) @@ -1360,6 +1400,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) OUTPUT_VARIABLE _${_PYTHON_PREFIX}_VERSION ERROR_QUIET) if (NOT _${_PYTHON_PREFIX}_RESULT) + set (_${_PYTHON_PREFIX}_COMPILER_USABLE TRUE) 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) @@ -1374,12 +1415,12 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endif() else() # compiler not usable - set_property (CACHE ${_PYTHON_PREFIX}_COMPILER PROPERTY VALUE "${_PYTHON_PREFIX}_COMPILER-NOTFOUND") + set (_${_PYTHON_PREFIX}_COMPILER_USABLE FALSE) endif() file (REMOVE_RECURSE "${_${_PYTHON_PREFIX}_VERSION_DIR}") endif() - if (${_PYTHON_PREFIX}_COMPILER) + if (_${_PYTHON_PREFIX}_COMPILER AND _${_PYTHON_PREFIX}_COMPILER_USABLE) 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}) @@ -1394,7 +1435,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) if (${_PYTHON_PREFIX}_Compiler_FOUND) # compute and save compiler signature - string (MD5 __${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${${_PYTHON_PREFIX}_COMPILER}") + string (MD5 __${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_COMPILER}") set (_${_PYTHON_PREFIX}_COMPILER_SIGNATURE "${__${_PYTHON_PREFIX}_COMPILER_SIGNATURE}" CACHE INTERNAL "") set (${_PYTHON_PREFIX}_COMPILER_ID IronPython) @@ -1403,7 +1444,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) unset (${_PYTHON_PREFIX}_COMPILER_ID) endif() - mark_as_advanced (${_PYTHON_PREFIX}_COMPILER + mark_as_advanced (_${_PYTHON_PREFIX}_COMPILER _${_PYTHON_PREFIX}_COMPILER_SIGNATURE) endif() @@ -1412,36 +1453,51 @@ endif() ## Development environment is not compatible with IronPython interpreter if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND NOT ${_PYTHON_PREFIX}_INTERPRETER_ID STREQUAL "IronPython") - list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS ${_PYTHON_PREFIX}_LIBRARY - ${_PYTHON_PREFIX}_LIBRARY_RELEASE + list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_LIBRARY_RELEASE ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE - ${_PYTHON_PREFIX}_LIBRARY_DEBUG + _${_PYTHON_PREFIX}_LIBRARY_DEBUG ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG - ${_PYTHON_PREFIX}_INCLUDE_DIR) + _${_PYTHON_PREFIX}_INCLUDE_DIR) if (${_PYTHON_PREFIX}_FIND_REQUIRED_Development) - list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_LIBRARY - ${_PYTHON_PREFIX}_INCLUDE_DIR) + list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_LIBRARIES + ${_PYTHON_PREFIX}_INCLUDE_DIRS) endif() - if (DEFINED ${_PYTHON_PREFIX}_LIBRARY_RELEASE OR DEFINED ${_PYTHON_PREFIX}_INCLUDE_DIR) + if (DEFINED _${_PYTHON_PREFIX}_LIBRARY_RELEASE OR DEFINED _${_PYTHON_PREFIX}_INCLUDE_DIR) # compute development signature and check validity of definition - string (MD5 __${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${${_PYTHON_PREFIX}_LIBRARY_RELEASE}:${${_PYTHON_PREFIX}_INCLUDE_DIR}") + string (MD5 __${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}:${_${_PYTHON_PREFIX}_INCLUDE_DIR}") + if (WIN32 AND NOT DEFINED _${_PYTHON_PREFIX}_LIBRARY_DEBUG) + set (_${_PYTHON_PREFIX}_LIBRARY_DEBUG "_${_PYTHON_PREFIX}_LIBRARY_DEBUG-NOTFOUND" CACHE INTERNAL "") + endif() + if (NOT DEFINED _${_PYTHON_PREFIX}_INCLUDE_DIR) + set (_${_PYTHON_PREFIX}_INCLUDE_DIR "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND" CACHE INTERNAL "") + endif() if (__${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE) # check version validity if (${_PYTHON_PREFIX}_FIND_VERSION_EXACT) - _python_validate_library (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT) - _python_validate_include_dir (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT) + _python_validate_library (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT CHECK_EXISTS) + _python_validate_include_dir (${${_PYTHON_PREFIX}_FIND_VERSION} EXACT CHECK_EXISTS) else() - _python_validate_library (${${_PYTHON_PREFIX}_FIND_VERSION}) - _python_validate_include_dir (${${_PYTHON_PREFIX}_FIND_VERSION}) + _python_validate_library (${${_PYTHON_PREFIX}_FIND_VERSION} CHECK_EXISTS) + _python_validate_include_dir (${${_PYTHON_PREFIX}_FIND_VERSION} CHECK_EXISTS) endif() else() - unset (${_PYTHON_PREFIX}_LIBRARY_RELEASE CACHE) - unset (${_PYTHON_PREFIX}_LIBRARY_DEBUG CACHE) - unset (${_PYTHON_PREFIX}_INCLUDE_DIR CACHE) + unset (_${_PYTHON_PREFIX}_LIBRARY_RELEASE CACHE) + unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG CACHE) + unset (_${_PYTHON_PREFIX}_INCLUDE_DIR CACHE) unset (_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE CACHE) endif() endif() + if (DEFINED ${_PYTHON_PREFIX}_LIBRARY + AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_LIBRARY}") + set (_${_PYTHON_PREFIX}_LIBRARY_RELEASE "${${_PYTHON_PREFIX}_LIBRARY}" CACHE INTERNAL "") + unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG CACHE) + unset (_${_PYTHON_PREFIX}_INCLUDE_DIR CACHE) + endif() + if (DEFINED ${_PYTHON_PREFIX}_INCLUDE_DIR + AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_INCLUDE_DIR}") + set (_${_PYTHON_PREFIX}_INCLUDE_DIR "${${_PYTHON_PREFIX}_INCLUDE_DIR}" CACHE INTERNAL "") + endif() # Support preference of static libs by adjusting CMAKE_FIND_LIBRARY_SUFFIXES unset (_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES) @@ -1454,7 +1510,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() endif() - if (NOT ${_PYTHON_PREFIX}_LIBRARY_RELEASE OR NOT ${_PYTHON_PREFIX}_INCLUDE_DIR) + if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE OR NOT _${_PYTHON_PREFIX}_INCLUDE_DIR) # if python interpreter is found, use it to look-up for artifacts # to ensure consistency between interpreter and development environments. # If not, try to locate a compatible config tool @@ -1653,7 +1709,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() endif() - if (NOT ${_PYTHON_PREFIX}_LIBRARY_RELEASE) + if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) if ((${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT CMAKE_CROSSCOMPILING) OR _${_PYTHON_PREFIX}_CONFIG) # retrieve root install directory _python_get_config_var (_${_PYTHON_PREFIX}_PREFIX PREFIX) @@ -1678,7 +1734,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS list (APPEND _${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) - find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} @@ -1688,7 +1744,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # Rely on HINTS and standard paths if interpreter or config tool failed to locate artifacts - if (NOT ${_PYTHON_PREFIX}_LIBRARY_RELEASE) + if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) unset (_${_PYTHON_PREFIX}_VIRTUALENV_PATHS) @@ -1724,7 +1780,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endforeach() if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} @@ -1738,7 +1794,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} @@ -1750,7 +1806,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # search in HINTS locations - find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} @@ -1772,7 +1828,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # search in all default paths - find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR PATHS ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS} @@ -1789,7 +1845,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_LIB_VERSION} LIBRARY) if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} @@ -1803,7 +1859,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} @@ -1815,7 +1871,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # search in HINTS locations - find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR HINTS ${_${_PYTHON_PREFIX}_HINTS} @@ -1837,14 +1893,14 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # search in all default paths - find_library (${_PYTHON_PREFIX}_LIBRARY_RELEASE + find_library (_${_PYTHON_PREFIX}_LIBRARY_RELEASE NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} NAMES_PER_DIR PATHS ${__${_PYTHON_PREFIX}_FRAMEWORK_PATHS} ${__${_PYTHON_PREFIX}_REGISTRY_PATHS} PATH_SUFFIXES ${_${_PYTHON_PREFIX}_PATH_SUFFIXES}) - if (${_PYTHON_PREFIX}_LIBRARY_RELEASE) + if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE) break() endif() endforeach() @@ -1855,14 +1911,20 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS # finalize library version information _python_get_version (LIBRARY PREFIX _${_PYTHON_PREFIX}_) + set (${_PYTHON_PREFIX}_LIBRARY_RELEASE "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" CACHE FILEPATH "Path to a library." FORCE) + + if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND NOT EXISTS "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}") + set_property (CACHE _${_PYTHON_PREFIX}_LIBRARY_RELEASE PROPERTY VALUE "_${_PYTHON_PREFIX}_LIBRARY_RELEASE-NOTFOUND") + endif() + set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) - if (WIN32 AND ${_PYTHON_PREFIX}_LIBRARY_RELEASE) + if (WIN32 AND _${_PYTHON_PREFIX}_LIBRARY_RELEASE) # search for debug library # use release library location as a hint _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 DEBUG) - get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) - find_library (${_PYTHON_PREFIX}_LIBRARY_DEBUG + get_filename_component (_${_PYTHON_PREFIX}_PATH "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) + find_library (_${_PYTHON_PREFIX}_LIBRARY_DEBUG NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG} NAMES_PER_DIR HINTS "${_${_PYTHON_PREFIX}_PATH}" ${_${_PYTHON_PREFIX}_HINTS} @@ -1870,9 +1932,9 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # retrieve runtime libraries - if (${_PYTHON_PREFIX}_LIBRARY_RELEASE) + if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE) _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 POSIX LIBRARY) - get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) + get_filename_component (_${_PYTHON_PREFIX}_PATH "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) get_filename_component (_${_PYTHON_PREFIX}_PATH2 "${_${_PYTHON_PREFIX}_PATH}" DIRECTORY) _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES} @@ -1880,9 +1942,9 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS HINTS "${_${_PYTHON_PREFIX}_PATH}" "${_${_PYTHON_PREFIX}_PATH2}" ${_${_PYTHON_PREFIX}_HINTS} PATH_SUFFIXES bin) endif() - if (${_PYTHON_PREFIX}_LIBRARY_DEBUG) + if (_${_PYTHON_PREFIX}_LIBRARY_DEBUG) _python_get_names (_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_VERSION} WIN32 DEBUG) - get_filename_component (_${_PYTHON_PREFIX}_PATH "${${_PYTHON_PREFIX}_LIBRARY_DEBUG}" DIRECTORY) + get_filename_component (_${_PYTHON_PREFIX}_PATH "${_${_PYTHON_PREFIX}_LIBRARY_DEBUG}" DIRECTORY) get_filename_component (_${_PYTHON_PREFIX}_PATH2 "${_${_PYTHON_PREFIX}_PATH}" DIRECTORY) _python_find_runtime_library (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG NAMES ${_${_PYTHON_PREFIX}_LIB_NAMES_DEBUG} @@ -1892,11 +1954,11 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # Don't search for include dir if no library was founded - if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND NOT ${_PYTHON_PREFIX}_INCLUDE_DIR) + if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND NOT _${_PYTHON_PREFIX}_INCLUDE_DIR) if ((${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT CMAKE_CROSSCOMPILING) OR _${_PYTHON_PREFIX}_CONFIG) _python_get_config_var (_${_PYTHON_PREFIX}_INCLUDE_DIRS INCLUDES) - find_path (${_PYTHON_PREFIX}_INCLUDE_DIR + find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR NAMES Python.h HINTS ${_${_PYTHON_PREFIX}_INCLUDE_DIRS} NO_SYSTEM_ENVIRONMENT_PATH @@ -1904,7 +1966,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # Rely on HINTS and standard paths if interpreter or config tool failed to locate artifacts - if (NOT ${_PYTHON_PREFIX}_INCLUDE_DIR) + 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) @@ -1912,15 +1974,15 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS unset (_${_PYTHON_PREFIX}_INCLUDE_HINTS) # Use the library's install prefix as a hint - if (${${_PYTHON_PREFIX}_LIBRARY_RELEASE} MATCHES "^(.+/Frameworks/Python.framework/Versions/[0-9.]+)") + if (${_${_PYTHON_PREFIX}_LIBRARY_RELEASE} MATCHES "^(.+/Frameworks/Python.framework/Versions/[0-9.]+)") list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}") - elseif (${${_PYTHON_PREFIX}_LIBRARY_RELEASE} MATCHES "^(.+)/lib(64|32)?/python[0-9.]+/config") + elseif (${_${_PYTHON_PREFIX}_LIBRARY_RELEASE} MATCHES "^(.+)/lib(64|32)?/python[0-9.]+/config") list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${CMAKE_MATCH_1}") - elseif (DEFINED CMAKE_LIBRARY_ARCHITECTURE AND ${${_PYTHON_PREFIX}_LIBRARY_RELEASE} MATCHES "^(.+)/lib/${CMAKE_LIBRARY_ARCHITECTURE}") + elseif (DEFINED CMAKE_LIBRARY_ARCHITECTURE AND ${_${_PYTHON_PREFIX}_LIBRARY_RELEASE} MATCHES "^(.+)/lib/${CMAKE_LIBRARY_ARCHITECTURE}") 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}_LIBRARY_RELEASE}" DIRECTORY) + get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" DIRECTORY) get_filename_component (_${_PYTHON_PREFIX}_PREFIX "${_${_PYTHON_PREFIX}_PREFIX}" DIRECTORY) list (APPEND _${_PYTHON_PREFIX}_INCLUDE_HINTS "${_${_PYTHON_PREFIX}_PREFIX}") endif() @@ -1930,7 +1992,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS _python_get_path_suffixes (_${_PYTHON_PREFIX}_PATH_SUFFIXES VERSION ${_${_PYTHON_PREFIX}_VERSION} INCLUDE) if (APPLE AND _${_PYTHON_PREFIX}_FIND_FRAMEWORK STREQUAL "FIRST") - find_path (${_PYTHON_PREFIX}_INCLUDE_DIR + find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR NAMES Python.h HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS} PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} @@ -1943,7 +2005,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() if (WIN32 AND _${_PYTHON_PREFIX}_FIND_REGISTRY STREQUAL "FIRST") - find_path (${_PYTHON_PREFIX}_INCLUDE_DIR + find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR NAMES Python.h HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS} PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} @@ -1965,7 +2027,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS unset (__${_PYTHON_PREFIX}_REGISTRY_PATHS) endif() - find_path (${_PYTHON_PREFIX}_INCLUDE_DIR + find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR NAMES Python.h HINTS ${_${_PYTHON_PREFIX}_INCLUDE_HINTS} ${_${_PYTHON_PREFIX}_HINTS} PATHS ${_${_PYTHON_PREFIX}_VIRTUALENV_PATHS} @@ -1977,15 +2039,21 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # search header file in standard locations - find_path (${_PYTHON_PREFIX}_INCLUDE_DIR + find_path (_${_PYTHON_PREFIX}_INCLUDE_DIR NAMES Python.h) endif() - # retrieve version from header file - _python_get_version (INCLUDE PREFIX _${_PYTHON_PREFIX}_INC_) + set (${_PYTHON_PREFIX}_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") + + if (_${_PYTHON_PREFIX}_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}") + set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") + endif() - if (${_PYTHON_PREFIX}_INCLUDE_DIR) - # update versionning + if (_${_PYTHON_PREFIX}_INCLUDE_DIR) + # retrieve version from header file + _python_get_version (INCLUDE PREFIX _${_PYTHON_PREFIX}_INC_) + + # update versioning if (_${_PYTHON_PREFIX}_INC_VERSION VERSION_EQUAL ${_${_PYTHON_PREFIX}_VERSION}) set (_${_PYTHON_PREFIX}_VERSION_PATCH ${_${_PYTHON_PREFIX}_INC_VERSION_PATCH}) endif() @@ -2000,10 +2068,14 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # define public variables + set (${_PYTHON_PREFIX}_LIBRARY_DEBUG "${_${_PYTHON_PREFIX}_LIBRARY_DEBUG}" CACHE FILEPATH "Path to a library." FORCE) + 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() @@ -2019,9 +2091,7 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG) endif() - set (${_PYTHON_PREFIX}_INCLUDE_DIRS "${${_PYTHON_PREFIX}_INCLUDE_DIR}") - - if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_INCLUDE_DIR) + if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE AND _${_PYTHON_PREFIX}_INCLUDE_DIR) if (${_PYTHON_PREFIX}_Interpreter_FOUND OR ${_PYTHON_PREFIX}_Compiler_FOUND) # development 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} @@ -2032,11 +2102,16 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_${_PYTHON_PREFIX}_INC_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_INC_VERSION_MINOR} VERSION_EQUAL ${_${_PYTHON_PREFIX}_VERSION_MAJOR}.${_${_PYTHON_PREFIX}_VERSION_MINOR}) set (${_PYTHON_PREFIX}_Development_FOUND TRUE) endif() + if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND + (NOT _${_PYTHON_PREFIX}_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS + OR NOT _${_PYTHON_PREFIX}_INC_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS)) + set (${_PYTHON_PREFIX}_Development_FOUND FALSE) + endif() endif() if (${_PYTHON_PREFIX}_Development_FOUND) # compute and save development signature - string (MD5 __${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${${_PYTHON_PREFIX}_LIBRARY_RELEASE}:${${_PYTHON_PREFIX}_INCLUDE_DIR}") + string (MD5 __${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE "${_${_PYTHON_PREFIX}_SIGNATURE}:${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}:${_${_PYTHON_PREFIX}_INCLUDE_DIR}") set (_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE "${__${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE}" CACHE INTERNAL "") else() unset (_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE CACHE) @@ -2047,28 +2122,34 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS set (CMAKE_FIND_LIBRARY_SUFFIXES ${_${_PYTHON_PREFIX}_CMAKE_FIND_LIBRARY_SUFFIXES}) endif() - mark_as_advanced (${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE + mark_as_advanced (_${_PYTHON_PREFIX}_LIBRARY_RELEASE + _${_PYTHON_PREFIX}_LIBRARY_DEBUG + ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG - ${_PYTHON_PREFIX}_INCLUDE_DIR + _${_PYTHON_PREFIX}_INCLUDE_DIR _${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE) endif() if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Interpreter_FOUND) - list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) + list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) if (${_PYTHON_PREFIX}_FIND_REQUIRED_NumPy) - list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) + list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS) endif() - if (DEFINED ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) + if (DEFINED ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR + AND IS_ABSOLUTE "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") + set (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}" CACHE INTERNAL "") + elseif (DEFINED _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) # compute numpy signature. Depends on interpreter and development signatures - string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}:${_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE}:${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") - if (NOT __${_PYTHON_PREFIX}_NUMPY_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_NUMPY_SIGNATURE) - unset (${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR CACHE) + string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}:${_${_PYTHON_PREFIX}_DEVELOPMENT_SIGNATURE}:${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") + if (NOT __${_PYTHON_PREFIX}_NUMPY_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_NUMPY_SIGNATURE + OR NOT EXISTS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") + unset (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR CACHE) unset (_${_PYTHON_PREFIX}_NUMPY_SIGNATURE CACHE) endif() endif() - if (NOT ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) + if (NOT _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) execute_process( COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "from __future__ import print_function\ntry: import numpy; print(numpy.get_include(), end='')\nexcept:pass\n" @@ -2078,16 +2159,20 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte OUTPUT_STRIP_TRAILING_WHITESPACE) if (NOT _${_PYTHON_PREFIX}_RESULT) - find_path (${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR + find_path (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR NAMES "numpy/arrayobject.h" "numpy/numpyconfig.h" HINTS "${_${_PYTHON_PREFIX}_NumPy_PATH}" NO_DEFAULT_PATH) endif() endif() - if(${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) - set (${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") + set (${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") + + if(_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR AND NOT EXISTS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") + set_property (CACHE _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR PROPERTY VALUE "_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR-NOTFOUND") + endif() + if (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) execute_process ( COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c "from __future__ import print_function\ntry: import numpy; print(numpy.__version__, end='')\nexcept:pass\n" @@ -2112,6 +2197,8 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte else() unset (_${_PYTHON_PREFIX}_NUMPY_SIGNATURE CACHE) endif() + + mark_as_advanced (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) endif() # final validation @@ -2155,10 +2242,12 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT") set (_${_PYTHON_PREFIX}_LIBRARY_TYPE STATIC) endif() - add_library (${__name} ${_${_PYTHON_PREFIX}_LIBRARY_TYPE} IMPORTED) + if (NOT TARGET ${__name}) + add_library (${__name} ${_${_PYTHON_PREFIX}_LIBRARY_TYPE} IMPORTED) + endif() set_property (TARGET ${__name} - PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIR}") + PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIRS}") if (${_PYTHON_PREFIX}_LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE) # System manage shared libraries in two parts: import and runtime @@ -2204,33 +2293,31 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT") endif() endmacro() - if (NOT TARGET ${_PYTHON_PREFIX}::Python) - __python_import_library (${_PYTHON_PREFIX}::Python) - endif() + __python_import_library (${_PYTHON_PREFIX}::Python) - if (NOT TARGET ${_PYTHON_PREFIX}::Module) - if (CMAKE_SYSTEM_NAME MATCHES "^(Windows.*|CYGWIN|MSYS)$") - # On Windows/CYGWIN/MSYS, Python::Module is the same as Python::Python - # but ALIAS cannot be used because the imported library is not GLOBAL. - __python_import_library (${_PYTHON_PREFIX}::Module) - else() + if (CMAKE_SYSTEM_NAME MATCHES "^(Windows.*|CYGWIN|MSYS)$") + # On Windows/CYGWIN/MSYS, Python::Module is the same as Python::Python + # but ALIAS cannot be used because the imported library is not GLOBAL. + __python_import_library (${_PYTHON_PREFIX}::Module) + else() + if (NOT TARGET ${_PYTHON_PREFIX}::Module ) add_library (${_PYTHON_PREFIX}::Module INTERFACE IMPORTED) - set_property (TARGET ${_PYTHON_PREFIX}::Module - PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIR}") + endif() + set_property (TARGET ${_PYTHON_PREFIX}::Module + PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIRS}") - # When available, enforce shared library generation with undefined symbols - if (APPLE) - set_property (TARGET ${_PYTHON_PREFIX}::Module - PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-undefined,dynamic_lookup") - endif() - if (CMAKE_SYSTEM_NAME STREQUAL "SunOS") - set_property (TARGET ${_PYTHON_PREFIX}::Module - PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-z,nodefs") - endif() - if (CMAKE_SYSTEM_NAME STREQUAL "AIX") - set_property (TARGET ${_PYTHON_PREFIX}::Module - PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-b,erok") - endif() + # When available, enforce shared library generation with undefined symbols + if (APPLE) + set_property (TARGET ${_PYTHON_PREFIX}::Module + PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-undefined,dynamic_lookup") + endif() + if (CMAKE_SYSTEM_NAME STREQUAL "SunOS") + set_property (TARGET ${_PYTHON_PREFIX}::Module + PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-z,nodefs") + endif() + if (CMAKE_SYSTEM_NAME STREQUAL "AIX") + set_property (TARGET ${_PYTHON_PREFIX}::Module + PROPERTY INTERFACE_LINK_OPTIONS "LINKER:-b,erok") endif() endif() @@ -2269,7 +2356,7 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT") AND NOT TARGET ${_PYTHON_PREFIX}::NumPy AND TARGET ${_PYTHON_PREFIX}::Module) add_library (${_PYTHON_PREFIX}::NumPy INTERFACE IMPORTED) set_property (TARGET ${_PYTHON_PREFIX}::NumPy - PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}") + PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS}") target_link_libraries (${_PYTHON_PREFIX}::NumPy INTERFACE ${_PYTHON_PREFIX}::Module) endif() endif() diff --git a/Modules/FindPython2.cmake b/Modules/FindPython2.cmake index 82878ea..0cecdc6 100644 --- a/Modules/FindPython2.cmake +++ b/Modules/FindPython2.cmake @@ -199,6 +199,44 @@ Hints recommended to also include the component ``Interpreter`` to get expected result. +Artifacts Specification +^^^^^^^^^^^^^^^^^^^^^^^ + +To solve special cases, it is possible to specify directly the artifacts by +setting the following variables: + +``Python2_EXECUTABLE`` + The path to the interpreter. + +``Python2_COMPILER`` + The path to the compiler. + +``Python2_LIBRARY`` + The path to the library. It will be used to compute the + variables ``Python2_LIBRARIES``, ``Python2_LIBRAY_DIRS`` and + ``Python2_RUNTIME_LIBRARY_DIRS``. + +``Python2_INCLUDE_DIR`` + The path to the directory of the ``Python`` headers. It will be used to + compute the variable ``Python2_INCLUDE_DIRS``. + +``Python2_NumPy_INCLUDE_DIR`` + The path to the directory of the ``NumPy`` headers. It will be used to + compute the variable ``Python2_NumPy_INCLUDE_DIRS``. + +.. note:: + + All paths must be absolute. Any artifact specified with a relative path + will be ignored. + +.. note:: + + When an artifact is specified, all ``HINTS`` will be ignored and no search + will be performed for this artifact. + + If more than one artifact is specified, it is the user's responsability to + ensure the consistency of the various artifacts. + Commands ^^^^^^^^ diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake index 417a789..1edb9c9 100644 --- a/Modules/FindPython3.cmake +++ b/Modules/FindPython3.cmake @@ -240,6 +240,44 @@ Hints recommended to also include the component ``Interpreter`` to get expected result. +Artifacts Specification +^^^^^^^^^^^^^^^^^^^^^^^ + +To solve special cases, it is possible to specify directly the artifacts by +setting the following variables: + +``Python3_EXECUTABLE`` + The path to the interpreter. + +``Python3_COMPILER`` + The path to the compiler. + +``Python3_LIBRARY`` + The path to the library. It will be used to compute the + variables ``Python3_LIBRARIES``, ``Python3_LIBRAY_DIRS`` and + ``Python3_RUNTIME_LIBRARY_DIRS``. + +``Python3_INCLUDE_DIR`` + The path to the directory of the ``Python`` headers. It will be used to + compute the variable ``Python3_INCLUDE_DIRS``. + +``Python3_NumPy_INCLUDE_DIR`` + The path to the directory of the ``NumPy`` headers. It will be used to + compute the variable ``Python3_NumPy_INCLUDE_DIRS``. + +.. note:: + + All paths must be absolute. Any artifact specified with a relative path + will be ignored. + +.. note:: + + When an artifact is specified, all ``HINTS`` will be ignored and no search + will be performed for this artifact. + + If more than one artifact is specified, it is the user's responsability to + ensure the consistency of the various artifacts. + Commands ^^^^^^^^ diff --git a/Tests/FindPython/CMakeLists.txt b/Tests/FindPython/CMakeLists.txt index 4be2f22..868cfe0 100644 --- a/Tests/FindPython/CMakeLists.txt +++ b/Tests/FindPython/CMakeLists.txt @@ -121,6 +121,19 @@ if(CMake_TEST_FindPython) --test-command ${CMAKE_CTEST_COMMAND} -V -C $ ) + add_test(NAME FindPython.RequiredArtifacts COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/RequiredArtifacts" + "${CMake_BINARY_DIR}/Tests/FindPython/RequiredArtifacts" + ${build_generator_args} + --build-project TestRequiredArtifacts + --build-options ${build_options} "-Dbuild_generator_args=${build_generator_args}" + "-DCMake_SOURCE_DIR=${CMake_SOURCE_DIR}" + "-DCMake_BINARY_DIR=${CMake_BINARY_DIR}" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) + endif() if(CMake_TEST_FindPython_NumPy) diff --git a/Tests/FindPython/RequiredArtifacts/CMakeLists.txt b/Tests/FindPython/RequiredArtifacts/CMakeLists.txt new file mode 100644 index 0000000..39e8ea5 --- /dev/null +++ b/Tests/FindPython/RequiredArtifacts/CMakeLists.txt @@ -0,0 +1,110 @@ +cmake_minimum_required(VERSION 3.1) + +project(TestRequiredArtifacts LANGUAGES C) + +include(CTest) + +find_package(Python2 REQUIRED COMPONENTS Interpreter Development) +if (NOT Python2_FOUND) + message (FATAL_ERROR "Fail to found Python 2") +endif() +find_package(Python3 REQUIRED COMPONENTS Interpreter Development) +if (NOT Python3_FOUND) + message (FATAL_ERROR "Fail to found Python 3") +endif() + + +add_test(NAME FindPython.RequiredArtifacts.Interpreter.VALID COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/RequiredArtifacts/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/RequiredArtifacts/Interpreter.VALID" + ${build_generator_args} + --build-project TestRequiredArtifacts.Check + --build-options -DPYTHON_IS_FOUND=TRUE -DCHECK_INTERPRETER=ON + "-DPython3_EXECUTABLE=${Python3_EXECUTABLE}" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) +add_test(NAME FindPython.RequiredArtifacts.Interpreter.INVALID COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/RequiredArtifacts/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/RequiredArtifacts/Interpreter.INVALID" + ${build_generator_args} + --build-project TestRequiredArtifacts.Check + --build-options -DPYTHON_IS_FOUND=FALSE -DCHECK_INTERPRETER=ON + "-DPython3_EXECUTABLE=${Python3_EXECUTABLE}-bad${CMAKE_EXECUTABLE_SUFFIX}" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) + +add_test(NAME FindPython.RequiredArtifacts.Library.VALID COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/RequiredArtifacts/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/RequiredArtifacts/Library.VALID" + ${build_generator_args} + --build-project TestRequiredArtifacts.Check + --build-options -DPYTHON_IS_FOUND=TRUE -DCHECK_LIBRARY=ON + "-DPython3_LIBRARY=${Python3_LIBRARY_RELEASE}" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) +add_test(NAME FindPython.RequiredArtifacts.Library.INVALID COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/RequiredArtifacts/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/RequiredArtifacts/Library.INVALID" + ${build_generator_args} + --build-project TestRequiredArtifacts.Check + --build-options -DPYTHON_IS_FOUND=FALSE -DCHECK_LIBRARY=ON + "-DPython3_LIBRARY=${Python2_LIBRARY_RELEASE}" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) + +add_test(NAME FindPython.RequiredArtifacts.Include.VALID COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/RequiredArtifacts/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/RequiredArtifacts/Include.VALID" + ${build_generator_args} + --build-project TestRequiredArtifacts.Check + --build-options -DPYTHON_IS_FOUND=TRUE -DCHECK_INCLUDE=ON + "-DPython3_INCLUDE_DIR=${Python3_INCLUDE_DIRS}" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) +add_test(NAME FindPython.RequiredArtifacts.Include.INVALID COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/RequiredArtifacts/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/RequiredArtifacts/Include.INVALID" + ${build_generator_args} + --build-project TestRequiredArtifacts.Check + --build-options -DPYTHON_IS_FOUND=FALSE -DCHECK_INCLUDE=ON + "-DPython3_INCLUDE_DIR=${Python2_INCLUDE_DIRS}" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) + +add_test(NAME FindPython.RequiredArtifacts.Interpreter-Library.INVALID COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/RequiredArtifacts/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/RequiredArtifacts/Interpreter-Library.INVALID" + ${build_generator_args} + --build-project TestRequiredArtifacts.Check + --build-options -DPYTHON_IS_FOUND=FALSE -DCHECK_INTERPRETER=ON -DCHECK_LIBRARY=ON + "-DPython3_EXECUTABLE=${Python3_EXECUTABLE}" + "-DPython3_LIBRARY=${Python2_LIBRARY_RELEASE}" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) + +add_test(NAME FindPython.RequiredArtifacts.Library-Include.INVALID COMMAND + ${CMAKE_CTEST_COMMAND} -C $ + --build-and-test + "${CMake_SOURCE_DIR}/Tests/FindPython/RequiredArtifacts/Check" + "${CMake_BINARY_DIR}/Tests/FindPython/RequiredArtifacts/Library-Include.INVALID" + ${build_generator_args} + --build-project TestRequiredArtifacts.Check + --build-options -DPYTHON_IS_FOUND=FALSE -DCHECK_LIBRARY=ON -DCHECK_INCLUDE=ON + "-DPython3_LIBRARY=${Python3_LIBRARY_RELEASE}" + "-DPython3_INCLUDE_DIR=${Python2_INCLUDE_DIRS}" + --test-command ${CMAKE_CTEST_COMMAND} -V -C $ + ) diff --git a/Tests/FindPython/RequiredArtifacts/Check/CMakeLists.txt b/Tests/FindPython/RequiredArtifacts/Check/CMakeLists.txt new file mode 100644 index 0000000..b859ac5 --- /dev/null +++ b/Tests/FindPython/RequiredArtifacts/Check/CMakeLists.txt @@ -0,0 +1,41 @@ +cmake_minimum_required(VERSION 3.1) + +project(TestRequiredArtifacts.Check LANGUAGES C) + +set (components) +if (CHECK_INTERPRETER) + set (required_interpreter "${Python3_EXECUTABLE}") + list (APPEND components Interpreter) +endif() +if (CHECK_LIBRARY OR CHECK_INCLUDE) + list (APPEND components Development) + if (CHECK_LIBRARY) + set (required_library "${Python3_LIBRARY}") + endif() + if (CHECK_INCLUDE) + set (required_include "${Python3_INCLUDE_DIR}") + endif() +endif() + +find_package (Python3 COMPONENTS ${components}) + + +if (PYTHON_IS_FOUND AND NOT Python3_FOUND) + message (FATAL_ERROR "Python3 unexpectedly not found") +endif() +if (NOT PYTHON_IS_FOUND AND Python3_FOUND) + message (FATAL_ERROR "Python3 unexpectedly found") +endif() + + +if (CHECK_INTERPRETER AND NOT Python3_EXECUTABLE STREQUAL required_interpreter) + message (FATAL_ERROR "Fail to use input variable Python3_EXECUTABLE") +endif() + +if (CHECK_LIBRARY AND NOT Python3_LIBRARY_RELEASE STREQUAL required_library) + message (FATAL_ERROR "Fail to use input variable Python3_LIBRARY") +endif() + +if (CHECK_INCLUDE AND NOT Python3_INCLUDE_DIRS STREQUAL required_include) + message (FATAL_ERROR "Fail to use input variable Python3_INCLUDE_DIR") +endif() -- cgit v0.12