diff options
author | Marc Chevrier <marc.chevrier@gmail.com> | 2024-05-30 17:08:30 (GMT) |
---|---|---|
committer | Marc Chevrier <marc.chevrier@gmail.com> | 2024-06-04 16:14:35 (GMT) |
commit | 9a0dee7257e9b9739f67300631cb56a5482de70e (patch) | |
tree | f6ef3272c9c3b90bc58c9b678b3d56bf8216edff | |
parent | 4178ab928f7e09ad453ec79815de79b9aab780a3 (diff) | |
download | CMake-9a0dee7257e9b9739f67300631cb56a5482de70e.zip CMake-9a0dee7257e9b9739f67300631cb56a5482de70e.tar.gz CMake-9a0dee7257e9b9739f67300631cb56a5482de70e.tar.bz2 |
FindPython: Add support for free threaded python
Fixes: #26016
-rw-r--r-- | Help/release/dev/FindPython-free_threaded_Python.rst | 5 | ||||
-rw-r--r-- | Modules/FindPython.cmake | 39 | ||||
-rw-r--r-- | Modules/FindPython/Support.cmake | 183 | ||||
-rw-r--r-- | Modules/FindPython3.cmake | 41 | ||||
-rw-r--r-- | Tests/FindPython/Python3/CMakeLists.txt | 5 |
5 files changed, 176 insertions, 97 deletions
diff --git a/Help/release/dev/FindPython-free_threaded_Python.rst b/Help/release/dev/FindPython-free_threaded_Python.rst new file mode 100644 index 0000000..56c143a --- /dev/null +++ b/Help/release/dev/FindPython-free_threaded_Python.rst @@ -0,0 +1,5 @@ +FindPython-free_thread_Python +----------------------------- + +* The :module:`FindPython`, :module:`FindPython3` modules gained the support + of the free threaded python version. diff --git a/Modules/FindPython.cmake b/Modules/FindPython.cmake index b963ef5..345afc5 100644 --- a/Modules/FindPython.cmake +++ b/Modules/FindPython.cmake @@ -310,42 +310,53 @@ 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 ``Python_FIND_ABI`` is not defined, any ABI 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``, ``<empty>``, ``dmu``, ``dm``, ``du`` and ``d``. + ``u``, ``<empty>``, ``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 <https://www.python.org/>`_ will be found only if value for - each flag is ``OFF`` or ``ANY``. + `python.org <https://www.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 diff --git a/Modules/FindPython/Support.cmake b/Modules/FindPython/Support.cmake index d05d27b..0f9d568 100644 --- a/Modules/FindPython/Support.cmake +++ b/Modules/FindPython/Support.cmake @@ -226,17 +226,28 @@ endfunction() function (_PYTHON_GET_ABIFLAGS _PGABIFLAGS) - set (abiflags) + if (NOT DEFINED _${_PYTHON_PREFIX}_FIND_ABI) + set (${_PGABIFLAGS} "<none>" PARENT_SCOPE) + return() + endif() + + set (abiflags "<none>") list (GET _${_PYTHON_PREFIX}_FIND_ABI 0 pydebug) list (GET _${_PYTHON_PREFIX}_FIND_ABI 1 pymalloc) list (GET _${_PYTHON_PREFIX}_FIND_ABI 2 unicode) + list (LENGTH _${_PYTHON_PREFIX}_FIND_ABI find_abi_length) + if (find_abi_length GREATER 3) + list (GET _${_PYTHON_PREFIX}_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" "<none>") 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" "<none>") elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ANY") set (abiflags "mu" "m") elseif (pymalloc STREQUAL "ON" AND unicode STREQUAL "ON") @@ -244,7 +255,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" "<none>") elseif (pymalloc STREQUAL "OFF" AND unicode STREQUAL "ON") set (abiflags "u") endif() @@ -261,10 +272,26 @@ function (_PYTHON_GET_ABIFLAGS _PGABIFLAGS) list (TRANSFORM flags PREPEND "d") list (APPEND abiflags "${flags}") else() - set (abiflags "" "d") + set (abiflags "<none>" "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 "<none>" "t") + endif() + endif() + list (TRANSFORM abiflags REPLACE "^(.+)<none>$" "\\1") set (${_PGABIFLAGS} "${abiflags}" PARENT_SCOPE) endfunction() @@ -277,6 +304,7 @@ function (_PYTHON_GET_PATH_SUFFIXES _PYTHON_PGPS_PATH_SUFFIXES) if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS) set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}") + list (TRANSFORM abi REPLACE "^<none>$" "") else() set (abi "mu" "m" "u" "") endif() @@ -368,19 +396,33 @@ function (_PYTHON_GET_NAMES _PYTHON_PGN_NAMES) 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() + if (DEFINED _${_PYTHON_PREFIX}_ABIFLAGS) + set (abi "${_${_PYTHON_PREFIX}_ABIFLAGS}") + list (TRANSFORM abi REPLACE "^<none>$" "") + else() + set (abi "") + endif() + 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}") + list (TRANSFORM abi REPLACE "^<none>$" "") else() if (_PGN_INTERPRETER OR _PGN_CONFIG) set (abi "") @@ -506,6 +548,9 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) endif() endif() endif() + if (NAME STREQUAL "ABIFLAGS" AND NOT _values) + set (_values "<none>") + endif() endif() if (_${_PYTHON_PREFIX}_EXECUTABLE AND NOT CMAKE_CROSSCOMPILING) @@ -600,6 +645,20 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) 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 "<none>") + else() + set (_values "t") + endif() else() set (config_flag "${NAME}") if (NAME STREQUAL "CONFIGDIR") @@ -614,6 +673,9 @@ function (_PYTHON_GET_CONFIG_VAR _PYTHON_PGCV_VALUE NAME) if (_result) unset (_values) endif() + if (NAME STREQUAL "ABIFLAGS" AND NOT _values) + set (_values "<none>") + endif() endif() endif() @@ -650,26 +712,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 @@ -685,7 +748,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) @@ -693,14 +755,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) @@ -708,7 +769,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() @@ -730,39 +790,44 @@ 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 <none> + set (abi "<none>") 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 "<none>") + endif() + set (${_PGV_PREFIX}ABI "${abi}" PARENT_SCOPE) endfunction() function (_PYTHON_GET_LAUNCHER _PYTHON_PGL_NAME) @@ -845,20 +910,11 @@ function (_PYTHON_VALIDATE_INTERPRETER) 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}\"") @@ -869,7 +925,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 @@ -936,7 +992,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 @@ -960,7 +1016,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 @@ -984,7 +1040,7 @@ function (_PYTHON_VALIDATE_INTERPRETER) else() set(target_arm FALSE) endif() - execute_process (COMMAND ${launcher} "${_${_PYTHON_PREFIX}_EXECUTABLE}" -c + 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 @@ -1252,7 +1308,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") @@ -1452,7 +1508,7 @@ 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 "<none>") else() unset (_${_PYTHON_PREFIX}_FIND_ABI) unset (_${_PYTHON_PREFIX}_ABIFLAGS) @@ -1461,12 +1517,12 @@ else() 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) endif() + _python_get_abiflags (_${_PYTHON_PREFIX}_ABIFLAGS) endif() unset (${_PYTHON_PREFIX}_SOABI) unset (${_PYTHON_PREFIX}_SOSABI) @@ -2168,16 +2224,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) @@ -2835,7 +2882,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS OUTPUT_STRIP_TRAILING_WHITESPACE) if (_${_PYTHON_PREFIX}_RESULT) # assume ABI is not supported - set (__${_PYTHON_PREFIX}_ABIFLAGS "") + set (__${_PYTHON_PREFIX}_ABIFLAGS "<none>") endif() if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # Wrong ABI @@ -2930,7 +2977,7 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS OUTPUT_STRIP_TRAILING_WHITESPACE) if (_${_PYTHON_PREFIX}_RESULT) # assume ABI is not supported - set (__${_PYTHON_PREFIX}_ABIFLAGS "") + set (__${_PYTHON_PREFIX}_ABIFLAGS "<none>") endif() if (DEFINED _${_PYTHON_PREFIX}_FIND_ABI AND NOT __${_PYTHON_PREFIX}_ABIFLAGS IN_LIST _${_PYTHON_PREFIX}_ABIFLAGS) # Wrong ABI @@ -3723,7 +3770,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) diff --git a/Modules/FindPython3.cmake b/Modules/FindPython3.cmake index b2a5b09..9002209 100644 --- a/Modules/FindPython3.cmake +++ b/Modules/FindPython3.cmake @@ -308,42 +308,53 @@ 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 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``, ``<empty>``, ``dmu``, ``dm``, ``du`` and ``d``. + ``u``, ``<empty>``, ``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 <https://www.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 <https://www.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 diff --git a/Tests/FindPython/Python3/CMakeLists.txt b/Tests/FindPython/Python3/CMakeLists.txt index 53d8b12..28f68e1 100644 --- a/Tests/FindPython/Python3/CMakeLists.txt +++ b/Tests/FindPython/Python3/CMakeLists.txt @@ -76,6 +76,11 @@ if (abi MATCHES "u") else() list (APPEND Python3_VALID_ABI "OFF") endif() +if (abi MATCHES "t") + list (APPEND Python3_VALID_ABI "ON") +else() + list (APPEND Python3_VALID_ABI "OFF") +endif() # build an invalid pattern for ABI set (Python3_INVALID_ABI) foreach (abi IN LISTS Python3_VALID_ABI) |