FindPython: Add support for free threaded python

Fixes: #26016
This commit is contained in:
Marc Chevrier
2024-05-30 19:08:30 +02:00
parent 4178ab928f
commit 9a0dee7257
5 changed files with 177 additions and 98 deletions

View File

@@ -0,0 +1,5 @@
FindPython-free_thread_Python
-----------------------------
* The :module:`FindPython`, :module:`FindPython3` modules gained the support
of the free threaded python version.

View File

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

View File

@@ -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_DEBUG)
string (APPEND name "_d")
if (_PGN_INTERPRETER)
set (name_version ${version})
else()
string (REPLACE "." "" name_version ${version})
endif()
list (APPEND names "${name}")
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)
list (TRANSFORM abinames APPEND "_d")
endif()
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)

View File

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

View File

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