Browse Source

Merge topic 'FindPython-numpy'

513e77550d FindPython: Introduce NumPy component

Acked-by: Kitware Robot <[email protected]>
Merge-request: !2734
Marc Chevrier 6 years ago
parent
commit
0d8d7a6896

+ 5 - 0
Help/release/dev/FindPython-NumPy-component.rst

@@ -0,0 +1,5 @@
+FindPython-NumPy-component
+--------------------------
+
+* The :module:`FindPython`, :module:`FindPython2`, and :module:`FindPython3`
+  modules gained support for ``NumPy`` component.

+ 11 - 2
Modules/FindPython.cmake

@@ -14,11 +14,12 @@ Three components are supported:
 * ``Compiler``: search for Python compiler. Only offered by IronPython.
 * ``Development``: search for development artifacts (include directories and
   libraries).
+* ``NumPy``: search for NumPy include directories.
 
 If no ``COMPONENTS`` is specified, ``Interpreter`` is assumed.
 
-To ensure consistent versions between components ``Interpreter``, ``Compiler``
-and ``Development``, specify all components at the same time::
+To ensure consistent versions between components ``Interpreter``, ``Compiler``,
+``Development`` and ``NumPy``, specify all components at the same time::
 
   find_package (Python COMPONENTS Interpreter Development)
 
@@ -39,6 +40,8 @@ This module defines the following :ref:`Imported Targets <Imported Targets>`
   Python compiler. Target defined if component ``Compiler`` is found.
 ``Python::Python``
   Python library. Target defined if component ``Development`` is found.
+``Python::NumPy``
+  NumPy Python library. Target defined if component ``NumPy`` is found.
 
 Result Variables
 ^^^^^^^^^^^^^^^^
@@ -104,6 +107,12 @@ This module will set the following variables in your project
   Python minor version.
 ``Python_VERSION_PATCH``
   Python patch version.
+``Python_NumPy_FOUND``
+  System has the NumPy.
+``Python_NumPy_INCLUDE_DIRS``
+  The NumPy include directries.
+``Python_NumPy_VERSION``
+  The NumPy version.
 
 Hints
 ^^^^^

+ 47 - 0
Modules/FindPython/Support.cmake

@@ -209,6 +209,10 @@ if (NOT ${_PYTHON_PREFIX}_FIND_COMPONENTS)
   set (${_PYTHON_PREFIX}_FIND_COMPONENTS Interpreter)
   set (${_PYTHON_PREFIX}_FIND_REQUIRED_Interpreter TRUE)
 endif()
+if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS)
+  list (APPEND ${_PYTHON_PREFIX}_FIND_COMPONENTS "Interpreter" "Development")
+  list (REMOVE_DUPLICATES ${_PYTHON_PREFIX}_FIND_COMPONENTS)
+endif()
 foreach (_${_PYTHON_PREFIX}_COMPONENT IN LISTS ${_PYTHON_PREFIX}_FIND_COMPONENTS)
   set (${_PYTHON_PREFIX}_${_${_PYTHON_PREFIX}_COMPONENT}_FOUND FALSE)
 endforeach()
@@ -1122,6 +1126,41 @@ if ("Development" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS
   endif()
 endif()
 
+if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_Interpreter_FOUND)
+  if (${_PYTHON_PREFIX}_FIND_REQUIRED_NumPy)
+    list (APPEND _${_PYTHON_PREFIX}_REQUIRED_VARS ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR)
+    list (APPEND _${_PYTHON_PREFIX}_CACHED_VARS ${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR)
+  endif()
+  execute_process(
+      COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
+              "from __future__ import print_function\ntry: import numpy; print(numpy.get_include(), end='')\nexcept:pass\n"
+      RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+      OUTPUT_VARIABLE _${_PYTHON_PREFIX}_NumPy_PATH
+      ERROR_QUIET
+      OUTPUT_STRIP_TRAILING_WHITESPACE)
+  if (NOT _${_PYTHON_PREFIX}_RESULT)
+    find_path(${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR
+              NAMES arrayobject.h numpyconfig.h
+              HINTS "${_${_PYTHON_PREFIX}_NumPy_PATH}"
+              PATH_SUFFIXES numpy
+              NO_DEFAULT_PATH)
+  endif()
+  if(${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR)
+    set(${_PYTHON_PREFIX}_NumPy_INCLUDE_DIRS "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
+    set(${_PYTHON_PREFIX}_NumPy_FOUND TRUE)
+  endif()
+  if(${_PYTHON_PREFIX}_NumPy_FOUND)
+    execute_process(
+            COMMAND "${${_PYTHON_PREFIX}_EXECUTABLE}" -c
+            "from __future__ import print_function\ntry: import numpy; print(numpy.__version__, end='')\nexcept:pass\n"
+            RESULT_VARIABLE _${_PYTHON_PREFIX}_RESULT
+            OUTPUT_VARIABLE _${_PYTHON_PREFIX}_NumPy_VERSION)
+    if (NOT _${_PYTHON_PREFIX}_RESULT)
+       set(${_PYTHON_PREFIX}_NumPy_VERSION "${_${_PYTHON_PREFIX}_NumPy_VERSION}")
+    endif()
+  endif()
+endif()
+
 # final validation
 if (${_PYTHON_PREFIX}_VERSION_MAJOR AND
     NOT ${_PYTHON_PREFIX}_VERSION_MAJOR VERSION_EQUAL _${_PYTHON_PREFIX}_REQUIRED_VERSION_MAJOR)
@@ -1249,6 +1288,14 @@ if(_${_PYTHON_PREFIX}_CMAKE_ROLE STREQUAL "PROJECT")
       endif()
     endfunction()
   endif()
+
+  if ("NumPy" IN_LIST ${_PYTHON_PREFIX}_FIND_COMPONENTS AND ${_PYTHON_PREFIX}_NumPy_FOUND
+      AND NOT TARGET ${_PYTHON_PREFIX}::NumPy AND TARGET ${_PYTHON_PREFIX}::Python)
+    add_library (${_PYTHON_PREFIX}::NumPy INTERFACE IMPORTED)
+    set_property (TARGET ${_PYTHON_PREFIX}::NumPy
+                  PROPERTY INTERFACE_INCLUDE_DIRECTORIES "${${_PYTHON_PREFIX}_NumPy_INCLUDE_DIR}")
+    target_link_libraries (${_PYTHON_PREFIX}::NumPy INTERFACE ${_PYTHON_PREFIX}::Python)
+  endif()
 endif()
 
 # final clean-up

+ 11 - 2
Modules/FindPython2.cmake

@@ -14,11 +14,12 @@ Three components are supported:
 * ``Compiler``: search for Python 2 compiler. Only offered by IronPython.
 * ``Development``: search for development artifacts (include directories and
   libraries)
+* ``NumPy``: search for NumPy include directories.
 
 If no ``COMPONENTS`` is specified, ``Interpreter`` is assumed.
 
-To ensure consistent versions between components ``Interpreter``, ``Compiler``
-and ``Development``, specify all components at the same time::
+To ensure consistent versions between components ``Interpreter``, ``Compiler``,
+``Development`` and ``NumPy``, specify all components at the same time::
 
   find_package (Python2 COMPONENTS Interpreter Development)
 
@@ -40,6 +41,8 @@ This module defines the following :ref:`Imported Targets <Imported Targets>`
   Python 2 compiler. Target defined if component ``Compiler`` is found.
 ``Python2::Python``
   Python 2 library. Target defined if component ``Development`` is found.
+``Python2::NumPy``
+  NumPy library for Python 2. Target defined if component ``NumPy`` is found.
 
 Result Variables
 ^^^^^^^^^^^^^^^^
@@ -105,6 +108,12 @@ This module will set the following variables in your project
   Python 2 minor version.
 ``Python2_VERSION_PATCH``
   Python 2 patch version.
+``Python2_NumPy_FOUND``
+  System has the NumPy.
+``Python2_NumPy_INCLUDE_DIRS``
+  The NumPy include directries.
+``Python2_NumPy_VERSION``
+  The NumPy version.
 
 Hints
 ^^^^^

+ 11 - 2
Modules/FindPython3.cmake

@@ -14,11 +14,12 @@ Three components are supported:
 * ``Compiler``: search for Python 3 compiler. Only offered by IronPython.
 * ``Development``: search for development artifacts (include directories and
   libraries)
+* ``NumPy``: search for NumPy include directories.
 
 If no ``COMPONENTS`` is specified, ``Interpreter`` is assumed.
 
-To ensure consistent versions between components ``Interpreter``, ``Compiler``
-and ``Development``, specify all components at the same time::
+To ensure consistent versions between components ``Interpreter``, ``Compiler``,
+``Development`` and ``NumPy``, specify all components at the same time::
 
   find_package (Python3 COMPONENTS Interpreter Development)
 
@@ -40,6 +41,8 @@ This module defines the following :ref:`Imported Targets <Imported Targets>`
   Python 3 compiler. Target defined if component ``Compiler`` is found.
 ``Python3::Python``
   Python 3 library. Target defined if component ``Development`` is found.
+``Python3::NumPy``
+  NumPy library for Python 3. Target defined if component ``NumPy`` is found.
 
 Result Variables
 ^^^^^^^^^^^^^^^^
@@ -105,6 +108,12 @@ This module will set the following variables in your project
   Python 3 minor version.
 ``Python3_VERSION_PATCH``
   Python 3 patch version.
+``Python3_NumPy_FOUND``
+  System has the NumPy.
+``Python3_NumPy_INCLUDE_DIRS``
+  The NumPy include directries.
+``Python3_NumPy_VERSION``
+  The NumPy version.
 
 Hints
 ^^^^^

+ 1 - 1
Tests/CMakeLists.txt

@@ -1558,7 +1558,7 @@ ${CMake_BINARY_DIR}/bin/cmake -DDIR=dev -P ${CMake_SOURCE_DIR}/Utilities/Release
     add_subdirectory(FindXercesC)
   endif()
 
-  if(CMake_TEST_FindPython)
+  if(CMake_TEST_FindPython OR CMake_TEST_FindPython_NumPy)
     add_subdirectory(FindPython)
   endif()
 

+ 88 - 63
Tests/FindPython/CMakeLists.txt

@@ -1,69 +1,94 @@
-add_test(NAME FindPython.Python2 COMMAND
-  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
-  --build-and-test
-  "${CMake_SOURCE_DIR}/Tests/FindPython/Python2"
-  "${CMake_BINARY_DIR}/Tests/FindPython/Python2"
-  ${build_generator_args}
-  --build-project TestPython2
-  --build-options ${build_options}
-  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
-  )
+if(CMake_TEST_FindPython)
+  add_test(NAME FindPython.Python2 COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindPython/Python2"
+    "${CMake_BINARY_DIR}/Tests/FindPython/Python2"
+    ${build_generator_args}
+    --build-project TestPython2
+    --build-options ${build_options}
+    --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+    )
 
-add_test(NAME FindPython.Python2Fail COMMAND
-  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
-  --build-and-test
-  "${CMake_SOURCE_DIR}/Tests/FindPython/Python2Fail"
-  "${CMake_BINARY_DIR}/Tests/FindPython/Python2Fail"
-  ${build_generator_args}
-  --build-project TestPython2Fail
-  --build-options ${build_options}
-  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
-  )
-set_tests_properties(FindPython.Python2Fail PROPERTIES
-  PASS_REGULAR_EXPRESSION "Could NOT find Python2 \\(missing: foobar\\)")
+  add_test(NAME FindPython.Python2Fail COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindPython/Python2Fail"
+    "${CMake_BINARY_DIR}/Tests/FindPython/Python2Fail"
+    ${build_generator_args}
+    --build-project TestPython2Fail
+    --build-options ${build_options}
+    --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+    )
+  set_tests_properties(FindPython.Python2Fail PROPERTIES
+    PASS_REGULAR_EXPRESSION "Could NOT find Python2 \\(missing: foobar\\)")
 
-add_test(NAME FindPython.Python3 COMMAND
-  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
-  --build-and-test
-  "${CMake_SOURCE_DIR}/Tests/FindPython/Python3"
-  "${CMake_BINARY_DIR}/Tests/FindPython/Python3"
-  ${build_generator_args}
-  --build-project TestPython3
-  --build-options ${build_options}
-  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
-  )
+  add_test(NAME FindPython.Python3 COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindPython/Python3"
+    "${CMake_BINARY_DIR}/Tests/FindPython/Python3"
+    ${build_generator_args}
+    --build-project TestPython3
+    --build-options ${build_options}
+    --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+    )
 
-add_test(NAME FindPython.Python3Fail COMMAND
-  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
-  --build-and-test
-  "${CMake_SOURCE_DIR}/Tests/FindPython/Python3Fail"
-  "${CMake_BINARY_DIR}/Tests/FindPython/Python3Fail"
-  ${build_generator_args}
-  --build-project TestPython3Fail
-  --build-options ${build_options}
-  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
-  )
-set_tests_properties(FindPython.Python3Fail PROPERTIES
-  PASS_REGULAR_EXPRESSION "Could NOT find Python3 \\(missing: foobar\\)")
+  add_test(NAME FindPython.Python3Fail COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindPython/Python3Fail"
+    "${CMake_BINARY_DIR}/Tests/FindPython/Python3Fail"
+    ${build_generator_args}
+    --build-project TestPython3Fail
+    --build-options ${build_options}
+    --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+    )
+  set_tests_properties(FindPython.Python3Fail PROPERTIES
+    PASS_REGULAR_EXPRESSION "Could NOT find Python3 \\(missing: foobar\\)")
 
-add_test(NAME FindPython.Python COMMAND
-  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
-  --build-and-test
-  "${CMake_SOURCE_DIR}/Tests/FindPython/Python"
-  "${CMake_BINARY_DIR}/Tests/FindPython/Python"
-  ${build_generator_args}
-  --build-project TestPython
-  --build-options ${build_options}
-  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
-  )
+  add_test(NAME FindPython.Python COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindPython/Python"
+    "${CMake_BINARY_DIR}/Tests/FindPython/Python"
+    ${build_generator_args}
+    --build-project TestPython
+    --build-options ${build_options}
+    --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+    )
+
+  add_test(NAME FindPython.MultiplePackages COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindPython/MultiplePackages"
+    "${CMake_BINARY_DIR}/Tests/FindPython/MultiplePackages"
+    ${build_generator_args}
+    --build-project TestMultiplePackages
+    --build-options ${build_options}
+    --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+    )
+endif()
 
-add_test(NAME FindPython.MultiplePackages COMMAND
-  ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
-  --build-and-test
-  "${CMake_SOURCE_DIR}/Tests/FindPython/MultiplePackages"
-  "${CMake_BINARY_DIR}/Tests/FindPython/MultiplePackages"
-  ${build_generator_args}
-  --build-project TestMultiplePackages
-  --build-options ${build_options}
-  --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+if(CMake_TEST_FindPython_NumPy)
+  add_test(NAME FindPython.NumPy COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindPython/NumPy"
+    "${CMake_BINARY_DIR}/Tests/FindPython/NumPy"
+    ${build_generator_args}
+    --build-project TestNumPy
+    --build-options ${build_options}
+    --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
+  )
+  add_test(NAME FindPython.NumPyOnly COMMAND
+    ${CMAKE_CTEST_COMMAND} -C $<CONFIGURATION>
+    --build-and-test
+    "${CMake_SOURCE_DIR}/Tests/FindPython/NumPyOnly"
+    "${CMake_BINARY_DIR}/Tests/FindPython/NumPyOnly"
+    ${build_generator_args}
+    --build-project TestNumPyOnly
+    --build-options ${build_options}
+    --test-command ${CMAKE_CTEST_COMMAND} -V -C $<CONFIGURATION>
   )
+ endif()

+ 22 - 0
Tests/FindPython/NumPy/CMakeLists.txt

@@ -0,0 +1,22 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(TestNumPy C)
+
+find_package (Python2 REQUIRED COMPONENTS Interpreter Development NumPy)
+find_package (Python3 REQUIRED COMPONENTS Interpreter Development NumPy)
+
+Python2_add_library (arraytest2 MODULE arraytest.c)
+target_compile_definitions (arraytest2 PRIVATE PYTHON2)
+target_link_libraries (arraytest2 PRIVATE Python2::NumPy)
+
+Python3_add_library (arraytest3 MODULE arraytest.c)
+target_compile_definitions (arraytest3 PRIVATE PYTHON3)
+target_link_libraries (arraytest3 PRIVATE Python3::NumPy)
+
+add_test (NAME python2_arraytest
+          COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:arraytest2>"
+          "${Python2_EXECUTABLE}" -c "import numpy; import arraytest2; arraytest2.vecsq(numpy.array([1, 2, 3]));")
+
+add_test (NAME python3_arraytest
+          COMMAND "${CMAKE_COMMAND}" -E env "PYTHONPATH=$<TARGET_FILE_DIR:arraytest3>"
+          "${Python3_EXECUTABLE}" -c "import numpy; import arraytest3; arraytest3.vecsq(numpy.array([1, 2, 3]));")

+ 58 - 0
Tests/FindPython/NumPy/arraytest.c

@@ -0,0 +1,58 @@
+#include "Python.h"
+
+#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
+#include "arrayobject.h"
+
+#include <math.h>
+
+static PyObject* vecsq(PyObject* self, PyObject* args);
+
+static PyMethodDef arraytestMethods[] = { { "vecsq", vecsq, METH_VARARGS },
+                                          { NULL, NULL } };
+
+static PyObject* vecsq(PyObject* self, PyObject* args)
+{
+  PyArrayObject *vecin, *vecout;
+  npy_intp dims[2];
+  double *cin, *cout;
+  int i, j, n, m;
+
+  if (!PyArg_ParseTuple(args, "O!", &PyArray_Type, &vecin))
+    return NULL;
+
+  n = dims[0] = PyArray_NDIM(vecin);
+  vecout = (PyArrayObject*)PyArray_SimpleNew(1, dims, NPY_DOUBLE);
+
+  cin = (double*)PyArray_DATA(vecin);
+  cout = (double*)PyArray_DATA(vecout);
+
+  for (i = 0; i < n; i++) {
+    cout[i] = cin[i] * cin[i];
+  }
+  return PyArray_Return(vecout);
+}
+
+#if defined(PYTHON2)
+PyMODINIT_FUNC init_C_arraytest(void)
+{
+  (void)Py_InitModule("arraytest2", arraytestMethods);
+  import_array();
+}
+#endif
+
+#if defined(PYTHON3)
+static struct PyModuleDef arraytestmodule = {
+  PyModuleDef_HEAD_INIT, "arraytest3", /* name of module */
+  NULL,                                /* module documentation, may be NULL */
+  -1, /* size of per-interpreter state of the module,
+         or -1 if the module keeps state in global variables. */
+  arraytestMethods
+};
+
+PyMODINIT_FUNC PyInit_C_arraytest(void)
+{
+  PyObject* po = PyModule_Create(&arraytestmodule);
+  import_array();
+  return po;
+}
+#endif

+ 14 - 0
Tests/FindPython/NumPyOnly/CMakeLists.txt

@@ -0,0 +1,14 @@
+cmake_minimum_required(VERSION 3.1)
+
+project(TestNumPyOnly C)
+
+find_package(Python2 REQUIRED COMPONENTS NumPy)
+find_package(Python3 REQUIRED COMPONENTS NumPy)
+
+Python2_add_library (arraytest2 MODULE ../NumPy/arraytest.c)
+target_compile_definitions (arraytest2 PRIVATE PYTHON2)
+target_link_libraries (arraytest2 PRIVATE Python2::NumPy)
+
+Python3_add_library (arraytest3 MODULE ../NumPy/arraytest.c)
+target_compile_definitions (arraytest3 PRIVATE PYTHON3)
+target_link_libraries (arraytest3 PRIVATE Python3::NumPy)