diff --git a/CMakeLists.txt b/CMakeLists.txt index ab57b99..b41008c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,7 @@ include (config/project_config_embeddable.cmake) project (simlfs) set_project_names (simlfs SimLFS) set_project_brief ("C++ Simulated Low Fare Search (LFS) Library") -set_project_versions (1 00 6) +set_project_versions (1 00 7) ## # Project options diff --git a/ChangeLog b/ChangeLog index 8372080..a30089c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,6 @@ +* Mon Jan 27 2025 Denis Arnaud - 1.00.7 +- Upgraded CMake support files + * Sat Mar 23 2024 Denis Arnaud - 1.00.6 - Upgraded CMake support files diff --git a/NEWS b/NEWS index 14e68bd..a5c736d 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,7 @@ +* 2025-01-27: +- Version 1.00.7 +- Upgraded CMake support files + * 2024-03-23: - Version 1.00.6 - Upgraded CMake support files diff --git a/README.md b/README.md index 448076b..632cb18 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ To customise the following to your environment, you can alter the path to the installation directory: ```bash export INSTALL_BASEDIR="${HOME}/dev/deliveries" -export LFS_VER="1.00.6" +export LFS_VER="1.00.7" if [ -d /usr/lib64 ]; then LIBSUFFIX="64"; fi export LIBSUFFIX_4_CMAKE="-DLIB_SUFFIX=$LIBSUFFIX" `` diff --git a/autogen.sh b/autogen.sh index 895f669..be85536 100755 --- a/autogen.sh +++ b/autogen.sh @@ -51,7 +51,7 @@ fi # VERSION_MAJOR=1 VERSION_MINOR=00 -VERSION_PATCH=6 +VERSION_PATCH=7 VERSION_TMP_STRING=`grep "set_project_versions" CMakeLists.txt | sed -e "s/set_project_versions.*\([0-9]\+.\+[0-9]\+.\+[0-9]\+\).\+/\1/"` VERSION_STRING=`echo "${VERSION_TMP_STRING}" | grep "^[0-9]\+.[0-9]\+.[0-9]\+$"` diff --git a/config/FindDoxygenWrapper.cmake b/config/FindDoxygenWrapper.cmake index 90487ec..f582d88 100644 --- a/config/FindDoxygenWrapper.cmake +++ b/config/FindDoxygenWrapper.cmake @@ -8,8 +8,7 @@ if (DOXYGEN_FOUND STREQUAL "YES") execute_process ( COMMAND ${DOXYGEN_EXECUTABLE} --version OUTPUT_VARIABLE MY_TMP - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + OUTPUT_STRIP_TRAILING_WHITESPACE) set (DOXYGEN_VERSION ${MY_TMP}) # Check the version requirement only diff --git a/config/FindMySQL.cmake b/config/FindMySQL.cmake index 1aa3def..1299947 100644 --- a/config/FindMySQL.cmake +++ b/config/FindMySQL.cmake @@ -26,16 +26,14 @@ if (UNIX) execute_process ( COMMAND ${MYSQL_CONFIG} --version OUTPUT_VARIABLE MY_TMP - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + OUTPUT_STRIP_TRAILING_WHITESPACE) set (MYSQL_VERSION ${MY_TMP}) # Set INCLUDE_DIR execute_process ( COMMAND ${MYSQL_CONFIG} --include OUTPUT_VARIABLE MY_TMP - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + OUTPUT_STRIP_TRAILING_WHITESPACE) string (REGEX REPLACE "-I([^ ]*)( .*)?" "\\1" MY_TMP "${MY_TMP}") set (MYSQL_ADD_INCLUDE_PATH ${MY_TMP} CACHE FILEPATH INTERNAL) @@ -44,8 +42,7 @@ if (UNIX) execute_process ( COMMAND ${MYSQL_CONFIG} --libs_r OUTPUT_VARIABLE MY_TMP - OUTPUT_STRIP_TRAILING_WHITESPACE - ) + OUTPUT_STRIP_TRAILING_WHITESPACE) set (MYSQL_ADD_LIBRARIES "") string (REGEX MATCHALL "-l[^ ]*" MYSQL_LIB_LIST "${MY_TMP}") diff --git a/config/FindPython.cmake b/config/FindPython.cmake index 31ef1c7..a6f4bf5 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 @@ -406,7 +451,7 @@ Hints See `IronPython `_. * ``PyPy``: This implementation use ``RPython`` language and ``RPython translation toolchain`` to produce the python interpreter. - See `PyPy `_. + See `PyPy `_. The default value is: @@ -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 b56f671..c741ec1 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() @@ -3264,14 +3464,15 @@ if (("Development.Module" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS endif() # finalize library version information - _python_get_version (SABI_LIBRARY PREFIX _${_PYTHON_PREFIX}_) # ABI library does not have the full version information - if (${_PYTHON_PREFIX}_Interpreter_FOUND OR _${_PYTHON_PREFIX}_LIBRARY_RELEASE) - # update from interpreter or library + if (${_PYTHON_PREFIX}_Interpreter_FOUND AND NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) + # update from interpreter set (_${_PYTHON_PREFIX}_VERSION ${${_PYTHON_PREFIX}_VERSION}) set (_${_PYTHON_PREFIX}_VERSION_MAJOR ${${_PYTHON_PREFIX}_VERSION_MAJOR}) set (_${_PYTHON_PREFIX}_VERSION_MINOR ${${_PYTHON_PREFIX}_VERSION_MINOR}) set (_${_PYTHON_PREFIX}_VERSION_PATCH ${${_PYTHON_PREFIX}_VERSION_PATCH}) + elseif(NOT _${_PYTHON_PREFIX}_LIBRARY_RELEASE) + _python_get_version (SABI_LIBRARY PREFIX _${_PYTHON_PREFIX}_) endif() set (${_PYTHON_PREFIX}_SABI_LIBRARY_RELEASE "${_${_PYTHON_PREFIX}_SABI_LIBRARY_RELEASE}") @@ -3524,6 +3725,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 +3762,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 +3789,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 +3844,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 +3902,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 +3951,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 +4009,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 +4067,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 +4129,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 +4252,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 41d9b68..bf541ee 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 @@ -305,7 +339,7 @@ Hints See `IronPython `_. * ``PyPy``: This implementation use ``RPython`` language and ``RPython translation toolchain`` to produce the python interpreter. - See `PyPy `_. + See `PyPy `_. The default value is: @@ -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 ae086e8..cf93ecb 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 @@ -404,7 +449,7 @@ Hints See `IronPython `_. * ``PyPy``: This implementation use ``RPython`` language and ``RPython translation toolchain`` to produce the python interpreter. - See `PyPy `_. + See `PyPy `_. The default value is: @@ -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 e6dd298..e5bcb5f 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 8dfd060..6bf244e 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}") @@ -64,7 +81,10 @@ if(IS_ABSOLUTE "${PYTHON_EXECUTABLE}") endif() endif() -include(${CMAKE_CURRENT_LIST_DIR}/CMakeFindFrameworks.cmake) +block(SCOPE_FOR POLICIES) + cmake_policy(SET CMP0173 OLD) + include(${CMAKE_CURRENT_LIST_DIR}/CMakeFindFrameworks.cmake) +endblock() # Search for the python framework on Apple. CMAKE_FIND_FRAMEWORKS(Python) @@ -79,7 +99,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 +417,5 @@ extern \"C\" { execute_process(COMMAND ${CMAKE_COMMAND} -E copy_if_different "${_filenameTmp}" "${_filename}" OUTPUT_QUIET ERROR_QUIET) endfunction() + +cmake_policy(POP)