summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Chevrier <marc.chevrier@gmail.com>2024-05-30 17:08:30 (GMT)
committerMarc Chevrier <marc.chevrier@gmail.com>2024-06-04 16:14:35 (GMT)
commit9a0dee7257e9b9739f67300631cb56a5482de70e (patch)
treef6ef3272c9c3b90bc58c9b678b3d56bf8216edff
parent4178ab928f7e09ad453ec79815de79b9aab780a3 (diff)
downloadCMake-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.rst5
-rw-r--r--Modules/FindPython.cmake39
-rw-r--r--Modules/FindPython/Support.cmake183
-rw-r--r--Modules/FindPython3.cmake41
-rw-r--r--Tests/FindPython/Python3/CMakeLists.txt5
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)