diff --git a/config/FindBoost.cmake b/config/FindBoost.cmake index 248ea8b6..1de476a7 100644 --- a/config/FindBoost.cmake +++ b/config/FindBoost.cmake @@ -5,6 +5,11 @@ FindBoost --------- +.. versionchanged:: 3.30 + This module is available only if policy :policy:`CMP0167` is not set to + ``NEW``. Port projects to upstream Boost's ``BoostConfig.cmake`` package + configuration file, for which ``find_package(Boost)`` now searches. + Find Boost include dirs and libraries Use this module by invoking :command:`find_package` with the form: @@ -379,6 +384,16 @@ the Boost CMake package configuration for details on what it provides. Set ``Boost_NO_BOOST_CMAKE`` to ``ON``, to disable the search for boost-cmake. #]=======================================================================] +cmake_policy(GET CMP0167 _FindBoost_CMP0167) +if(_FindBoost_CMP0167 STREQUAL "NEW") + message(FATAL_ERROR "The FindBoost module has been removed by policy CMP0167.") +endif() + +if(_FindBoost_testing) + set(_FindBoost_included TRUE) + return() +endif() + # The FPHSA helper provides standard way of reporting final search results to # the user including the version and component checks. include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) @@ -387,6 +402,7 @@ include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) cmake_policy(PUSH) cmake_policy(SET CMP0057 NEW) # if IN_LIST cmake_policy(SET CMP0102 NEW) # if mark_as_advanced(non_cache_var) +cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_ function(_boost_get_existing_target component target_var) set(names "${component}") @@ -1394,7 +1410,7 @@ function(_Boost_COMPONENT_DEPENDENCIES component _ret) set(_Boost_THREAD_DEPENDENCIES chrono atomic) set(_Boost_WAVE_DEPENDENCIES filesystem serialization thread chrono atomic) set(_Boost_WSERIALIZATION_DEPENDENCIES serialization) - if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.85.0 AND NOT Boost_NO_WARN_NEW_VERSIONS) + if(Boost_VERSION_STRING VERSION_GREATER_EQUAL 1.86.0 AND NOT Boost_NO_WARN_NEW_VERSIONS) message(WARNING "New Boost version may have incorrect or missing dependencies and imported targets") endif() endif() @@ -1669,7 +1685,7 @@ else() # _Boost_COMPONENT_HEADERS. See the instructions at the top of # _Boost_COMPONENT_DEPENDENCIES. set(_Boost_KNOWN_VERSIONS ${Boost_ADDITIONAL_VERSIONS} - "1.84.0" "1.84" + "1.85.0" "1.85" "1.84.0" "1.84" "1.83.0" "1.83" "1.82.0" "1.82" "1.81.0" "1.81" "1.80.0" "1.80" "1.79.0" "1.79" "1.78.0" "1.78" "1.77.0" "1.77" "1.76.0" "1.76" "1.75.0" "1.75" "1.74.0" "1.74" "1.73.0" "1.73" "1.72.0" "1.72" "1.71.0" "1.71" "1.70.0" "1.70" "1.69.0" "1.69" diff --git a/config/FindICU.cmake b/config/FindICU.cmake index b4f4d713..63c25760 100644 --- a/config/FindICU.cmake +++ b/config/FindICU.cmake @@ -24,10 +24,10 @@ platform-specific library name will be automatically selected. This module reports information about the ICU installation in several variables. General variables:: - ICU_VERSION - ICU release version ICU_FOUND - true if the main programs and libraries were found - ICU_LIBRARIES - component libraries to be linked ICU_INCLUDE_DIRS - the directories containing the ICU headers + ICU_LIBRARIES - component libraries to be linked + ICU_VERSION - ICU release version Imported targets:: @@ -83,12 +83,10 @@ The following cache variables may also be set:: In most cases none of the above variables will require setting, unless multiple ICU versions are available and a specific version is required. - -Other variables one may set to control this module are:: - - ICU_DEBUG - Set to ON to enable debug output from FindICU. #]=======================================================================] +cmake_policy(PUSH) +cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_ # Written by Roger Leigh set(icu_programs @@ -136,6 +134,7 @@ function(_ICU_FIND) HINTS ${icu_roots} PATH_SUFFIXES ${icu_include_suffixes} DOC "ICU include directory") + mark_as_advanced(ICU_INCLUDE_DIR) set(ICU_INCLUDE_DIR "${ICU_INCLUDE_DIR}" PARENT_SCOPE) # Get version @@ -178,7 +177,6 @@ function(_ICU_FIND) # Find all ICU libraries list(APPEND icu_library_suffixes "${_lib64}" "lib") - set(ICU_REQUIRED_LIBS_FOUND ON) set(static_prefix ) # static icu libraries compiled with MSVC have the prefix 's' if(MSVC) @@ -189,8 +187,9 @@ function(_ICU_FIND) set(component_cache "ICU_${component_upcase}_LIBRARY") set(component_cache_release "${component_cache}_RELEASE") set(component_cache_debug "${component_cache}_DEBUG") - set(component_found "ICU_${component_upcase}_FOUND") + set(component_found "ICU_${component}_FOUND") set(component_found_compat "${component_upcase}_FOUND") + set(component_found_compat2 "ICU_${component_upcase}_FOUND") set(component_libnames "icu${component}") set(component_debug_libnames "icu${component}d") @@ -253,27 +252,17 @@ function(_ICU_FIND) if(${component_cache}) set("${component_found}" ON) set("${component_found_compat}" ON) + set("${component_found_compat2}" ON) list(APPEND ICU_LIBRARY "${${component_cache}}") - if (ICU_FIND_REQUIRED_${component}) - list(APPEND ICU_LIBS_FOUND "${component} (required): ${${component_cache}}") - else() - list(APPEND ICU_LIBS_FOUND "${component} (optional): ${${component_cache}}") - endif() - else() - if (ICU_FIND_REQUIRED_${component}) - set(ICU_REQUIRED_LIBS_FOUND OFF) - list(APPEND ICU_LIBS_NOTFOUND "${component} (required)") - else() - list(APPEND ICU_LIBS_NOTFOUND "${component} (optional)") - endif() endif() mark_as_advanced("${component_found}") mark_as_advanced("${component_found_compat}") + mark_as_advanced("${component_found_compat2}") set("${component_cache}" "${${component_cache}}" PARENT_SCOPE) set("${component_found}" "${${component_found}}" PARENT_SCOPE) set("${component_found_compat}" "${${component_found_compat}}" PARENT_SCOPE) + set("${component_found_compat2}" "${${component_found_compat2}}" PARENT_SCOPE) endforeach() - set(_ICU_REQUIRED_LIBS_FOUND "${ICU_REQUIRED_LIBS_FOUND}" PARENT_SCOPE) set(ICU_LIBRARY "${ICU_LIBRARY}" PARENT_SCOPE) # Find all ICU data files @@ -302,43 +291,21 @@ function(_ICU_FIND) mark_as_advanced("${cache_var}") set("${data_var}" "${${cache_var}}" PARENT_SCOPE) endforeach() - - if(NOT ICU_FIND_QUIETLY) - if(ICU_LIBS_FOUND) - message(STATUS "Found the following ICU libraries:") - foreach(found ${ICU_LIBS_FOUND}) - message(STATUS " ${found}") - endforeach() - endif() - if(ICU_LIBS_NOTFOUND) - message(STATUS "The following ICU libraries were not found:") - foreach(notfound ${ICU_LIBS_NOTFOUND}) - message(STATUS " ${notfound}") - endforeach() - endif() - endif() - - if(ICU_DEBUG) - message(STATUS "--------FindICU.cmake search debug--------") - message(STATUS "ICU binary path search order: ${icu_roots}") - message(STATUS "ICU include path search order: ${icu_roots}") - message(STATUS "ICU library path search order: ${icu_roots}") - message(STATUS "----------------") - endif() endfunction() _ICU_FIND() include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake) -FIND_PACKAGE_HANDLE_STANDARD_ARGS(ICU - FOUND_VAR ICU_FOUND - REQUIRED_VARS ICU_INCLUDE_DIR - ICU_LIBRARY - _ICU_REQUIRED_LIBS_FOUND - VERSION_VAR ICU_VERSION - FAIL_MESSAGE "Failed to find all ICU components") - -unset(_ICU_REQUIRED_LIBS_FOUND) +find_package_handle_standard_args(ICU + REQUIRED_VARS + ICU_INCLUDE_DIR + ICU_LIBRARY + VERSION_VAR + ICU_VERSION + HANDLE_COMPONENTS + FAIL_MESSAGE + "Failed to find all ICU components" +) if(ICU_FOUND) set(ICU_INCLUDE_DIRS "${ICU_INCLUDE_DIR}") @@ -392,45 +359,5 @@ if(ICU_FOUND) endforeach() endif() -if(ICU_DEBUG) - message(STATUS "--------FindICU.cmake results debug--------") - message(STATUS "ICU found: ${ICU_FOUND}") - message(STATUS "ICU_VERSION number: ${ICU_VERSION}") - message(STATUS "ICU_ROOT directory: ${ICU_ROOT}") - message(STATUS "ICU_INCLUDE_DIR directory: ${ICU_INCLUDE_DIR}") - message(STATUS "ICU_LIBRARIES: ${ICU_LIBRARIES}") - - foreach(program IN LISTS icu_programs) - string(TOUPPER "${program}" program_upcase) - set(program_lib "ICU_${program_upcase}_EXECUTABLE") - message(STATUS "${program} program: ${program_lib}=${${program_lib}}") - unset(program_upcase) - unset(program_lib) - endforeach() - - foreach(data IN LISTS icu_data) - string(TOUPPER "${data}" data_upcase) - string(REPLACE "." "_" data_upcase "${data_upcase}") - set(data_lib "ICU_${data_upcase}") - message(STATUS "${data} data: ${data_lib}=${${data_lib}}") - unset(data_upcase) - unset(data_lib) - endforeach() - - foreach(component IN LISTS ICU_FIND_COMPONENTS) - string(TOUPPER "${component}" component_upcase) - set(component_lib "ICU_${component_upcase}_LIBRARIES") - set(component_found "ICU_${component_upcase}_FOUND") - set(component_found_compat "${component_upcase}_FOUND") - message(STATUS "${component} library found: ${component_found}=${${component_found}}") - message(STATUS "${component} library found (compat name): ${component_found_compat}=${${component_found_compat}}") - message(STATUS "${component} library: ${component_lib}=${${component_lib}}") - unset(component_upcase) - unset(component_lib) - unset(component_found) - unset(component_found_compat) - endforeach() - message(STATUS "----------------") -endif() - unset(icu_programs) +cmake_policy(POP) diff --git a/config/FindPackageHandleStandardArgs.cmake b/config/FindPackageHandleStandardArgs.cmake index 56ba1e67..c6db4330 100644 --- a/config/FindPackageHandleStandardArgs.cmake +++ b/config/FindPackageHandleStandardArgs.cmake @@ -225,6 +225,9 @@ macro(_FPHSA_FAILURE_MESSAGE _msg) set (__msg "${_msg}") if (FPHSA_REASON_FAILURE_MESSAGE) string(APPEND __msg "\n Reason given by package: ${FPHSA_REASON_FAILURE_MESSAGE}\n") + elseif(NOT DEFINED PROJECT_NAME) + string(APPEND __msg "\n" + "Hint: The project() command has not yet been called. It sets up system-specific search paths.") endif() if (${_NAME}_FIND_REQUIRED) message(FATAL_ERROR "${__msg}") @@ -342,7 +345,7 @@ function(FIND_PACKAGE_CHECK_VERSION version result) set(version_msg "Found unsuitable version \"${version}\", but required is exact version \"${${package}_FIND_VERSION}\"") else () set(version_ok TRUE) - set(version_msg "(found suitable exact version \"${_FOUND_VERSION}\")") + set(version_msg "(found suitable exact version \"${version}\")") endif () else () if (NOT ${package}_FIND_VERSION VERSION_EQUAL version) diff --git a/config/FindPackageMessage.cmake b/config/FindPackageMessage.cmake index 0628b981..7efbe18d 100644 --- a/config/FindPackageMessage.cmake +++ b/config/FindPackageMessage.cmake @@ -37,6 +37,7 @@ function(find_package_message pkg msg details) set(DETAILS_VAR FIND_PACKAGE_MESSAGE_DETAILS_${pkg}) if(NOT "${details}" STREQUAL "${${DETAILS_VAR}}") # The message has not yet been printed. + string(STRIP "${msg}" msg) message(STATUS "${msg}") # Save the find details in the cache to avoid printing the same diff --git a/config/FindPython.cmake b/config/FindPython.cmake index 31ef1c7d..797891b9 100644 --- a/config/FindPython.cmake +++ b/config/FindPython.cmake @@ -77,9 +77,25 @@ This module defines the following :ref:`Imported Targets `: :prop_gbl:`CMAKE_ROLE` is ``PROJECT``. ``Python::Interpreter`` - Python interpreter. Target defined if component ``Interpreter`` is found. + Python interpreter. This target is defined only if the ``Interpreter`` + component is found. +``Python::InterpreterDebug`` + .. versionadded:: 3.30 + + Python debug interpreter. This target is defined only if the ``Interpreter`` + component is found and the ``Python_EXECUTABLE_DEBUG`` variable is defined. + The target is only defined on the ``Windows`` platform. + +``Python::InterpreterMultiConfig`` + .. versionadded:: 3.30 + + Python interpreter. The release or debug version of the interpreter will be + used, based on the context (platform, configuration). + This target is defined only if the ``Interpreter`` component is found + ``Python::Compiler`` - Python compiler. Target defined if component ``Compiler`` is found. + Python compiler. This target is defined only if the ``Compiler`` component is + found. ``Python::Module`` .. versionadded:: 3.15 @@ -114,6 +130,20 @@ This module will set the following variables in your project System has the Python interpreter. ``Python_EXECUTABLE`` Path to the Python interpreter. +``Python_EXECUTABLE_DEBUG`` + .. versionadded:: 3.30 + + Path to the debug Python interpreter. It is only defined on the ``Windows`` + platform. + +``Python_INTERPRETER`` + .. versionadded:: 3.30 + + Path to the Python interpreter, defined as a + :manual:`generator expression ` selecting + the ``Python_EXECUTABLE`` or ``Python_EXECUTABLE_DEBUG`` variable based on + the context (platform, configuration). + ``Python_INTERPRETER_ID`` A short string unique to the interpreter. Possible values include: * Python @@ -125,38 +155,28 @@ This module will set the following variables in your project ``Python_STDLIB`` Standard platform independent installation directory. - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=True)`` - or else ``sysconfig.get_path('stdlib')``. + Information returned by ``sysconfig.get_path('stdlib')``. ``Python_STDARCH`` Standard platform dependent installation directory. - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=True)`` - or else ``sysconfig.get_path('platstdlib')``. + Information returned by ``sysconfig.get_path('platstdlib')``. ``Python_SITELIB`` Third-party platform independent installation directory. - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False)`` - or else ``sysconfig.get_path('purelib')``. + Information returned by ``sysconfig.get_path('purelib')``. ``Python_SITEARCH`` Third-party platform dependent installation directory. - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)`` - or else ``sysconfig.get_path('platlib')``. + Information returned by ``sysconfig.get_path('platlib')``. ``Python_SOABI`` .. versionadded:: 3.17 Extension suffix for modules. - Information computed from ``distutils.sysconfig.get_config_var('EXT_SUFFIX')`` - or ``distutils.sysconfig.get_config_var('SOABI')`` or - ``python3-config --extension-suffix``. If package ``distutils.sysconfig`` is - not available, ``sysconfig.get_config_var('EXT_SUFFIX')`` or - ``sysconfig.get_config_var('SOABI')`` are used. + Information computed from ``sysconfig.get_config_var('EXT_SUFFIX')`` or + ``sysconfig.get_config_var('SOABI')`` or + ``python3-config --extension-suffix``. ``Python_SOSABI`` .. versionadded:: 3.26 @@ -204,6 +224,17 @@ This module will set the following variables in your project The Python include directories. +``Python_DEFINITIONS`` + .. versionadded:: 3.30.3 + + The Python preprocessor definitions. + +``Python_DEBUG_POSTFIX`` + .. versionadded.. 3.30 + + Postfix of debug python module. This variable can be used to define the + :prop_tgt:`DEBUG_POSTFIX` target property. + ``Python_LINK_OPTIONS`` .. versionadded:: 3.19 @@ -284,42 +315,54 @@ Hints This hint will be honored only when searched for ``Python`` version 3. - .. note:: + The ``Python_FIND_ABI`` variable is a 4-tuple specifying, in that order, + ``pydebug`` (``d``), ``pymalloc`` (``m``), ``unicode`` (``u``) and + ``gil_disabled`` (``t``) flags. - If ``Python_FIND_ABI`` is not defined, any ABI will be searched. + .. versionadded:: 3.30 + A fourth element, specifying the ``gil_disabled`` flag (i.e. free + threaded python), is added and is optional. If not specified, the value is + ``OFF``. - The ``Python_FIND_ABI`` variable is a 3-tuple specifying, in that order, - ``pydebug`` (``d``), ``pymalloc`` (``m``) and ``unicode`` (``u``) flags. Each element can be set to one of the following: * ``ON``: Corresponding flag is selected. * ``OFF``: Corresponding flag is not selected. * ``ANY``: The two possibilities (``ON`` and ``OFF``) will be searched. - From this 3-tuple, various ABIs will be searched starting from the most - specialized to the most general. Moreover, ``debug`` versions will be - searched **after** ``non-debug`` ones. + .. note:: + + If ``Python3_FIND_ABI`` is not defined, any ABI, excluding the + ``gil_disabled`` flag, will be searched. + + From this 4-tuple, various ABIs will be searched starting from the most + specialized to the most general. Moreover, when ``ANY`` is specified for + ``pydebug`` and ``gil_disabled``, ``debug`` and ``free threaded`` versions + will be searched **after** ``non-debug`` and ``non-gil-disabled`` ones. For example, if we have:: - set (Python_FIND_ABI "ON" "ANY" "ANY") + set (Python_FIND_ABI "ON" "ANY" "ANY" "ON") The following flags combinations will be appended, in that order, to the - artifact names: ``dmu``, ``dm``, ``du``, and ``d``. + artifact names: ``tdmu``, ``tdm``, ``tdu``, and ``td``. And to search any possible ABIs:: - set (Python_FIND_ABI "ANY" "ANY" "ANY") + set (Python_FIND_ABI "ANY" "ANY" "ANY" "ANY") The following combinations, in that order, will be used: ``mu``, ``m``, - ``u``, ````, ``dmu``, ``dm``, ``du`` and ``d``. + ``u``, ````, ``dmu``, ``dm``, ``du``, ``d``, ``tmu``, ``tm``, ``tu``, + ``t``, ``tdmu``, ``tdm``, ``tdu``, and ``td``. .. note:: - This hint is useful only on ``POSIX`` systems. So, on ``Windows`` systems, + This hint is useful only on ``POSIX`` systems except for the + ``gil_disabled`` flag. So, on ``Windows`` systems, when ``Python_FIND_ABI`` is defined, ``Python`` distributions from - `python.org `_ will be found only if value for - each flag is ``OFF`` or ``ANY``. + `python.org `_ will be found only if the value for + each flag is ``OFF`` or ``ANY`` except for the fourth one + (``gil_disabled``). ``Python_FIND_STRATEGY`` .. versionadded:: 3.15 @@ -335,6 +378,8 @@ Hints constraints is founded. This is the default if policy :policy:`CMP0094` is set to ``NEW``. + See also ``Python_FIND_UNVERSIONED_NAMES``. + ``Python_FIND_REGISTRY`` .. versionadded:: 3.13 @@ -442,6 +487,8 @@ Hints This is the default. * ``NEVER``: The generic name are not searched at all. + See also ``Python_FIND_STRATEGY``. + Artifacts Specification ^^^^^^^^^^^^^^^^^^^^^^^ @@ -543,6 +590,10 @@ If the library type is not specified, ``MODULE`` is assumed. When option ``WITH_SOABI`` is also specified, the module suffix will include the ``Python_SOSABI`` value, if any. + +.. versionadded:: 3.30 + For ``MODULE`` type, the :prop_tgt:`DEBUG_POSTFIX` target property is + initialized with the value of ``Python_DEBUG_POSTFIX`` variable if defined. #]=======================================================================] diff --git a/config/FindPython/Support.cmake b/config/FindPython/Support.cmake index b56f6716..e0bdbc54 100644 --- a/config/FindPython/Support.cmake +++ b/config/FindPython/Support.cmake @@ -20,6 +20,8 @@ cmake_policy (SET CMP0057 NEW) cmake_policy (SET CMP0124 NEW) # registry view behavior cmake_policy (SET CMP0134 NEW) +# file(STRINGS) with REGEX updates CMAKE_MATCH_ +cmake_policy(SET CMP0159 NEW) if (NOT DEFINED _PYTHON_PREFIX) message (FATAL_ERROR "FindPython: INTERNAL ERROR") @@ -28,7 +30,7 @@ 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.13 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) + set(_${_PYTHON_PREFIX}_VERSIONS 3.14 3.13 3.12 3.11 3.10 3.9 3.8 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() @@ -192,28 +194,25 @@ function (_PYTHON_GET_REGISTRIES _PYTHON_PGR_REGISTRY_PATHS) if (implementation STREQUAL "CPython") foreach (version IN LISTS _PGR_VERSION) string (REPLACE "." "" version_no_dots ${version}) - list (APPEND registries - [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath] - [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath]) + list (TRANSFORM _${_PYTHON_PREFIX}_ARCH REPLACE "^(.+)$" "[HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-\\1/InstallPath]" OUTPUT_VARIABLE reg_paths) + list (APPEND registries ${reg_paths}) if (version VERSION_GREATER_EQUAL "3.5") # cmake_host_system_information is not usable in bootstrap get_filename_component (arch "[HKEY_CURRENT_USER\\Software\\Python\\PythonCore\\${version};SysArchitecture]" NAME) - if (arch MATCHES "(${_${_PYTHON_PREFIX}_ARCH}|${_${_PYTHON_PREFIX}_ARCH2})bit") - list (APPEND registries - [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath]) + string (REPLACE "bit" "" arch "${arch}") + if (arch IN_LIST _${_PYTHON_PREFIX}_ARCH) + list (APPEND registries [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath]) endif() else() - list (APPEND registries - [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath]) - endif() - list (APPEND registries - [HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath] - [HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath] - [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath] - [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath] - [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}/InstallPath] - [HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH}/InstallPath] - [HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-${_${_PYTHON_PREFIX}_ARCH2}/InstallPath]) + list (APPEND registries [HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}/InstallPath]) + endif() + list (TRANSFORM _${_PYTHON_PREFIX}_ARCH REPLACE "^(.+)$" "[HKEY_CURRENT_USER/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-\\1/InstallPath]" OUTPUT_VARIABLE reg_paths) + list (APPEND registries ${reg_paths}) + list (TRANSFORM _${_PYTHON_PREFIX}_ARCH REPLACE "^(.+)$" "[HKEY_CURRENT_USER/SOFTWARE/Python/PythonCore/${version}-\\1/InstallPath]" OUTPUT_VARIABLE reg_paths) + list (APPEND registries ${reg_paths}) + list (APPEND registries [HKEY_LOCAL_MACHINE/SOFTWARE/Python/PythonCore/${version}/InstallPath]) + list (TRANSFORM _${_PYTHON_PREFIX}_ARCH REPLACE "^(.+)$" "[HKEY_LOCAL_MACHINE/SOFTWARE/Python/ContinuumAnalytics/Anaconda${version_no_dots}-\\1/InstallPath]" OUTPUT_VARIABLE reg_paths) + list (APPEND registries ${reg_paths}) endforeach() elseif (implementation STREQUAL "IronPython") foreach (version IN LISTS _PGR_VERSION) @@ -226,18 +225,24 @@ function (_PYTHON_GET_REGISTRIES _PYTHON_PGR_REGISTRY_PATHS) endfunction() -function (_PYTHON_GET_ABIFLAGS _PGABIFLAGS) - set (abiflags) - list (GET _${_PYTHON_PREFIX}_FIND_ABI 0 pydebug) - list (GET _${_PYTHON_PREFIX}_FIND_ABI 1 pymalloc) - list (GET _${_PYTHON_PREFIX}_FIND_ABI 2 unicode) +function (_PYTHON_GET_ABIFLAGS _PGA_FIND_ABI _PGABIFLAGS) + set (abiflags "") + list (GET _PGA_FIND_ABI 0 pydebug) + list (GET _PGA_FIND_ABI 1 pymalloc) + list (GET _PGA_FIND_ABI 2 unicode) + list (LENGTH _PGA_FIND_ABI find_abi_length) + if (find_abi_length GREATER 3) + list (GET _PGA_FIND_ABI 3 gil) + else() + set (gil "OFF") + endif() if (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ANY") - set (abiflags "mu" "m" "u" "") + set (abiflags "mu" "m" "u" "") elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "ON") set (abiflags "mu" "u") elseif (pymalloc STREQUAL "ANY" AND unicode STREQUAL "OFF") - set (abiflags "m" "") + set (abiflags "m" "") elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY") set (abiflags "mu" "m") elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ON") @@ -245,7 +250,7 @@ function (_PYTHON_GET_ABIFLAGS _PGABIFLAGS) elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "OFF") set (abiflags "m") elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY") - set (abiflags "u" "") + set (abiflags "u" "") elseif (pymalloc STREQUAL "OFF" AND unicode STREQUAL "ON") set (abiflags "u") endif() @@ -262,10 +267,26 @@ function (_PYTHON_GET_ABIFLAGS _PGABIFLAGS) list (TRANSFORM flags PREPEND "d") list (APPEND abiflags "${flags}") else() - set (abiflags "" "d") + set (abiflags "" "d") endif() endif() + if (gil STREQUAL "ON") + if (abiflags) + list (TRANSFORM abiflags PREPEND "t") + else() + set (abiflags "t") + endif() + elseif (gil STREQUAL "ANY") + if (abiflags) + set (flags "${abiflags}") + list (TRANSFORM flags PREPEND "t") + list (APPEND abiflags "${flags}") + else() + set (abiflags "" "t") + endif() + endif() + list (TRANSFORM abiflags REPLACE "^(.+)$" "\\1") set (${_PGABIFLAGS} "${abiflags}" PARENT_SCOPE) endfunction() @@ -276,11 +297,8 @@ function (_PYTHON_GET_PATH_SUFFIXES _PYTHON_PGPS_PATH_SUFFIXES) set (_PGPS_IMPLEMENTATIONS ${_${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS}) endif() - if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS) - set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}") - else() - set (abi "mu" "m" "u" "") - endif() + set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}") + list (TRANSFORM abi REPLACE "^$" "") set (path_suffixes) @@ -361,30 +379,36 @@ function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES) foreach (implementation IN LISTS _PGN_IMPLEMENTATIONS) if (implementation STREQUAL "CPython") if (_PGN_INTERPRETER AND _${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES STREQUAL "FIRST") - list (APPEND names python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python) + if (_PGN_DEBUG) + list (APPEND names python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}_d python_d) + else() + list (APPEND names python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python) + endif() endif() foreach (version IN LISTS _PGN_VERSION) if (_PGN_WIN32) - string (REPLACE "." "" version_no_dots ${version}) - - set (name python${version_no_dots}) + if (_PGN_INTERPRETER) + set (name_version ${version}) + else() + string (REPLACE "." "" name_version ${version}) + endif() + set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}") + list (TRANSFORM abi REPLACE "^$" "") + if (abi) + set (abinames "${abi}") + list (TRANSFORM abinames PREPEND "python${name_version}") + else() + set (abinames "python${name_version}") + endif() if (_PGN_DEBUG) - string (APPEND name "_d") + list (TRANSFORM abinames APPEND "_d") endif() - - list (APPEND names "${name}") + list (APPEND names ${abinames}) endif() if (_PGN_POSIX) - if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS) - set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}") - else() - if (_PGN_INTERPRETER OR _PGN_CONFIG) - set (abi "") - else() - set (abi "mu" "m" "u" "") - endif() - endif() + set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}") + list (TRANSFORM abi REPLACE "^$" "") if (abi) if (_PGN_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) @@ -413,7 +437,11 @@ function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES) endif() endforeach() if (_PGN_INTERPRETER AND _${_PYTHON_PREFIX}_FIND_UNVERSIONED_NAMES STREQUAL "LAST") - list (APPEND names python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python) + if (_PGN_DEBUG) + list (APPEND names python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR}_d python_d) + else() + list (APPEND names python${_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR} python) + endif() endif() elseif (implementation STREQUAL "IronPython") if (_PGN_INTERPRETER) @@ -459,7 +487,7 @@ endfunction() function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) unset (${_PYTHON_PGCV_VALUE} PARENT_SCOPE) - if (NOT NAME MATCHES "^(PREFIX|ABIFLAGS|CONFIGDIR|INCLUDES|LIBS|SOABI|SOSABI)$") + if (NOT NAME MATCHES "^(PREFIX|ABIFLAGS|CONFIGDIR|INCLUDES|LIBS|SOABI|SOSABI|POSTFIX)$") return() endif() @@ -477,7 +505,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) set (config_flag "--${NAME}") endif() string (TOLOWER "${config_flag}" config_flag) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" ${config_flag} + execute_process (COMMAND ${_${_PYTHON_PREFIX}_CONFIG_LAUNCHER} ${config_flag} RESULT_VARIABLE _result OUTPUT_VARIABLE _values ERROR_QUIET @@ -495,15 +523,18 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) if (_values MATCHES "^(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.so|\\.pyd)$") set(_values "") else() - string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}") + string (REGEX REPLACE "^([.-]|_d\\.)(.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\2" _values "${_values}") endif() endif() endif() + if (NAME STREQUAL "ABIFLAGS" AND NOT _values) + set (_values "") + endif() endif() if (_${_PYTHON_PREFIX}_EXECUTABLE AND NOT CMAKE_CROSSCOMPILING) if (NAME STREQUAL "PREFIX") - execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.PREFIX,sysconfig.EXEC_PREFIX,sysconfig.BASE_EXEC_PREFIX]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_config_var('base') or '', sysconfig.get_config_var('installed_base') or '']))" + execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_config_var('base') or '', sysconfig.get_config_var('installed_base') or '']))\nexcept Exception:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.PREFIX,sysconfig.EXEC_PREFIX,sysconfig.BASE_EXEC_PREFIX]))" RESULT_VARIABLE _result OUTPUT_VARIABLE _values ERROR_QUIET @@ -520,7 +551,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) set (_scheme "posix_prefix") endif() execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_python_inc(plat_specific=True),sysconfig.get_python_inc(plat_specific=False)]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_path('platinclude'),sysconfig.get_path('platinclude','${_scheme}'),sysconfig.get_path('include'),sysconfig.get_path('include','${_scheme}')]))" + "import sys\ntry:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_path('platinclude'),sysconfig.get_path('platinclude','${_scheme}'),sysconfig.get_path('include'),sysconfig.get_path('include','${_scheme}')]))\nexcept Exception:\n from distutils import sysconfig\n 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 @@ -533,7 +564,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) elseif (NAME STREQUAL "SOABI") # first step: compute SOABI form EXT_SUFFIX config variable execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(sysconfig.get_config_var('EXT_SUFFIX') or '')\nexcept Exception:\n import sysconfig;sys.stdout.write(sysconfig.get_config_var('EXT_SUFFIX') or '')" + "import sys\ntry:\n import sysconfig\n sys.stdout.write(sysconfig.get_config_var('EXT_SUFFIX') or '')\nexcept Exception:\n from distutils import sysconfig;sys.stdout.write(sysconfig.get_config_var('EXT_SUFFIX') or '')" RESULT_VARIABLE _result OUTPUT_VARIABLE _values ERROR_QUIET @@ -546,7 +577,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) if (_values MATCHES "^(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.so|\\.pyd)$") set(_values "") else() - string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}") + string (REGEX REPLACE "^([.-]|_d\\.)(.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\2" _values "${_values}") endif() endif() endif() @@ -554,7 +585,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) # second step: use SOABI or SO config variables as fallback if (NOT _values) execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('SO') or '']))\nexcept Exception:\n import sysconfig;sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('SO') or '']))" + "import sys\ntry:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('SO') or '']))\nexcept Exception:\n from distutils import sysconfig;sys.stdout.write(';'.join([sysconfig.get_config_var('SOABI') or '',sysconfig.get_config_var('SO') or '']))" RESULT_VARIABLE _result OUTPUT_VARIABLE _soabi ERROR_QUIET @@ -573,7 +604,7 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) if (_values MATCHES "^(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.so|\\.pyd)$") set(_values "") else() - string (REGEX REPLACE "^[.-](.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}") + string (REGEX REPLACE "^([.-]|_d\\.)(.+)(${CMAKE_SHARED_LIBRARY_SUFFIX}|\\.(so|pyd))$" "\\1" _values "${_values}") endif() endif() endif() @@ -589,13 +620,31 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) else() string (REGEX REPLACE "^\\.(.+)\\.[^.]+$" "\\1" _values "${_values}") endif() + elseif (NAME STREQUAL "POSTFIX") + if (WIN32 AND _${_PYTHON_PREFIX}_LIBRARY_DEBUG MATCHES "_d${CMAKE_IMPORT_LIBRARY_SUFFIX}$") + set (_values "_d") + endif() + elseif (NAME STREQUAL "ABIFLAGS" AND WIN32) + # config var ABIFLAGS does not exist, check GIL specific variable + execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c + "import sys; import sysconfig; sys.stdout.write(str(sysconfig.get_config_var('Py_GIL_DISABLED')))" + RESULT_VARIABLE _result + OUTPUT_VARIABLE _values + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (result OR NOT _values EQUAL "1") + # assume ABI is not supported or GIL is set + set (_values "") + else() + set (_values "t") + endif() else() set (config_flag "${NAME}") if (NAME STREQUAL "CONFIGDIR") set (config_flag "LIBPL") endif() execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys\ntry:\n from distutils import sysconfig\n sys.stdout.write(sysconfig.get_config_var('${config_flag}'))\nexcept Exception:\n import sysconfig\n sys.stdout.write(sysconfig.get_config_var('${config_flag}'))" + "import sys\ntry:\n import sysconfig\n sys.stdout.write(sysconfig.get_config_var('${config_flag}'))\nexcept Exception:\n from distutils import sysconfig\n sys.stdout.write(sysconfig.get_config_var('${config_flag}'))" RESULT_VARIABLE _result OUTPUT_VARIABLE _values ERROR_QUIET @@ -603,10 +652,13 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) if (_result) unset (_values) endif() + if (NAME STREQUAL "ABIFLAGS" AND NOT _values) + set (_values "") + endif() endif() endif() - if (NAME STREQUAL "ABIFLAGS" OR NAME STREQUAL "SOABI" OR NAME STREQUAL "SOSABI") + if (NAME STREQUAL "ABIFLAGS" OR NAME STREQUAL "SOABI" OR NAME STREQUAL "SOSABI" OR NAME STREQUAL "POSTFIX") set (${_PYTHON_PGCV_VALUE} "${_values}" PARENT_SCOPE) return() endif() @@ -639,26 +691,27 @@ function (_PYTHON_GET_VERSION) unset (${_PGV_PREFIX}VERSION_PATCH PARENT_SCOPE) unset (${_PGV_PREFIX}ABI PARENT_SCOPE) + unset (abi) + if (_PGV_LIBRARY) # retrieve version and abi from library name if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE) get_filename_component (library_name "${_${_PYTHON_PREFIX}_LIBRARY_RELEASE}" NAME) # extract version from library name - if (library_name MATCHES "python([23])([0-9]+)") + if (library_name MATCHES "python([23])([0-9]+)([tdmu]*)") 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 (library_name MATCHES "python([23])\\.([0-9]+)([dmu]*)") + set (abi "${CMAKE_MATCH_3}") + elseif (library_name MATCHES "python([23])\\.([0-9]+)([tdmu]*)") 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 "${CMAKE_MATCH_3}" PARENT_SCOPE) + set (abi "${CMAKE_MATCH_3}") elseif (library_name MATCHES "pypy([23])\\.([0-9]+)-c") 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 (library_name MATCHES "pypy(3)?-c") set (version "${CMAKE_MATCH_1}") # try to pick-up a more precise version from the path @@ -674,7 +727,6 @@ function (_PYTHON_GET_VERSION) set (${_PGV_PREFIX}VERSION_MAJOR "2" PARENT_SCOPE) set (${_PGV_PREFIX}VERSION "2" PARENT_SCOPE) endif() - set (${_PGV_PREFIX}ABI "" PARENT_SCOPE) endif() endif() elseif (_PGV_SABI_LIBRARY) @@ -682,14 +734,13 @@ function (_PYTHON_GET_VERSION) if (_${_PYTHON_PREFIX}_SABI_LIBRARY_RELEASE) get_filename_component (library_name "${_${_PYTHON_PREFIX}_SABI_LIBRARY_RELEASE}" NAME) # extract version from library name - if (library_name MATCHES "python([23])([dmu]*)") + if (library_name MATCHES "python([23])([tdmu]*)") set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE) set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}" PARENT_SCOPE) - set (${_PGV_PREFIX}ABI "${CMAKE_MATCH_2}" PARENT_SCOPE) + set (abi "${CMAKE_MATCH_2}") elseif (library_name MATCHES "pypy([23])-c") set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE) set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}" PARENT_SCOPE) - set (${_PGV_PREFIX}ABI "" PARENT_SCOPE) elseif (library_name MATCHES "pypy-c") # try to pick-up a more precise version from the path get_filename_component (library_dir "${_${_PYTHON_PREFIX}_SABI_LIBRARY_RELEASE}" DIRECTORY) @@ -697,7 +748,6 @@ function (_PYTHON_GET_VERSION) set (${_PGV_PREFIX}VERSION_MAJOR "${CMAKE_MATCH_1}" PARENT_SCOPE) set (${_PGV_PREFIX}VERSION "${CMAKE_MATCH_1}" PARENT_SCOPE) endif() - set (${_PGV_PREFIX}ABI "" PARENT_SCOPE) endif() endif() else() @@ -719,48 +769,84 @@ 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)") - set (abi) - if (config MATCHES "#[ ]*define[ ]+MS_WIN32") - # ABI not used on Windows - set (abi "") + set (config_flags "Py_GIL_DISABLED|Py_DEBUG|Py_UNICODE_SIZE|MS_WIN32") + if ("${version_major}.${version_minor}" VERSION_LESS "3.8") + # pymalloc is not the default. Must be part of the name signature + string (APPEND config_flags "|WITH_PYMALLOC") + endif() + file (STRINGS "${_${_PYTHON_PREFIX}_INCLUDE_DIR}/pyconfig.h" config REGEX "(${config_flags})") + if (config MATCHES "(^|;)[ ]*#[ ]*define[ ]+MS_WIN32") + # same header is used regardless abi, so set is as + set (abi "") else() if (NOT config) # pyconfig.h can be a wrapper to a platform specific pyconfig.h # In this case, try to identify ABI from include directory - if (_${_PYTHON_PREFIX}_INCLUDE_DIR MATCHES "python${version_major}\\.${version_minor}+([dmu]*)") + if (_${_PYTHON_PREFIX}_INCLUDE_DIR MATCHES "python${version_major}\\.${version_minor}+([tdmu]*)") set (abi "${CMAKE_MATCH_1}") - else() - set (abi "") endif() else() - if (config MATCHES "#[ ]*define[ ]+Py_DEBUG[ ]+1") + if (config MATCHES "(^|;)[ ]*#[ ]*define[ ]+Py_GIL_DISABLED[ ]+1") + string (APPEND abi "t") + endif() + if (config MATCHES "(^|;)[ ]*#[ ]*define[ ]+Py_DEBUG[ ]+1") string (APPEND abi "d") endif() - if (config MATCHES "#[ ]*define[ ]+WITH_PYMALLOC[ ]+1") + if (config MATCHES "(^|;)[ ]*#[ ]*define[ ]+WITH_PYMALLOC[ ]+1") string (APPEND abi "m") endif() - if (config MATCHES "#[ ]*define[ ]+Py_UNICODE_SIZE[ ]+4") + if (config MATCHES "(^|;)[ ]*#[ ]*define[ ]+Py_UNICODE_SIZE[ ]+4") string (APPEND abi "u") endif() endif() - set (${_PGV_PREFIX}ABI "${abi}" PARENT_SCOPE) endif() - else() - # ABI not supported - set (${_PGV_PREFIX}ABI "" PARENT_SCOPE) endif() endif() endif() + if (NOT abi) + set (abi "") + endif() + set (${_PGV_PREFIX}ABI "${abi}" PARENT_SCOPE) endfunction() function (_PYTHON_GET_LAUNCHER _PYTHON_PGL_NAME) - cmake_parse_arguments (PARSE_ARGV 1 _PGL "INTERPRETER;COMPILER" "" "") + cmake_parse_arguments (PARSE_ARGV 1 _PGL "INTERPRETER;COMPILER" "CONFIG" "") unset (${_PYTHON_PGL_NAME} PARENT_SCOPE) if ((_PGL_INTERPRETER AND NOT _${_PYTHON_PREFIX}_EXECUTABLE) - OR (_PGL_COMPILER AND NOT _${_PYTHON_PREFIX}_COMPILER)) + OR (_PGL_COMPILER AND NOT _${_PYTHON_PREFIX}_COMPILER) + OR (_PGL_CONFIG AND NOT _${_PYTHON_PREFIX}_CONFIG)) + return() + endif() + + if (_PGL_CONFIG) + # default config script can be launched directly + set (${_PYTHON_PGL_NAME} "${_${_PYTHON_PREFIX}_CONFIG}" PARENT_SCOPE) + + if (NOT MINGW) + return() + endif() + # on MINGW environment, python-config script may require bash to be launched + execute_process (COMMAND cygpath.exe -u "${_${_PYTHON_PREFIX}_CONFIG}" + RESULT_VARIABLE _result + OUTPUT_VARIABLE _config + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + if (_result) + # impossible to convert path, keep default config + return() + endif() + execute_process (COMMAND bash.exe "${_config}" --prefix + RESULT_VARIABLE _result + OUTPUT_QUIET + ERROR_QUIET) + if (_result) + # fail to execute through bash, keep default config + return() + endif() + + set(${_PYTHON_PGL_NAME} bash.exe "${_config}" PARENT_SCOPE) return() endif() @@ -773,7 +859,7 @@ function (_PYTHON_GET_LAUNCHER _PYTHON_PGL_NAME) AND ext STREQUAL ".exe") set (${_PYTHON_PGL_NAME} "${${_PYTHON_PREFIX}_DOTNET_LAUNCHER}" PARENT_SCOPE) endif() - else() + elseif (_PGL_COMPILER) get_filename_component (name "${_${_PYTHON_PREFIX}_COMPILER}" NAME) get_filename_component (ext "${_${_PYTHON_PREFIX}_COMPILER}" LAST_EXT) if (name IN_LIST _${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_NAMES @@ -787,6 +873,7 @@ endfunction() function (_PYTHON_VALIDATE_INTERPRETER) if (NOT _${_PYTHON_PREFIX}_EXECUTABLE) + unset (_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG CACHE) return() endif() @@ -796,23 +883,17 @@ function (_PYTHON_VALIDATE_INTERPRETER) # interpreter does not exist anymore set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot find the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + if (WIN32 AND DEFINED CACHE{_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG}) + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE_DEBUG-NOTFOUND") + endif() return() endif() - _python_get_launcher (launcher INTERPRETER) + _python_get_launcher (_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER INTERPRETER) # validate ABI compatibility if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI) - execute_process (COMMAND ${launcher} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys; sys.stdout.write(sys.abiflags)" - RESULT_VARIABLE result - OUTPUT_VARIABLE abi - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (result) - # assume ABI is not supported - set (abi "") - endif() + _python_get_config_var (abi ABIFLAGS) if (NOT abi IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # incompatible ABI set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong ABI for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") @@ -823,7 +904,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) if (_PVI_IN_RANGE OR _PVI_VERSION) # retrieve full version - execute_process (COMMAND ${launcher} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c + execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))" RESULT_VARIABLE result OUTPUT_VARIABLE version @@ -833,6 +914,9 @@ function (_PYTHON_VALIDATE_INTERPRETER) # interpreter is not usable set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + if (WIN32 AND DEFINED CACHE{_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG}) + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE_DEBUG-NOTFOUND") + endif() return() endif() @@ -858,6 +942,9 @@ function (_PYTHON_VALIDATE_INTERPRETER) # interpreter has wrong version set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + if (WIN32 AND DEFINED CACHE{_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG}) + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE_DEBUG-NOTFOUND") + endif() return() else() # check that version is OK @@ -867,6 +954,9 @@ function (_PYTHON_VALIDATE_INTERPRETER) OR NOT version VERSION_GREATER_EQUAL _PVI_VERSION) set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + if (WIN32 AND DEFINED CACHE{_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG}) + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE_DEBUG-NOTFOUND") + endif() return() endif() endif() @@ -879,6 +969,9 @@ function (_PYTHON_VALIDATE_INTERPRETER) # interpreter has invalid version set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + if (WIN32 AND DEFINED CACHE{_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG}) + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE_DEBUG-NOTFOUND") + endif() return() endif() endif() @@ -887,7 +980,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) 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 ${launcher} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c + execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys; sys.stdout.write(str(sys.version_info[0]))" RESULT_VARIABLE result OUTPUT_VARIABLE version @@ -901,6 +994,9 @@ function (_PYTHON_VALIDATE_INTERPRETER) set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong major version for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") endif() set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + if (WIN32 AND DEFINED CACHE{_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG}) + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE_DEBUG-NOTFOUND") + endif() return() endif() endif() @@ -911,7 +1007,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) OR "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) AND NOT CMAKE_CROSSCOMPILING) # In this case, interpreter must have same architecture as environment - execute_process (COMMAND ${launcher} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c + execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys, struct; sys.stdout.write(str(struct.calcsize(\"P\")))" RESULT_VARIABLE result OUTPUT_VARIABLE size @@ -925,8 +1021,41 @@ function (_PYTHON_VALIDATE_INTERPRETER) set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") endif() set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + if (WIN32 AND DEFINED CACHE{_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG}) + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE_DEBUG-NOTFOUND") + endif() return() endif() + + if (WIN32) + # In this case, check if the interpreter is compatible with the target processor architecture + if (NOT CMAKE_GENERATOR_PLATFORM AND CMAKE_SYSTEM_PROCESSOR MATCHES "ARM" OR CMAKE_GENERATOR_PLATFORM MATCHES "ARM") + set(target_arm TRUE) + else() + set(target_arm FALSE) + endif() + execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c + "import sys, sysconfig; sys.stdout.write(sysconfig.get_platform())" + RESULT_VARIABLE result + OUTPUT_VARIABLE platform + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE) + string(TOUPPER "${platform}" platform) + if (result OR ((target_arm AND NOT platform MATCHES "ARM") OR + (NOT target_arm AND platform MATCHES "ARM"))) + # interpreter not usable or has wrong architecture + if (result) + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Cannot use the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") + else() + set_property (CACHE _${_PYTHON_PREFIX}_Interpreter_REASON_FAILURE PROPERTY VALUE "Wrong architecture for the interpreter \"${_${_PYTHON_PREFIX}_EXECUTABLE}\"") + endif() + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE-NOTFOUND") + if (WIN32 AND DEFINED CACHE{_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG}) + set_property (CACHE _${_PYTHON_PREFIX}_EXECUTABLE_DEBUG PROPERTY VALUE "${_PYTHON_PREFIX}_EXECUTABLE_DEBUG-NOTFOUND") + endif() + return() + endif() + endif() endif() endfunction() @@ -957,7 +1086,7 @@ function (_PYTHON_VALIDATE_COMPILER) # retrieve python environment version from compiler set (working_dir "${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/PythonCompilerVersion.dir") - file (WRITE "${working_dir}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]]))\n") + file (WRITE "${working_dir}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]])); sys.stdout.flush()\n") execute_process (COMMAND ${launcher} "${_${_PYTHON_PREFIX}_COMPILER}" ${_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS} /target:exe /embed "${working_dir}/version.py" @@ -1049,7 +1178,7 @@ endfunction() function (_PYTHON_VALIDATE_LIBRARY) if (NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) - unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG) + unset (_${_PYTHON_PREFIX}_LIBRARY_DEBUG CACHE) return() endif() @@ -1116,7 +1245,7 @@ endfunction() function (_PYTHON_VALIDATE_SABI_LIBRARY) if (NOT _${_PYTHON_PREFIX}_SABI_LIBRARY_RELEASE) - unset (_${_PYTHON_PREFIX}_SABI_LIBRARY_DEBUG) + unset (_${_PYTHON_PREFIX}_SABI_LIBRARY_DEBUG CACHE) return() endif() @@ -1176,7 +1305,7 @@ function (_PYTHON_VALIDATE_INCLUDE_DIR) # 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) + if (NOT WIN32 AND DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT inc_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # incompatible ABI set_property (CACHE _${_PYTHON_PREFIX}_Development_INCLUDE_DIR_REASON_FAILURE PROPERTY VALUE "Wrong ABI for the directory \"${_${_PYTHON_PREFIX}_INCLUDE_DIR}\"") set_property (CACHE _${_PYTHON_PREFIX}_INCLUDE_DIR PROPERTY VALUE "${_PYTHON_PREFIX}_INCLUDE_DIR-NOTFOUND") @@ -1376,25 +1505,33 @@ endif() if (_${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR VERSION_LESS "3") # ABI not supported unset (_${_PYTHON_PREFIX}_FIND_ABI) - set (_${_PYTHON_PREFIX}_ABIFLAGS "") + set (_${_PYTHON_PREFIX}_ABIFLAGS "") else() unset (_${_PYTHON_PREFIX}_FIND_ABI) - unset (_${_PYTHON_PREFIX}_ABIFLAGS) if (DEFINED ${_PYTHON_PREFIX}_FIND_ABI) # normalization string (TOUPPER "${${_PYTHON_PREFIX}_FIND_ABI}" _${_PYTHON_PREFIX}_FIND_ABI) list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(TRUE|Y(ES)?|1)$" "ON") list (TRANSFORM _${_PYTHON_PREFIX}_FIND_ABI REPLACE "^(FALSE|N(O)?|0)$" "OFF") - if (NOT _${_PYTHON_PREFIX}_FIND_ABI MATCHES "^(ON|OFF|ANY);(ON|OFF|ANY);(ON|OFF|ANY)$") + if (NOT _${_PYTHON_PREFIX}_FIND_ABI MATCHES "^(ON|OFF|ANY);(ON|OFF|ANY);(ON|OFF|ANY)(;(ON|OFF|ANY))?$") message (AUTHOR_WARNING "Find${_PYTHON_PREFIX}: ${${_PYTHON_PREFIX}_FIND_ABI}: invalid value for '${_PYTHON_PREFIX}_FIND_ABI'. Ignore it") unset (_${_PYTHON_PREFIX}_FIND_ABI) endif() - _python_get_abiflags (_${_PYTHON_PREFIX}_ABIFLAGS) + _python_get_abiflags ("${${_PYTHON_PREFIX}_FIND_ABI}" _${_PYTHON_PREFIX}_ABIFLAGS) + else() + if (WIN32) + _python_get_abiflags ("OFF;OFF;OFF;OFF" _${_PYTHON_PREFIX}_ABIFLAGS) + else() + _python_get_abiflags ("ANY;ANY;ANY;OFF" _${_PYTHON_PREFIX}_ABIFLAGS) + endif() endif() endif() unset (${_PYTHON_PREFIX}_SOABI) unset (${_PYTHON_PREFIX}_SOSABI) +# Windows CPython implementation may be requiring a postfix in debug mode +unset (${_PYTHON_PREFIX}_DEBUG_POSTFIX) + # Define lookup strategy cmake_policy (GET CMP0094 _${_PYTHON_PREFIX}_LOOKUP_POLICY) if (_${_PYTHON_PREFIX}_LOOKUP_POLICY STREQUAL "NEW") @@ -1419,19 +1556,37 @@ if (CMAKE_SIZEOF_VOID_P) OR "Development.SABIModule" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS OR "Development.Embed" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # In this case, search only for 64bit or 32bit - set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH}) set (_${_PYTHON_PREFIX}_REGISTRY_VIEW REGISTRY_VIEW ${_${_PYTHON_PREFIX}_ARCH}) + if (WIN32 AND (NOT CMAKE_GENERATOR_PLATFORM AND CMAKE_SYSTEM_PROCESSOR MATCHES "ARM" + OR CMAKE_GENERATOR_PLATFORM MATCHES "ARM")) + # search exclusively ARM architecture: 64bit or 32bit + if (_${_PYTHON_PREFIX}_ARCH EQUAL 64) + set (_${_PYTHON_PREFIX}_ARCH ARM64) + else() + set (_${_PYTHON_PREFIX}_ARCH ARM) + endif() + endif() else() if (_${_PYTHON_PREFIX}_ARCH EQUAL "32") - set (_${_PYTHON_PREFIX}_ARCH2 64) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "ARM") + # search first ARM architectures: 32bit and then 64bit + list (PREPEND _${_PYTHON_PREFIX}_ARCH ARM ARM64) + endif() + list (APPEND _${_PYTHON_PREFIX}_ARCH 64) else() - set (_${_PYTHON_PREFIX}_ARCH2 32) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "ARM") + # search first ARM architectures: 64bit and then 32bit + list (PREPEND _${_PYTHON_PREFIX}_ARCH ARM64 ARM) + endif() + list (APPEND _${_PYTHON_PREFIX}_ARCH 32) endif() endif() else() # architecture unknown, search for both 64bit and 32bit - set (_${_PYTHON_PREFIX}_ARCH 64) - set (_${_PYTHON_PREFIX}_ARCH2 32) + set (_${_PYTHON_PREFIX}_ARCH 64 32) + if (CMAKE_SYSTEM_PROCESSOR MATCHES "ARM") + list (PREPEND _${_PYTHON_PREFIX}_ARCH ARM64 ARM) + endif() endif() # IronPython support @@ -1439,7 +1594,7 @@ unset (_${_PYTHON_PREFIX}_IRON_PYTHON_INTERPRETER_NAMES) unset (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_NAMES) unset (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS) if (CMAKE_SIZEOF_VOID_P) - if (_${_PYTHON_PREFIX}_ARCH EQUAL "32") + if (CMAKE_SIZEOF_VOID_P EQUAL "4") set (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS "/platform:x86") else() set (_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS "/platform:x64") @@ -1713,6 +1868,7 @@ endif() # first step, search for the interpreter if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS _${_PYTHON_PREFIX}_EXECUTABLE + _${_PYTHON_PREFIX}_EXECUTABLE_DEBUG _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES) if (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter) list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_EXECUTABLE) @@ -1725,6 +1881,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) unset (_${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES CACHE) endif() set (_${_PYTHON_PREFIX}_EXECUTABLE "${${_PYTHON_PREFIX}_EXECUTABLE}" CACHE INTERNAL "") + unset (_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG CACHE) 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}") @@ -1741,6 +1898,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) endif() else() unset (_${_PYTHON_PREFIX}_EXECUTABLE CACHE) + unset (_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG CACHE) endif() if (NOT _${_PYTHON_PREFIX}_EXECUTABLE) unset (_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE CACHE) @@ -2048,7 +2206,6 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 3 ${_PYTHON_PREFIX}_VERSION_PATCH) list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 4 _${_PYTHON_PREFIX}_ARCH) - set (_${_PYTHON_PREFIX}_ARCH2 ${_${_PYTHON_PREFIX}_ARCH}) list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 5 _${_PYTHON_PREFIX}_ABIFLAGS) list (GET _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES 6 ${_PYTHON_PREFIX}_SOABI) @@ -2069,16 +2226,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # 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}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys; sys.stdout.write(sys.abiflags)" - RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT - OUTPUT_VARIABLE _${_PYTHON_PREFIX}_ABIFLAGS - ERROR_QUIET - OUTPUT_STRIP_TRAILING_WHITESPACE) - if (_${_PYTHON_PREFIX}_RESULT) - # assunme ABI is not supported - set (_${_PYTHON_PREFIX}_ABIFLAGS "") - endif() + _python_get_config_var (_${_PYTHON_PREFIX}_ABIFLAGS ABIFLAGS) endif() if (${_PYTHON_PREFIX}_Interpreter_FOUND) @@ -2098,10 +2246,27 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) if (NOT _${_PYTHON_PREFIX}_RESULT) if (${_PYTHON_PREFIX}_IS64BIT) set (_${_PYTHON_PREFIX}_ARCH 64) - set (_${_PYTHON_PREFIX}_ARCH2 64) else() set (_${_PYTHON_PREFIX}_ARCH 32) - set (_${_PYTHON_PREFIX}_ARCH2 32) + endif() + endif() + + if (WIN32) + # check if architecture is Intel or ARM + execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c + "import sys; import sysconfig; sys.stdout.write(sysconfig.get_platform())" + RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT + OUTPUT_VARIABLE _${_PYTHON_PREFIX}_PLATFORM + ERROR_VARIABLE ${_PYTHON_PREFIX}_PLATFORM) + if (NOT _${_PYTHON_PREFIX}_RESULT) + string(TOUPPER "${_${_PYTHON_PREFIX}_PLATFORM}" _${_PYTHON_PREFIX}_PLATFORM) + if (_${_PYTHON_PREFIX}_PLATFORM MATCHES "ARM") + if (${_PYTHON_PREFIX}_IS64BIT) + set (_${_PYTHON_PREFIX}_ARCH ARM64) + else() + set (_${_PYTHON_PREFIX}_ARCH ARM) + endif() + endif() endif() endif() endif() @@ -2139,7 +2304,7 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # retrieve various package installation directories execute_process (COMMAND ${_${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c - "import sys\ntry:\n from distutils import sysconfig\n 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)]))\nexcept Exception:\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_path('stdlib'),sysconfig.get_path('platstdlib'),sysconfig.get_path('purelib'),sysconfig.get_path('platlib')]))" + "import sys\nif sys.version_info >= (3,10):\n import sysconfig\n sys.stdout.write(';'.join([sysconfig.get_path('stdlib'),sysconfig.get_path('platstdlib'),sysconfig.get_path('purelib'),sysconfig.get_path('platlib')]))\nelse:\n from distutils import sysconfig\n 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) @@ -2172,7 +2337,30 @@ if ("Interpreter" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) set (${_PYTHON_PREFIX}_EXECUTABLE "${_${_PYTHON_PREFIX}_EXECUTABLE}" CACHE FILEPATH "${_PYTHON_PREFIX} Interpreter") endif() + if (WIN32 AND _${_PYTHON_PREFIX}_EXECUTABLE AND "CPython" IN_LIST _${_PYTHON_PREFIX}_FIND_IMPLEMENTATIONS) + # search for debug interpreter + # use release interpreter location as a hint + _python_get_names (_${_PYTHON_PREFIX}_INTERPRETER_NAMES_DEBUG VERSION ${_${_PYTHON_PREFIX}_FIND_VERSIONS} IMPLEMENTATIONS CPython INTERPRETER WIN32 DEBUG) + get_filename_component (_${_PYTHON_PREFIX}_PATH "${_${_PYTHON_PREFIX}_EXECUTABLE}" DIRECTORY) + set (_${_PYTHON_PREFIX}_HINTS "${${_PYTHON_PREFIX}_ROOT_DIR}" ENV ${_PYTHON_PREFIX}_ROOT_DIR) + + find_program (_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG + NAMES ${_${_PYTHON_PREFIX}_INTERPRETER_NAMES_DEBUG} + NAMES_PER_DIR + HINTS "${_${_PYTHON_PREFIX}_PATH}" ${${_PYTHON_PREFIX}_HINTS} + NO_DEFAULT_PATH) + # second try including CMAKE variables to catch-up non conventional layouts + find_program (_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG + NAMES ${_${_PYTHON_PREFIX}_INTERPRETER_NAMES_DEBUG} + NAMES_PER_DIR + NO_SYSTEM_ENVIRONMENT_PATH + NO_CMAKE_SYSTEM_PATH) + endif() + set (${_PYTHON_PREFIX}_EXECUTABLE_DEBUG "${_${_PYTHON_PREFIX}_EXECUTABLE_DEBUG}") + set (${_PYTHON_PREFIX}_INTERPRETER "$,$,$>,${${_PYTHON_PREFIX}_EXECUTABLE_DEBUG},${${_PYTHON_PREFIX}_EXECUTABLE}>") + _python_mark_as_internal (_${_PYTHON_PREFIX}_EXECUTABLE + _${_PYTHON_PREFIX}_EXECUTABLE_DEBUG _${_PYTHON_PREFIX}_INTERPRETER_PROPERTIES _${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE) endif() @@ -2462,7 +2650,7 @@ if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS) # retrieve python environment version from compiler _python_get_launcher (_${_PYTHON_PREFIX}_COMPILER_LAUNCHER 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") + file (WRITE "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py" "import sys; sys.stdout.write('.'.join([str(x) for x in sys.version_info[:3]])); sys.stdout.flush()\n") execute_process (COMMAND ${_${_PYTHON_PREFIX}_COMPILER_LAUNCHER} "${_${_PYTHON_PREFIX}_COMPILER}" ${_${_PYTHON_PREFIX}_IRON_PYTHON_COMPILER_ARCH_FLAGS} /target:exe /embed "${_${_PYTHON_PREFIX}_VERSION_DIR}/version.py" @@ -2673,47 +2861,53 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS NO_DEFAULT_PATH) endif() + _python_get_launcher (_${_PYTHON_PREFIX}_CONFIG_LAUNCHER CONFIG "${_${_PYTHON_PREFIX}_CONFIG}") + if (_${_PYTHON_PREFIX}_CONFIG) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --help + execute_process (COMMAND ${_${_PYTHON_PREFIX}_CONFIG_LAUNCHER} --prefix RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE __${_PYTHON_PREFIX}_HELP - ERROR_QUIET + ERROR_VARIABLE __${_PYTHON_PREFIX}_HELP OUTPUT_STRIP_TRAILING_WHITESPACE) if (_${_PYTHON_PREFIX}_RESULT) # assume config tool is not usable unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + unset (_${_PYTHON_PREFIX}_CONFIG_LAUNCHER) endif() endif() if (_${_PYTHON_PREFIX}_CONFIG) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --abiflags + execute_process (COMMAND ${_${_PYTHON_PREFIX}_CONFIG_LAUNCHER} --abiflags RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE __${_PYTHON_PREFIX}_ABIFLAGS ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if (_${_PYTHON_PREFIX}_RESULT) # assume ABI is not supported - set (__${_PYTHON_PREFIX}_ABIFLAGS "") + set (__${_PYTHON_PREFIX}_ABIFLAGS "") endif() if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # Wrong ABI unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + unset (_${_PYTHON_PREFIX}_CONFIG_LAUNCHER) endif() endif() if (_${_PYTHON_PREFIX}_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) # check that config tool match library architecture - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir + execute_process (COMMAND ${_${_PYTHON_PREFIX}_CONFIG_LAUNCHER} --configdir RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if (_${_PYTHON_PREFIX}_RESULT) unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + unset (_${_PYTHON_PREFIX}_CONFIG_LAUNCHER) else() string(FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT) if (_${_PYTHON_PREFIX}_RESULT EQUAL -1) unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + unset (_${_PYTHON_PREFIX}_CONFIG_LAUNCHER) endif() endif() endif() @@ -2759,8 +2953,10 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS unset (_${_PYTHON_PREFIX}_CONFIG_NAMES) + _python_get_launcher (_${_PYTHON_PREFIX}_CONFIG_LAUNCHER CONFIG "${_${_PYTHON_PREFIX}_CONFIG}") + if (_${_PYTHON_PREFIX}_CONFIG) - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --help + execute_process (COMMAND ${_${_PYTHON_PREFIX}_CONFIG_LAUNCHER} --prefix RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE __${_PYTHON_PREFIX}_HELP ERROR_QUIET @@ -2768,6 +2964,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS if (_${_PYTHON_PREFIX}_RESULT) # assume config tool is not usable unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + unset (_${_PYTHON_PREFIX}_CONFIG_LAUNCHER) endif() endif() @@ -2775,35 +2972,38 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS continue() endif() - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --abiflags + execute_process (COMMAND ${_${_PYTHON_PREFIX}_CONFIG_LAUNCHER} --abiflags RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE __${_PYTHON_PREFIX}_ABIFLAGS ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if (_${_PYTHON_PREFIX}_RESULT) # assume ABI is not supported - set (__${_PYTHON_PREFIX}_ABIFLAGS "") + set (__${_PYTHON_PREFIX}_ABIFLAGS "") endif() if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # Wrong ABI unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + unset (_${_PYTHON_PREFIX}_CONFIG_LAUNCHER) continue() endif() if (_${_PYTHON_PREFIX}_CONFIG AND DEFINED CMAKE_LIBRARY_ARCHITECTURE) # check that config tool match library architecture - execute_process (COMMAND "${_${_PYTHON_PREFIX}_CONFIG}" --configdir + execute_process (COMMAND ${_${_PYTHON_PREFIX}_CONFIG_LAUNCHER} --configdir RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT OUTPUT_VARIABLE _${_PYTHON_PREFIX}_CONFIGDIR ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if (_${_PYTHON_PREFIX}_RESULT) unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + unset (_${_PYTHON_PREFIX}_CONFIG_LAUNCHER) continue() endif() string (FIND "${_${_PYTHON_PREFIX}_CONFIGDIR}" "${CMAKE_LIBRARY_ARCHITECTURE}" _${_PYTHON_PREFIX}_RESULT) if (_${_PYTHON_PREFIX}_RESULT EQUAL -1) unset (_${_PYTHON_PREFIX}_CONFIG CACHE) + unset (_${_PYTHON_PREFIX}_CONFIG_LAUNCHER) continue() endif() endif() @@ -3524,6 +3724,14 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_RELEASE _${_PYTHON_PREFIX}_RUNTIME_LIBRARY_DEBUG) endif() + + if (WIN32 AND _${_PYTHON_PREFIX}_LIBRARY_RELEASE MATCHES "t${CMAKE_IMPORT_LIBRARY_SUFFIX}$") + # On windows, header file is shared between the different implementations + # So Py_GIL_DISABLED should be set explicitly + set (${_PYTHON_PREFIX}_DEFINITIONS Py_GIL_DISABLED=1) + else() + unset (${_PYTHON_PREFIX}_DEFINITIONS) + endif() endif() if ("SABI_LIBRARY" IN_LIST _${_PYTHON_PREFIX}_FIND_DEVELOPMENT_ARTIFACTS) @@ -3553,6 +3761,14 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS _${_PYTHON_PREFIX}_RUNTIME_SABI_LIBRARY_RELEASE _${_PYTHON_PREFIX}_RUNTIME_SABI_LIBRARY_DEBUG) endif() + + if (WIN32 AND _${_PYTHON_PREFIX}_SABI_LIBRARY_RELEASE MATCHES "t${CMAKE_IMPORT_LIBRARY_SUFFIX}$") + # On windows, header file is shared between the different implementations + # So Py_GIL_DISABLED should be set explicitly + set (${_PYTHON_PREFIX}_DEFINITIONS Py_GIL_DISABLED=1) + else() + unset (${_PYTHON_PREFIX}_DEFINITIONS) + endif() endif() if (_${_PYTHON_PREFIX}_LIBRARY_RELEASE OR _${_PYTHON_PREFIX}_SABI_LIBRARY_RELEASE OR _${_PYTHON_PREFIX}_INCLUDE_DIR) @@ -3572,7 +3788,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS 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)) + OR (NOT WIN32 AND NOT _${_PYTHON_PREFIX}_INC_ABI IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS))) set (${_PYTHON_PREFIX}_Development.Module_FOUND FALSE) set (${_PYTHON_PREFIX}_Development.SABIModule_FOUND FALSE) set (${_PYTHON_PREFIX}_Development.Embed_FOUND FALSE) @@ -3627,6 +3843,10 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS _python_get_config_var (${_PYTHON_PREFIX}_SOSABI SOSABI) endif() + if (WIN32 AND NOT DEFINED ${_PYTHON_PREFIX}_DEBUG_POSTFIX) + _python_get_config_var (${_PYTHON_PREFIX}_DEBUG_POSTFIX POSTFIX) + endif() + _python_compute_development_signature (Module) _python_compute_development_signature (SABIModule) _python_compute_development_signature (Embed) @@ -3681,6 +3901,15 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte endif() endif() + # Workaround Intel MKL library outputting a message in stdout, which cause + # incorrect detection of numpy.get_include() and numpy.__version__ + # See https://github.com/numpy/numpy/issues/23775 and + # https://gitlab.kitware.com/cmake/cmake/-/issues/26240 + if(NOT DEFINED ENV{MKL_ENABLE_INSTRUCTIONS}) + set(_${_PYTHON_PREFIX}_UNSET_ENV_VAR_MKL_ENABLE_INSTRUCTIONS YES) + set(ENV{MKL_ENABLE_INSTRUCTIONS} "SSE4_2") + endif() + if (NOT _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR) execute_process(COMMAND ${${_PYTHON_PREFIX}_INTERPRETER_LAUNCHER} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c "import sys\ntry: import numpy; sys.stdout.write(numpy.get_include())\nexcept:pass\n" @@ -3721,6 +3950,12 @@ if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Inte set (${_PYTHON_PREFIX}_NumPy_FOUND FALSE) endif() + # Unset MKL_ENABLE_INSTRUCTIONS if set by us + if(DEFINED _${_PYTHON_PREFIX}_UNSET_ENV_VAR_MKL_ENABLE_INSTRUCTIONS) + unset(_${_PYTHON_PREFIX}_UNSET_ENV_VAR_MKL_ENABLE_INSTRUCTIONS) + unset(ENV{MKL_ENABLE_INSTRUCTIONS}) + endif() + if (${_PYTHON_PREFIX}_NumPy_FOUND) unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE CACHE) @@ -3773,11 +4008,27 @@ find_package_handle_standard_args (${_PYTHON_PREFIX} # Create imported targets and helper functions if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT") 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}") + AND ${_PYTHON_PREFIX}_Interpreter_FOUND) + if(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(${_PYTHON_PREFIX}_EXECUTABLE_DEBUG AND NOT TARGET ${_PYTHON_PREFIX}::InterpreterDebug) + add_executable (${_PYTHON_PREFIX}::InterpreterDebug IMPORTED) + set_property (TARGET ${_PYTHON_PREFIX}::InterpreterDebug + PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_EXECUTABLE_DEBUG}") + endif() + if(NOT TARGET ${_PYTHON_PREFIX}::InterpreterMultiConfig) + add_executable (${_PYTHON_PREFIX}::InterpreterMultiConfig IMPORTED) + set_property (TARGET ${_PYTHON_PREFIX}::InterpreterMultiConfig + PROPERTY IMPORTED_LOCATION "${${_PYTHON_PREFIX}_EXECUTABLE}") + if(${_PYTHON_PREFIX}_EXECUTABLE_DEBUG) + set_target_properties (${_PYTHON_PREFIX}::InterpreterMultiConfig + PROPERTIES IMPORTED_CONFIGURATIONS DEBUG + IMPORTED_LOCATION_DEBUG "${${_PYTHON_PREFIX}_EXECUTABLE_DEBUG}") + endif() + endif() endif() if ("Compiler" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS @@ -3815,6 +4066,12 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT") set_property (TARGET ${__name} PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIRS}") + if (${_PYTHON_PREFIX}_DEFINITIONS) + set_property (TARGET ${__name} + PROPERTY INTERFACE_COMPILE_DEFINITIONS "${${_PYTHON_PREFIX}_DEFINITIONS}") + endif() + + if (${_PYTHON_PREFIX}_${_PREFIX}LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_RUNTIME_${_PREFIX}LIBRARY_RELEASE) # System manage shared libraries in two parts: import and runtime if (${_PYTHON_PREFIX}_${_PREFIX}LIBRARY_RELEASE AND ${_PYTHON_PREFIX}_${_PREFIX}LIBRARY_DEBUG) @@ -3871,6 +4128,11 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT") set_property (TARGET ${__name} PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_INCLUDE_DIRS}") + if (${_PYTHON_PREFIX}_DEFINITIONS) + set_property (TARGET ${__name} + PROPERTY INTERFACE_COMPILE_DEFINITIONS "${${_PYTHON_PREFIX}_DEFINITIONS}") + endif() + # When available, enforce shared library generation with undefined symbols if (APPLE) set_property (TARGET ${__name} @@ -3989,6 +4251,9 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT") set_property (TARGET ${name} PROPERTY PREFIX "") if(CMAKE_SYSTEM_NAME STREQUAL "Windows") set_property (TARGET ${name} PROPERTY SUFFIX ".pyd") + if (${prefix}_DEBUG_POSTFIX) + set_property (TARGET ${name} PROPERTY DEBUG_POSTFIX "${${prefix}_DEBUG_POSTFIX}") + endif() endif() if (PYTHON_ADD_LIBRARY_WITH_SOABI) diff --git a/config/FindPython2.cmake b/config/FindPython2.cmake index 41d9b689..eb2b5a8d 100644 --- a/config/FindPython2.cmake +++ b/config/FindPython2.cmake @@ -71,9 +71,25 @@ This module defines the following :ref:`Imported Targets `: :prop_gbl:`CMAKE_ROLE` is ``PROJECT``. ``Python2::Interpreter`` - Python 2 interpreter. Target defined if component ``Interpreter`` is found. + Python 2 interpreter. This target is defined only if the ``Interpreter`` + component is found. +``Python2::InterpreterDebug`` + .. versionadded:: 3.30 + + Python 2 debug interpreter. This target is defined only if the + ``Interpreter`` component is found and the ``Python2_EXECUTABLE_DEBUG`` + variable is defined. The target is only defined on the ``Windows`` platform. + +``Python2::InterpreterMultiConfig`` + .. versionadded:: 3.30 + + Python 2 interpreter. The release or debug version of the interpreter will be + used, based on the context (platform, configuration). + This target is defined only if the ``Interpreter`` component is found + ``Python2::Compiler`` - Python 2 compiler. Target defined if component ``Compiler`` is found. + Python 2 compiler. This target is defined only if the ``Compiler`` component + is found. ``Python2::Module`` .. versionadded:: 3.15 @@ -101,6 +117,20 @@ This module will set the following variables in your project System has the Python 2 interpreter. ``Python2_EXECUTABLE`` Path to the Python 2 interpreter. +``Python2_EXECUTABLE_DEBUG`` + .. versionadded:: 3.30 + + Path to the debug Python 2 interpreter. It is only defined on the ``Windows`` + platform. + +``Python2_INTERPRETER`` + .. versionadded:: 3.30 + + Path to the Python 2 interpreter, defined as a + :manual:`generator expression ` selecting + the ``Python2_EXECUTABLE`` or ``Python2_EXECUTABLE_DEBUG`` variable based on + the context (platform, configuration). + ``Python2_INTERPRETER_ID`` A short string unique to the interpreter. Possible values include: * Python @@ -112,27 +142,23 @@ This module will set the following variables in your project ``Python2_STDLIB`` Standard platform independent installation directory. - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=True)`` - or else ``sysconfig.get_path('stdlib')``. + Information returned by ``sysconfig.get_path('stdlib')`` or else + ``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)`` - or else ``sysconfig.get_path('platstdlib')``. + Information returned by ``sysconfig.get_path('platstdlib')`` or else + ``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)`` - or else ``sysconfig.get_path('purelib')``. + Information returned by ``sysconfig.get_path('purelib')`` or else + ``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)`` - or else ``sysconfig.get_path('platlib')``. + Information returned by ``sysconfig.get_path('platlib')`` or else + ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)``. ``Python2_Compiler_FOUND`` System has the Python 2 compiler. ``Python2_COMPILER`` @@ -162,6 +188,12 @@ This module will set the following variables in your project ``Python2_INCLUDE_DIRS`` The Python 2 include directories. +``Python2_DEBUG_POSTFIX`` + .. versionadded.. 3.30 + + Postfix of debug python module. This variable can be used to define the + :prop_tgt:`DEBUG_POSTFIX` target property. + ``Python2_LINK_OPTIONS`` .. versionadded:: 3.19 @@ -234,6 +266,8 @@ Hints constraints is founded. This is the default if policy :policy:`CMP0094` is set to ``NEW``. + See also ``Python2_FIND_UNVERSIONED_NAMES``. + ``Python2_FIND_REGISTRY`` .. versionadded:: 3.13 @@ -341,6 +375,8 @@ Hints This is the default. * ``NEVER``: The generic name are not searched at all. + See also ``Python2_FIND_STRATEGY``. + Artifacts Specification ^^^^^^^^^^^^^^^^^^^^^^^ @@ -417,6 +453,10 @@ of Python module naming rules:: [ ...]) If library type is not specified, ``MODULE`` is assumed. + +.. versionadded:: 3.30 + For ``MODULE`` type, the :prop_tgt:`DEBUG_POSTFIX` target property is + initialized with the value of ``Python2_DEBUG_POSTFIX`` variable if defined. #]=======================================================================] diff --git a/config/FindPython3.cmake b/config/FindPython3.cmake index ae086e85..19b02246 100644 --- a/config/FindPython3.cmake +++ b/config/FindPython3.cmake @@ -78,9 +78,25 @@ This module defines the following :ref:`Imported Targets `: :prop_gbl:`CMAKE_ROLE` is ``PROJECT``. ``Python3::Interpreter`` - Python 3 interpreter. Target defined if component ``Interpreter`` is found. + Python 3 interpreter. This target is defined only if the ``Interpreter`` + component is found. +``Python3::InterpreterDebug`` + .. versionadded:: 3.30 + + Python 3 debug interpreter. This target is defined only if the + ``Interpreter`` component is found and the ``Python3_EXECUTABLE_DEBUG`` + variable is defined. The target is only defined on the ``Windows`` platform. + +``Python3::InterpreterMultiConfig`` + .. versionadded:: 3.30 + + Python 3 interpreter. The release or debug version of the interpreter will be + used, based on the context (platform, configuration). + This target is defined only if the ``Interpreter`` component is found + ``Python3::Compiler`` - Python 3 compiler. Target defined if component ``Compiler`` is found. + Python 3 compiler. This target is defined only if the ``Compiler`` component + is found. ``Python3::Module`` .. versionadded:: 3.15 @@ -115,6 +131,20 @@ This module will set the following variables in your project System has the Python 3 interpreter. ``Python3_EXECUTABLE`` Path to the Python 3 interpreter. +``Python3_EXECUTABLE_DEBUG`` + .. versionadded:: 3.30 + + Path to the debug Python 3 interpreter. It is only defined on ``Windows`` + platform. + +``Python3_INTERPRETER`` + .. versionadded:: 3.30 + + Path to the Python 3 interpreter, defined as a + :manual:`generator expression ` selecting + the ``Python3_EXECUTABLE`` or ``Python3_EXECUTABLE_DEBUG`` variable based on + the context (platform, configuration). + ``Python3_INTERPRETER_ID`` A short string unique to the interpreter. Possible values include: * Python @@ -126,38 +156,28 @@ This module will set the following variables in your project ``Python3_STDLIB`` Standard platform independent installation directory. - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=True)`` - or else ``sysconfig.get_path('stdlib')``. + Information returned by ``sysconfig.get_path('stdlib')``. ``Python3_STDARCH`` Standard platform dependent installation directory. - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=True)`` - or else ``sysconfig.get_path('platstdlib')``. + Information returned by ``sysconfig.get_path('platstdlib')``. ``Python3_SITELIB`` Third-party platform independent installation directory. - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=False,standard_lib=False)`` - or else ``sysconfig.get_path('purelib')``. + Information returned by ``sysconfig.get_path('purelib')``. ``Python3_SITEARCH`` Third-party platform dependent installation directory. - Information returned by - ``distutils.sysconfig.get_python_lib(plat_specific=True,standard_lib=False)`` - or else ``sysconfig.get_path('platlib')``. + Information returned by ``sysconfig.get_path('platlib')``. ``Python3_SOABI`` .. versionadded:: 3.17 Extension suffix for modules. - Information computed from ``distutils.sysconfig.get_config_var('EXT_SUFFIX')`` - or ``distutils.sysconfig.get_config_var('SOABI')`` or - ``python3-config --extension-suffix``. If package ``distutils.sysconfig`` is - not available, ``sysconfig.get_config_var('EXT_SUFFIX')`` or - ``sysconfig.get_config_var('SOABI')`` are used. + Information computed from ``sysconfig.get_config_var('EXT_SUFFIX')`` or + ``sysconfig.get_config_var('SOABI')`` or + ``python3-config --extension-suffix``. ``Python3_SOSABI`` .. versionadded:: 3.26 @@ -206,6 +226,17 @@ This module will set the following variables in your project The Python 3 include directories. +``Python3_DEFINITIONS`` + .. versionadded:: 3.30.3 + + The Python 3 preprocessor definitions. + +``Python3_DEBUG_POSTFIX`` + .. versionadded.. 3.30 + + Postfix of debug python module. This variable can be used to define the + :prop_tgt:`DEBUG_POSTFIX` target property. + ``Python3_LINK_OPTIONS`` .. versionadded:: 3.19 @@ -282,42 +313,54 @@ Hints This variable defines which ABIs, as defined in :pep:`3149`, should be searched. - .. note:: + The ``Python3_FIND_ABI`` variable is a 4-tuple specifying, in that order, + ``pydebug`` (``d``), ``pymalloc`` (``m``), ``unicode`` (``u``) and + ``gil_disabled`` (``t``) flags. - If ``Python3_FIND_ABI`` is not defined, any ABI will be searched. + .. versionadded:: 3.30 + A fourth element, specifying the ``gil_disabled`` flag (i.e. free + threaded python), is added and is optional. If not specified, the value is + ``OFF``. - The ``Python3_FIND_ABI`` variable is a 3-tuple specifying, in that order, - ``pydebug`` (``d``), ``pymalloc`` (``m``) and ``unicode`` (``u``) flags. Each element can be set to one of the following: * ``ON``: Corresponding flag is selected. * ``OFF``: Corresponding flag is not selected. * ``ANY``: The two possibilities (``ON`` and ``OFF``) will be searched. - From this 3-tuple, various ABIs will be searched starting from the most - specialized to the most general. Moreover, ``debug`` versions will be - searched **after** ``non-debug`` ones. + .. note:: + + If ``Python3_FIND_ABI`` is not defined, any ABI, excluding the + ``gil_disabled`` flag, will be searched. + + From this 4-tuple, various ABIs will be searched starting from the most + specialized to the most general. Moreover, when ``ANY`` is specified for + ``pydebug`` and ``gil_disabled``, ``debug`` and ``free threaded`` versions + will be searched **after** ``non-debug`` and ``non-gil-disabled`` ones. For example, if we have:: - set (Python3_FIND_ABI "ON" "ANY" "ANY") + set (Python3_FIND_ABI "ON" "ANY" "ANY" "ON") The following flags combinations will be appended, in that order, to the - artifact names: ``dmu``, ``dm``, ``du``, and ``d``. + artifact names: ``tdmu``, ``tdm``, ``tdu``, and ``td``. And to search any possible ABIs:: - set (Python3_FIND_ABI "ANY" "ANY" "ANY") + set (Python3_FIND_ABI "ANY" "ANY" "ANY" "ANY") The following combinations, in that order, will be used: ``mu``, ``m``, - ``u``, ````, ``dmu``, ``dm``, ``du`` and ``d``. + ``u``, ````, ``dmu``, ``dm``, ``du``, ``d``, ``tmu``, ``tm``, ``tu``, + ``t``, ``tdmu``, ``tdm``, ``tdu``, and ``td``. .. note:: - This hint is useful only on ``POSIX`` systems. So, on ``Windows`` systems, - when ``Python3_FIND_ABI`` is defined, ``Python`` distributions from - `python.org `_ will be found only if value for - each flag is ``OFF`` or ``ANY``. + This hint is useful only on ``POSIX`` systems except for the + ``gil_disabled`` flag. So, on ``Windows`` systems, + when ``Python_FIND_ABI`` is defined, ``Python`` distributions from + `python.org `_ will be found only if the value for + each flag is ``OFF`` or ``ANY`` except for the fourth one + (``gil_disabled``). ``Python3_FIND_STRATEGY`` .. versionadded:: 3.15 @@ -333,6 +376,8 @@ Hints constraints is founded. This is the default if policy :policy:`CMP0094` is set to ``NEW``. + See also ``Python3_FIND_UNVERSIONED_NAMES``. + ``Python3_FIND_REGISTRY`` .. versionadded:: 3.13 @@ -440,6 +485,8 @@ Hints This is the default. * ``NEVER``: The generic name are not searched at all. + See also ``Python3_FIND_STRATEGY``. + Artifacts Specification ^^^^^^^^^^^^^^^^^^^^^^^ @@ -541,6 +588,10 @@ If the library type is not specified, ``MODULE`` is assumed. When option ``WITH_SOABI`` is also specified, the module suffix will include the ``Python3_SOSABI`` value, if any. + +.. versionadded:: 3.30 + For ``MODULE`` type, the :prop_tgt:`DEBUG_POSTFIX` target property is + initialized with the value of ``Python3_DEBUG_POSTFIX`` variable if defined. #]=======================================================================] diff --git a/config/FindPythonInterp.cmake b/config/FindPythonInterp.cmake index e6dd2984..e5bcb5f5 100644 --- a/config/FindPythonInterp.cmake +++ b/config/FindPythonInterp.cmake @@ -5,6 +5,9 @@ FindPythonInterp ---------------- +.. versionchanged:: 3.27 + This module is available only if policy :policy:`CMP0148` is not set to ``NEW``. + .. deprecated:: 3.12 Use :module:`FindPython3`, :module:`FindPython2` or :module:`FindPython` instead. @@ -50,11 +53,21 @@ of PYTHON_LIBRARIES. #]=======================================================================] +cmake_policy(GET CMP0148 _FindPythonInterp_CMP0148) +if(_FindPythonInterp_CMP0148 STREQUAL "NEW") + message(FATAL_ERROR "The FindPythonInterp module has been removed by policy CMP0148.") +endif() + +if(_FindPythonInterp_testing) + set(_FindPythonInterp_included TRUE) + return() +endif() + unset(_Python_NAMES) set(_PYTHON1_VERSIONS 1.6 1.5) set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) -set(_PYTHON3_VERSIONS 3.13 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) +set(_PYTHON3_VERSIONS 3.14 3.13 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) if(PythonInterp_FIND_VERSION) if(PythonInterp_FIND_VERSION_COUNT GREATER 1) diff --git a/config/FindPythonLibs.cmake b/config/FindPythonLibs.cmake index 8dfd060b..467e8c27 100644 --- a/config/FindPythonLibs.cmake +++ b/config/FindPythonLibs.cmake @@ -5,6 +5,9 @@ FindPythonLibs -------------- +.. versionchanged:: 3.27 + This module is available only if policy :policy:`CMP0148` is not set to ``NEW``. + .. deprecated:: 3.12 Use :module:`FindPython3`, :module:`FindPython2` or :module:`FindPython` instead. @@ -45,6 +48,20 @@ get the currently active Python version by default with a consistent version of PYTHON_LIBRARIES. #]=======================================================================] +cmake_policy(PUSH) +cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_ + +cmake_policy(GET CMP0148 _FindPythonLibs_CMP0148) +if(_FindPythonLibs_CMP0148 STREQUAL "NEW") + message(FATAL_ERROR "The FindPythonLibs module has been removed by policy CMP0148.") +endif() + +if(_FindPythonLibs_testing) + set(_FindPythonLibs_included TRUE) + cmake_policy(POP) + return() +endif() + # Use the executable's path as a hint set(_Python_LIBRARY_PATH_HINT) if(IS_ABSOLUTE "${PYTHON_EXECUTABLE}") @@ -79,7 +96,7 @@ set(CMAKE_FIND_FRAMEWORK LAST) set(_PYTHON1_VERSIONS 1.6 1.5) set(_PYTHON2_VERSIONS 2.7 2.6 2.5 2.4 2.3 2.2 2.1 2.0) -set(_PYTHON3_VERSIONS 3.13 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) +set(_PYTHON3_VERSIONS 3.14 3.13 3.12 3.11 3.10 3.9 3.8 3.7 3.6 3.5 3.4 3.3 3.2 3.1 3.0) if(PythonLibs_FIND_VERSION) if(PythonLibs_FIND_VERSION_COUNT GREATER 1) @@ -397,3 +414,5 @@ extern \"C\" { execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_filenameTmp}" "${_filename}" OUTPUT_QUIET ERROR_QUIET) endfunction() + +cmake_policy(POP) diff --git a/config/FindSQLite3.cmake b/config/FindSQLite3.cmake index 88c7dd20..308a444d 100644 --- a/config/FindSQLite3.cmake +++ b/config/FindSQLite3.cmake @@ -32,12 +32,24 @@ This module will set the following variables if found: #]=======================================================================] +cmake_policy(PUSH) +cmake_policy(SET CMP0159 NEW) # file(STRINGS) with REGEX updates CMAKE_MATCH_ + +find_package(PkgConfig QUIET) +pkg_check_modules(PC_SQLite3 QUIET sqlite3) + # Look for the necessary header -find_path(SQLite3_INCLUDE_DIR NAMES sqlite3.h) +find_path(SQLite3_INCLUDE_DIR NAMES sqlite3.h + HINTS + ${PC_SQLite3_INCLUDE_DIRS} +) mark_as_advanced(SQLite3_INCLUDE_DIR) # Look for the necessary library -find_library(SQLite3_LIBRARY NAMES sqlite3 sqlite) +find_library(SQLite3_LIBRARY NAMES sqlite3 sqlite + HINTS + ${PC_SQLite3_LIBRARY_DIRS} +) mark_as_advanced(SQLite3_LIBRARY) # Extract version information from the header file @@ -66,3 +78,5 @@ if(SQLite3_FOUND) INTERFACE_INCLUDE_DIRECTORIES "${SQLite3_INCLUDE_DIR}") endif() endif() + +cmake_policy(POP)