summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRohit Goswami <rog32@hi.is>2021-11-15 00:10:46 +0000
committerRohit Goswami <rog32@hi.is>2021-11-15 03:49:21 +0000
commit9ce67e20ab316094cf8418c0dbbaacd9fcc610f2 (patch)
treec9c57148cc3c9039fe43cc2161562f119140b408
parenta565be5792bac34938f477e27bc085e65bd3191d (diff)
downloadnumpy-9ce67e20ab316094cf8418c0dbbaacd9fcc610f2.tar.gz
DOC: Add F77 scikit-build example
Co-authored-by: Nick Wogan <wogan@uw.edu>
-rw-r--r--doc/source/f2py/buildtools/skbuild.rst79
-rw-r--r--doc/source/f2py/code/CMakeLists_skbuild.txt89
-rw-r--r--doc/source/f2py/code/pyproj_skbuild.toml5
-rw-r--r--doc/source/f2py/code/setup_skbuild.py10
4 files changed, 183 insertions, 0 deletions
diff --git a/doc/source/f2py/buildtools/skbuild.rst b/doc/source/f2py/buildtools/skbuild.rst
index d55a1725b..961408c42 100644
--- a/doc/source/f2py/buildtools/skbuild.rst
+++ b/doc/source/f2py/buildtools/skbuild.rst
@@ -3,3 +3,82 @@
============================
Using via ``scikit-build``
============================
+
+``scikit-build`` provides two separate concepts geared towards the users of Python extension modules.
+1. A ``setuptools`` replacement
+2. A series of ``cmake`` modules with definitions which help building Python extensions
+
+.. note::
+
+ It is possible to use ``scikit-build``'s ``cmake`` modules to `bypass the
+ cmake setup mechanism`_ completely, and to write targets which call ``f2py
+ -c``. This usage is **not recommended** since the point of these build system
+ documents are to move away from the internal ``numpy.distutils`` methods.
+
+For situations where no ``setuptools`` replacements are required or wanted (i.e.
+if ``wheels`` are not needed), it is recommended to instead use the vanilla
+``cmake`` setup described in :ref:`f2py-cmake`.
+
+Fibonacci Walkthrough
+=======================
+
+We will consider the ``fib`` example from :ref:`f2py-getting-started` section.
+
+.. literalinclude:: ./../code/fib1.f
+ :language: fortran
+
+``CMake`` modules only
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Consider using the following ``CMakeLists.txt``.
+
+.. literalinclude:: ./../code/CMakeLists_skbuild.txt
+ :language: cmake
+
+Much of the logic is the same as in :ref:`f2py-cmake`, however notably here the
+appropriate module suffix is generated via ``sysconfig.get_config_var("SO")``.
+The resulting extension can be built and loaded in the standard workflow.
+
+.. code:: bash
+
+ ls .
+ # CMakeLists.txt fib1.f
+ mkdir build && cd build
+ cmake ..
+ make
+ python -c "import numpy as np; import fibby; a = np.zeros(9); fibby.fib(a); print (a)"
+ # [ 0. 1. 1. 2. 3. 5. 8. 13. 21.]
+
+
+``setuptools`` replacement
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The utility of ``scikit-build`` lies in being able to drive the generation of
+more than extension modules, in particular a common usage pattern is the
+generation of Python distributables (for example for PyPI).
+
+The workflow with ``scikit-build`` straightforwardly supports such packaging requirements. Consider augmenting the project with a ``setup.py`` as defined:
+
+.. literalinclude:: ./../code/setup_skbuild.py
+ :language: python
+
+Along with a commiserate ``pyproject.toml``
+
+.. literalinclude:: ./../code/pyproj_skbuild.toml
+ :language: toml
+
+Together these can build the extension using ``cmake`` in tandem with other
+standard ``setuptools`` outputs.
+
+.. code:: bash
+
+ ls .
+ # CMakeLists.txt fib1.f pyproject.toml setup.py
+ python setup.py build_ext --inplace
+ python -c "import numpy as np; import fibby.fibby; a = np.zeros(9); fibby.fibby.fib(a); print (a)"
+ # [ 0. 1. 1. 2. 3. 5. 8. 13. 21.]
+
+Where we have modified the path to the module as ``--inplace`` places the
+extension module in a subfolder.
+
+.. _bypass the cmake setup mechanism: https://scikit-build.readthedocs.io/en/latest/cmake-modules/F2PY.html
diff --git a/doc/source/f2py/code/CMakeLists_skbuild.txt b/doc/source/f2py/code/CMakeLists_skbuild.txt
new file mode 100644
index 000000000..97bc5c744
--- /dev/null
+++ b/doc/source/f2py/code/CMakeLists_skbuild.txt
@@ -0,0 +1,89 @@
+### setup project ###
+cmake_minimum_required(VERSION 3.17.3)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+
+project(fibby
+ VERSION 1.0
+ DESCRIPTION "FIB module"
+ LANGUAGES C Fortran
+ )
+
+# Safety net
+if(PROJECT_SOURCE_DIR STREQUAL PROJECT_BINARY_DIR)
+ message(
+ FATAL_ERROR
+ "In-source builds not allowed. Please make a new directory (called a build directory) and run CMake from there.\n"
+ )
+endif()
+
+# Grab Python
+find_package(Python3 3.9 REQUIRED
+ COMPONENTS Interpreter Development)
+
+# Ensure scikit-build modules
+if (NOT SKBUILD)
+ # Kanged -->https://github.com/Kitware/torch_liberator/blob/master/CMakeLists.txt
+ # If skbuild is not the driver; include its utilities in CMAKE_MODULE_PATH
+ execute_process(
+ COMMAND "${Python3_EXECUTABLE}"
+ -c "import os, skbuild; print(os.path.dirname(skbuild.__file__))"
+ OUTPUT_VARIABLE SKBLD_DIR
+ OUTPUT_STRIP_TRAILING_WHITESPACE
+ )
+ set(SKBLD_CMAKE_DIR "${SKBLD_DIR}/resources/cmake")
+ list(APPEND CMAKE_MODULE_PATH ${SKBLD_CMAKE_DIR})
+endif()
+
+# scikit-build style includes
+find_package(PythonExtensions REQUIRED) # for ${PYTHON_EXTENSION_MODULE_SUFFIX}
+find_package(NumPy REQUIRED) # for ${NumPy_INCLUDE_DIRS}
+find_package(F2PY REQUIRED) # for ${F2PY_INCLUDE_DIR}
+
+# Prepping the module
+set(f2py_module_name "fibby")
+set(fortran_src_file "${CMAKE_SOURCE_DIR}/fib1.f")
+set(generated_module_file ${f2py_module_name}${PYTHON_EXTENSION_MODULE_SUFFIX})
+
+# Target for enforcing dependencies
+add_custom_target(${f2py_module_name} ALL
+ DEPENDS "${fortran_src_file}"
+ )
+
+# Custom command for generating .c
+add_custom_command(
+ OUTPUT "${f2py_module_name}module.c"
+ COMMAND ${F2PY_EXECUTABLE}
+ -m ${f2py_module_name}
+ ${fortran_src_file}
+ --lower
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
+ DEPENDS ${fortran_src_file}
+ )
+
+add_library(${generated_module_file} MODULE
+ "${f2py_module_name}module.c"
+ "${F2PY_INCLUDE_DIR}/fortranobject.c"
+ "${fortran_src_file}")
+
+target_include_directories(${generated_module_file} PUBLIC
+ ${F2PY_INCLUDE_DIRS}
+ ${PYTHON_INCLUDE_DIRS})
+set_target_properties(${generated_module_file} PROPERTIES SUFFIX "")
+set_target_properties(${generated_module_file} PROPERTIES PREFIX "")
+
+# Linker fixes
+if (UNIX)
+ if (APPLE)
+ set_target_properties(${generated_module_file} PROPERTIES
+ LINK_FLAGS '-Wl,-dylib,-undefined,dynamic_lookup')
+ else()
+ set_target_properties(${generated_module_file} PROPERTIES
+ LINK_FLAGS '-Wl,--allow-shlib-undefined')
+ endif()
+endif()
+
+if (SKBUILD)
+ install(TARGETS ${generated_module_file} DESTINATION fibby)
+else()
+ install(TARGETS ${generated_module_file} DESTINATION ${CMAKE_SOURCE_DIR}/fibby)
+endif()
diff --git a/doc/source/f2py/code/pyproj_skbuild.toml b/doc/source/f2py/code/pyproj_skbuild.toml
new file mode 100644
index 000000000..6686d1736
--- /dev/null
+++ b/doc/source/f2py/code/pyproj_skbuild.toml
@@ -0,0 +1,5 @@
+[project]
+requires-python = ">=3.7"
+
+[build-system]
+requires = ["setuptools>=42", "wheel", "scikit-build", "cmake>=3.18", "numpy>=1.21"]
diff --git a/doc/source/f2py/code/setup_skbuild.py b/doc/source/f2py/code/setup_skbuild.py
new file mode 100644
index 000000000..4dfc6af8b
--- /dev/null
+++ b/doc/source/f2py/code/setup_skbuild.py
@@ -0,0 +1,10 @@
+from skbuild import setup
+
+setup(
+ name="fibby",
+ version="0.0.1",
+ description="a minimal example package (fortran version)",
+ license="MIT",
+ packages=['fibby'],
+ cmake_args=['-DSKBUILD=ON']
+)