FindPython: NumPy target does not depend on Development.Module

Fixes: #27123
This commit is contained in:
Marc Chevrier
2025-08-17 18:04:27 +02:00
parent 46fc0232ae
commit 0a4a4d2053
15 changed files with 162 additions and 26 deletions

View File

@@ -98,6 +98,7 @@ Policies Introduced by CMake 4.2
.. toctree::
:maxdepth: 1
CMP0201: The Python::NumPy target does not depend on the Python::Module target. </policy/CMP0201>
CMP0200: Location and configuration selection for imported targets is more consistent. </policy/CMP0200>
CMP0199: $<CONFIG> only matches the configuration of the consumed target. </policy/CMP0199>
CMP0198: CMAKE_PARENT_LIST_FILE is not defined in CMakeLists.txt. </policy/CMP0198>

36
Help/policy/CMP0201.rst Normal file
View File

@@ -0,0 +1,36 @@
CMP0201
-------
.. versionadded:: 4.2
The modules :module:`FindPython3`, :module:`FindPython2` and
:module:`FindPython` change the handling of the ``NumPy``
component and, respectively, the definition of the ``Python3::NumPy``,
``Python2::NumPy`` and ``Python::NumPy`` targets.
For CMake 4.2 and above, the specification of the ``NumPy`` component does not
imply anymore the component ``Development.Module`` and the ``Python3::NumPy``,
``Python2::NumPy`` and ``Python::NumPy`` targets provided, respectively, by the
modules :module:`FindPython3`, :module:`FindPython2` and :module:`FindPython`
do not depend on the ``Python3::Development.Module``,
``Python2::Development.Module`` and ``Python::Development.Module`` targets.
For CMake 4.1 and below, the specification of the ``NumPy`` component imply the
component ``Development.Module`` and the ``Python3::NumPy``, ``Python2::NumPy``
and ``Python::NumPy`` targets provided, respectively, by the modules
:module:`FindPython3`, :module:`FindPython2` and :module:`FindPython` depend on
the ``Python3::Development.Module``, ``Python2::Development.Module`` and
``Python::Development.Module`` targets.
The ``OLD`` behavior for this policy creates a dependency of the ``NumPy``
target over the ``Development.Module`` target. The ``NEW`` behavior does not
create a dependency of the ``NumPy`` target over the ``Development.Module``
target.
This policy provides compatibility with projects that expect the legacy
behavior.
.. |INTRODUCED_IN_CMAKE_VERSION| replace:: 4.2
.. |WARNS_OR_DOES_NOT_WARN| replace:: does *not* warn
.. include:: include/STANDARD_ADVICE.rst
.. include:: include/DEPRECATED.rst

View File

@@ -0,0 +1,5 @@
FindPython-NumPy-target
-----------------------
* The ``Python::NumPy`` target does not depend on
the ``Python::Development.Module`` target. See policy :policy:`CMP0201`.

View File

@@ -42,10 +42,14 @@ The following components are supported:
`Stable Application Binary Interface <https://docs.python.org/3/c-api/stable.html>`_.
This component is available only for version ``3.2`` and upper.
* ``NumPy``: search for NumPy include directories.
.. versionadded:: 3.14
Added the ``NumPy`` component.
* ``NumPy``: search for NumPy include directories. Specifying this component
imply also the components ``Interpreter`` and ``Development.Module``.
.. versionchanged:: 4.2
The component ``Development.Module`` is no longer implied when the policy
:policy:`CMP0201` is set to ``NEW``.
If no ``COMPONENTS`` are specified, ``Interpreter`` is assumed.
@@ -138,6 +142,11 @@ This module provides the following :ref:`Imported Targets`:
.. versionadded:: 3.14
NumPy Python library. Target defined if component ``NumPy`` is found.
Moreover, this target has the ``Python::Module`` target as dependency.
.. versionchanged:: 4.2
This target does not have anymore the ``Python::Module`` target as
dependency when the policy :policy:`CMP0201` is set to ``NEW``.
Result Variables
^^^^^^^^^^^^^^^^

View File

@@ -1475,12 +1475,16 @@ endif()
# handle components
cmake_policy (GET CMP0201 _${_PYTHON_PREFIX}_NUMPY_POLICY)
if (NOT ${_PYTHON_BASE}_FIND_COMPONENTS)
set (${_PYTHON_BASE}_FIND_COMPONENTS Interpreter)
set (${_PYTHON_BASE}_FIND_REQUIRED_Interpreter TRUE)
endif()
if ("NumPy" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS)
list (APPEND ${_PYTHON_BASE}_FIND_COMPONENTS "Interpreter" "Development.Module")
list (APPEND ${_PYTHON_BASE}_FIND_COMPONENTS "Interpreter")
if(NOT _${_PYTHON_PREFIX}_NUMPY_POLICY STREQUAL "NEW")
list (APPEND ${_PYTHON_BASE}_FIND_COMPONENTS "Development.Module")
endif()
endif()
if ("Development" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS)
list (APPEND ${_PYTHON_BASE}_FIND_COMPONENTS "Development.Module" "Development.Embed")
@@ -4050,7 +4054,12 @@ if ("NumPy" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Interp
set (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}" CACHE INTERNAL "")
elseif (DEFINED _${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR)
# compute numpy signature. Depends on interpreter and development signatures
string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}:${_${_PYTHON_PREFIX}_DEVELOPMENT_MODULE_SIGNATURE}:${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
set(__${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}")
if(NOT _${_PYTHON_PREFIX}_NUMPY_POLICY STREQUAL "NEW")
string(APPEND __${_PYTHON_PREFIX}_NUMPY_SIGNATURE ":${_${_PYTHON_PREFIX}_DEVELOPMENT_MODULE_SIGNATURE}")
endif()
string(APPEND __${_PYTHON_PREFIX}_NUMPY_SIGNATURE ":${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${__${_PYTHON_PREFIX}_NUMPY_SIGNATURE}")
if (NOT __${_PYTHON_PREFIX}_NUMPY_SIGNATURE STREQUAL _${_PYTHON_PREFIX}_NUMPY_SIGNATURE
OR NOT EXISTS "${_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
unset (_${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR CACHE)
@@ -4101,8 +4110,12 @@ if ("NumPy" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Interp
unset (${_PYTHON_PREFIX}_NumPy_VERSION)
endif()
# final step: set NumPy founded only if Development.Module component is founded as well
set(${_PYTHON_PREFIX}_NumPy_FOUND ${${_PYTHON_PREFIX}_Development.Module_FOUND})
if(NOT _${_PYTHON_PREFIX}_NUMPY_POLICY STREQUAL "NEW")
# final step: set NumPy founded only if Development.Module component is founded as well
set(${_PYTHON_PREFIX}_NumPy_FOUND ${${_PYTHON_PREFIX}_Development.Module_FOUND})
else()
set (${_PYTHON_PREFIX}_NumPy_FOUND TRUE)
endif()
else()
set (${_PYTHON_PREFIX}_NumPy_FOUND FALSE)
endif()
@@ -4117,7 +4130,12 @@ if ("NumPy" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Interp
unset (_${_PYTHON_PREFIX}_NumPy_REASON_FAILURE CACHE)
# compute and save numpy signature
string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}:${_${_PYTHON_PREFIX}_DEVELOPMENT_MODULE_SIGNATURE}:${${_PYTHON_PREFIX}_NumPyINCLUDE_DIR}")
set (__${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${_${_PYTHON_PREFIX}_INTERPRETER_SIGNATURE}")
if(NOT _${_PYTHON_PREFIX}_NUMPY_POLICY STREQUAL "NEW")
string (APPEND __${_PYTHON_PREFIX}_NUMPY_SIGNATURE ":${_${_PYTHON_PREFIX}_DEVELOPMENT_MODULE_SIGNATURE}")
endif()
string (APPEND __${_PYTHON_PREFIX}_NUMPY_SIGNATURE ":${${_PYTHON_PREFIX}_NumPyINCLUDE_DIR}")
string (MD5 __${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${__${_PYTHON_PREFIX}_NUMPY_SIGNATURE}")
set (_${_PYTHON_PREFIX}_NUMPY_SIGNATURE "${__${_PYTHON_PREFIX}_NUMPY_SIGNATURE}" CACHE INTERNAL "")
else()
unset (_${_PYTHON_PREFIX}_NUMPY_SIGNATURE CACHE)
@@ -4454,11 +4472,14 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT")
endif()
if ("NumPy" IN_LIST ${_PYTHON_BASE}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_NumPy_FOUND
AND NOT TARGET ${_PYTHON_PREFIX}::NumPy AND TARGET ${_PYTHON_PREFIX}::Module)
AND NOT TARGET ${_PYTHON_PREFIX}::NumPy AND
(_${_PYTHON_PREFIX}_NUMPY_POLICY STREQUAL "NEW" OR TARGET ${_PYTHON_PREFIX}::Module))
add_library (${_PYTHON_PREFIX}::NumPy INTERFACE IMPORTED)
set_property (TARGET ${_PYTHON_PREFIX}::NumPy
PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS}")
target_link_libraries (${_PYTHON_PREFIX}::NumPy INTERFACE ${_PYTHON_PREFIX}::Module)
if(NOT _${_PYTHON_PREFIX}_NUMPY_POLICY STREQUAL "NEW")
target_link_libraries (${_PYTHON_PREFIX}::NumPy INTERFACE ${_PYTHON_PREFIX}::Module)
endif()
endif()
endif()

View File

@@ -35,10 +35,14 @@ The following components are supported:
* ``Development.Embed``: search for artifacts for Python 2 embedding
developments.
* ``NumPy``: search for NumPy include directories.
.. versionadded:: 3.14
Added the ``NumPy`` component.
* ``NumPy``: search for NumPy include directories. Specifying this component
imply also the components ``Interpreter`` and ``Development.Module``.
.. versionchanged:: 4.2
The component ``Development.Module`` is no longer implied when the policy
:policy:`CMP0201` is set to ``NEW``.
If no ``COMPONENTS`` are specified, ``Interpreter`` is assumed.
@@ -125,6 +129,11 @@ This module provides the following :ref:`Imported Targets`:
.. versionadded:: 3.14
NumPy library for Python 2. Target defined if component ``NumPy`` is found.
Moreover, this target has the ``Python2::Module`` target as dependency.
.. versionchanged:: 4.2
This target does not have anymore the ``Python2::Module`` target as
dependency when the policy :policy:`CMP0201` is set to ``NEW``.
Result Variables
^^^^^^^^^^^^^^^^

View File

@@ -42,10 +42,14 @@ The following components are supported:
`Stable Application Binary Interface <https://docs.python.org/3/c-api/stable.html>`_.
This component is available only for version ``3.2`` and upper.
* ``NumPy``: search for NumPy include directories.
.. versionadded:: 3.14
Added the ``NumPy`` component.
* ``NumPy``: search for NumPy include directories. Specifying this component
imply also the components ``Interpreter`` and ``Development.Module``.
.. versionchanged:: 4.2
The component ``Development.Module`` is no longer implied when the policy
:policy:`CMP0201` is set to ``NEW``.
If no ``COMPONENTS`` are specified, ``Interpreter`` is assumed.
@@ -140,6 +144,11 @@ This module provides the following :ref:`Imported Targets`:
.. versionadded:: 3.14
NumPy library for Python 3. Target defined if component ``NumPy`` is found.
Moreover, this target has the ``Python3::Module`` target as dependency.
.. versionchanged:: 4.2
This target does not have anymore the ``Python3::Module`` target as
dependency when the policy :policy:`CMP0201` is set to ``NEW``.
Result Variables
^^^^^^^^^^^^^^^^

View File

@@ -600,6 +600,10 @@ class cmMakefile;
SELECT(POLICY, CMP0200, \
"Location and configuration selection for imported targets is more " \
"consistent.", \
4, 2, 0, WARN) \
SELECT(POLICY, CMP0201, \
"The Python::NumPy target does not depend on the Python::Module " \
"target.", \
4, 2, 0, WARN)
#define CM_SELECT_ID(F, A1, A2, A3, A4, A5, A6) F(A1)

View File

@@ -0,0 +1,3 @@
cmake_policy(SET CMP0201 NEW)
include(NumPy.cmake)

View File

@@ -0,0 +1,3 @@
cmake_policy(SET CMP0201 OLD)
include(NumPy.cmake)

View File

@@ -0,0 +1,3 @@
cmake_policy(SET CMP0201 NEW)
include(NumPyOnly.cmake)

View File

@@ -0,0 +1,3 @@
cmake_policy(SET CMP0201 OLD)
include(NumPyOnly.cmake)

View File

@@ -2,9 +2,15 @@ enable_language(C)
include(CTest)
cmake_policy(GET CMP0201 numpy_policy)
if(numpy_policy STREQUAL NEW)
set(components "Development.Module")
endif()
if(CMake_TEST_FindPython2_NumPy)
find_package (Python2 REQUIRED COMPONENTS NumPy)
find_package (Python2 REQUIRED COMPONENTS ${components} NumPy)
Python2_add_library (arraytest2 MODULE arraytest.c)
target_compile_definitions (arraytest2 PRIVATE PYTHON2)
@@ -18,7 +24,7 @@ endif()
if(CMake_TEST_FindPython3_NumPy)
find_package (Python3 REQUIRED COMPONENTS NumPy)
find_package (Python3 REQUIRED COMPONENTS ${components} NumPy)
Python3_add_library (arraytest3 MODULE arraytest.c)
target_compile_definitions (arraytest3 PRIVATE PYTHON3)

View File

@@ -0,0 +1,15 @@
enable_language(C)
include(CTest)
cmake_policy(SET CMP0201 NEW)
find_package (Python3 REQUIRED COMPONENTS Interpreter Development.SABIModule NumPy)
Python3_add_library (arraytest3 MODULE USE_SABI 3.${Python3_VERSION_MINOR} WITH_SOABI arraytest.c)
target_compile_definitions (arraytest3 PRIVATE PYTHON3)
target_link_libraries (arraytest3 PRIVATE Python3::NumPy)
add_test (NAME python3_arraytest
COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:arraytest3>"
"${Python3_INTERPRETER}" -c "import numpy; import arraytest3; arraytest3.vecsq(numpy.array([1, 2, 3]));")

View File

@@ -350,14 +350,23 @@ if(CMake_TEST_FindPython_Various)
endif()
if(CMake_TEST_FindPython2_NumPy OR CMake_TEST_FindPython3_NumPy)
run_python(NumPy ACTION RUN
OPTIONS -DCMake_TEST_FindPython2_NumPy=${CMake_TEST_FindPython2_NumPy}
-DCMake_TEST_FindPython3_NumPy=${CMake_TEST_FindPython3_NumPy})
run_python(NumPyOnly ACTION RUN
OPTIONS -DCMake_TEST_FindPython2_NumPy=${CMake_TEST_FindPython2_NumPy}
-DCMake_TEST_FindPython3_NumPy=${CMake_TEST_FindPython3_NumPy})
if(CMake_TEST_FindPython3_NumPy)
custom_failure_message_check("NumPy" "Interpreter:Development:NumPy" -DPython3_NumPy_INCLUDE_DIR=/not/found/numpy/include)
run_python(NumPy-CMP0201-OLD ACTION RUN
OPTIONS -DCMake_TEST_FindPython2_NumPy=${CMake_TEST_FindPython2_NumPy}
-DCMake_TEST_FindPython3_NumPy=${CMake_TEST_FindPython3_NumPy})
run_python(NumPy-CMP0201-NEW ACTION RUN
OPTIONS -DCMake_TEST_FindPython2_NumPy=${CMake_TEST_FindPython2_NumPy}
-DCMake_TEST_FindPython3_NumPy=${CMake_TEST_FindPython3_NumPy})
run_python(NumPyOnly-CMP0201-OLD ACTION RUN
OPTIONS -DCMake_TEST_FindPython2_NumPy=${CMake_TEST_FindPython2_NumPy}
-DCMake_TEST_FindPython3_NumPy=${CMake_TEST_FindPython3_NumPy})
run_python(NumPyOnly-CMP0201-NEW ACTION RUN
OPTIONS -DCMake_TEST_FindPython2_NumPy=${CMake_TEST_FindPython2_NumPy}
-DCMake_TEST_FindPython3_NumPy=${CMake_TEST_FindPython3_NumPy})
if(CMake_TEST_FindPython3_NumPy)
if(CMake_TEST_FindPython3_SABIModule)
run_python(NumPySABIModule ACTION RUN)
endif()
custom_failure_message_check("NumPy" "Interpreter:Development:NumPy" -DPython3_NumPy_INCLUDE_DIR=/not/found/numpy/include)
endif()
endif()