diff options
author | Rohit Goswami <rog32@hi.is> | 2021-11-15 00:10:46 +0000 |
---|---|---|
committer | Rohit Goswami <rog32@hi.is> | 2021-11-15 03:49:21 +0000 |
commit | 9ce67e20ab316094cf8418c0dbbaacd9fcc610f2 (patch) | |
tree | c9c57148cc3c9039fe43cc2161562f119140b408 | |
parent | a565be5792bac34938f477e27bc085e65bd3191d (diff) | |
download | numpy-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.rst | 79 | ||||
-rw-r--r-- | doc/source/f2py/code/CMakeLists_skbuild.txt | 89 | ||||
-rw-r--r-- | doc/source/f2py/code/pyproj_skbuild.toml | 5 | ||||
-rw-r--r-- | doc/source/f2py/code/setup_skbuild.py | 10 |
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'] +) |