Skip to main content

CMake helpers for building F2Py modules

Project description

f2py-cmake

Actions Status

PyPI version PyPI platforms

This provides helpers for using F2Py. Use:

include(UseF2Py)

You must have found a Python interpreter beforehand. This will define a F2Py::Headers target and provide the following helper functions:

f2py_object_library(<name> <type>)

f2py_generate_signature(<module> <files>...
                  OUTPUT <Signature>
                  [ONLY <functions> ...]
                  [SKIP <functions> ...]
                  [OUTPUT_VARIABLE <OutputVariable>]
                  [F2CMAP <file>]
                  [NOLOWER]
                  [F2PY_ARGS <args> ...]
                  )

f2py_generate_module(<module> <files>...
                  [F2PY_ARGS <args> ...]
                  [F77 | F90]
                  [NOLOWER]
                  [F2CMAP <file>]
                  [OUTPUT_DIR <OutputDir>]
                  [OUTPUT_VARIABLE <OutputVariable>]
                  )

f2py_add_module(<name> <files>...
                  [F2PY_ARGS <args> ...]
                  [F77 | F90]
                  [NOLOWER]
                  [OUTPUT_DIR <OutputDir>]
                  )

Example

f2py_add_module builds an importable extension module in a single call. It generates the wrappers, creates the Python module target, and compiles/links the F2Py fortranobject support for you:

find_package(
  Python
  COMPONENTS Interpreter Development.Module NumPy
  REQUIRED)

include(UseF2Py)

f2py_add_module(fibby fib1.f)

<name> may instead be a .pyf signature path (as accepted by f2py_generate_module); the module name is taken from the file stem. The created target is a normal CMake target named <name>, so customize it afterward with target_*() / set_target_properties() as usual.

If you need to share a single fortranobject library across several modules, or want the generated sources for custom wiring, use the primitives directly:

# Create the F2Py `numpyobject` library.
f2py_object_library(f2py_object OBJECT)

f2py_generate_module(fibby fib1.f OUTPUT_VARIABLE fibby_files)

python_add_library(fibby MODULE "${fibby_files}" WITH_SOABI)
target_link_libraries(fibby PRIVATE f2py_object)

Signatures

f2py_generate_signature generates a .pyf signature file from Fortran sources, which f2py_generate_module can then consume as its <module> argument. ONLY and SKIP restrict which routines are wrapped (a thin wrapper over f2py's only:/skip: selectors):

f2py_generate_signature(mymod a.f90 b.f90
                        ONLY public_api
                        OUTPUT mymod.pyf OUTPUT_VARIABLE mymod_sig)

# The signature defines the interface; a.f90/b.f90 are compiled and linked.
f2py_generate_module(${mymod_sig} a.f90 b.f90 OUTPUT_VARIABLE mymod_files)

python_add_library(mymod MODULE "${mymod_files}" WITH_SOABI)
target_link_libraries(mymod PRIVATE f2py_object)

The files passed to f2py_generate_module need not match those used for the signature. The signature alone defines the wrapped interface, so you can build it from a subset and link extra Fortran that is called internally but never exposed to Python:

f2py_generate_signature(mymod a.f90 OUTPUT mymod.pyf OUTPUT_VARIABLE mymod_sig)

# helper.f90 is linked but not wrapped.
f2py_generate_module("${mymod_sig}" a.f90 helper.f90 OUTPUT_VARIABLE mymod_files)

Custom type maps

Fortran code that uses custom kinds (such as real(kind=dp)) needs a .f2py_f2cmap file telling f2py how to map those kinds to C types, e.g.:

dict(real=dict(dp="double"))

A .f2py_f2cmap placed next to your sources is auto-detected by both f2py_generate_signature and f2py_generate_module. You can also point at one explicitly with F2CMAP <file> (a relative path is resolved against the current source directory, and an explicit F2CMAP overrides auto-detection):

f2py_generate_module(mymod mymod.f90 F2CMAP maps/types.f2cmap
                     OUTPUT_VARIABLE mymod_files)

f2py's own --f2cmap default (the cwd) does not work here: these helpers run f2py in the build directory, not the source tree, so the file must be located explicitly.

Limitations

The following are deliberate scope boundaries, not bugs:

  • USE/INCLUDE dependencies are not tracked. The f2py invocation only depends on the source files you pass to the helper. Files pulled in through Fortran INCLUDE, or modules compiled elsewhere and brought in via USE, are not listed as dependencies, so editing one of them will not retrigger f2py regeneration. Work around this by passing those files explicitly, touching a tracked source, or doing a clean rebuild.

scikit-build-core

To use this package with scikit-build-core, you need to include it in your build requirements:

[build-system]
requires = ["scikit-build-core", "numpy", "f2py-cmake"]
build-backend = "scikit_build_core.build"

Vendoring

You can vendor UseF2Py into your package, as well. This avoids requiring a dependency at build time and protects you against changes in this package, at the expense of requiring manual re-vendoring to get bugfixes and/or improvements. This mechanism is also ideal if you want to support direct builds, outside of scikit-build-core.

You should make a CMake helper directory, such as cmake. Add this to your CMakeLists.txt like this:

list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")

Then, you can vendor our file into that folder:

pipx run f2py-cmake vendor cmake

Acknowledgements

Support for this work was provided by NSF grant OAC-2209877. Any opinions, findings, and conclusions or recommendations expressed in this material are those of the author(s) and do not necessarily reflect the views of the National Science Foundation.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

f2py_cmake-0.2.0.tar.gz (26.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

f2py_cmake-0.2.0-py3-none-any.whl (18.0 kB view details)

Uploaded Python 3

File details

Details for the file f2py_cmake-0.2.0.tar.gz.

File metadata

  • Download URL: f2py_cmake-0.2.0.tar.gz
  • Upload date:
  • Size: 26.5 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for f2py_cmake-0.2.0.tar.gz
Algorithm Hash digest
SHA256 c624915ac59b12b351f9da4c186e49123e04a44f3d401d0c4fc214f307b77023
MD5 8ba2e88acb793908b75e688a95daff9e
BLAKE2b-256 ac6323fc154c88bcf3f5e4295f146451af96c7b2fd85683bb61f7cb481f28871

See more details on using hashes here.

Provenance

The following attestation bundles were made for f2py_cmake-0.2.0.tar.gz:

Publisher: cd.yml on scikit-build/f2py-cmake

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file f2py_cmake-0.2.0-py3-none-any.whl.

File metadata

  • Download URL: f2py_cmake-0.2.0-py3-none-any.whl
  • Upload date:
  • Size: 18.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for f2py_cmake-0.2.0-py3-none-any.whl
Algorithm Hash digest
SHA256 6f04daed3fd0d15eee0dfcc811fa0c7fb663ac99a9aec19aac72f220d9a00d13
MD5 713db08128b72c321af174dbf8d8ffcd
BLAKE2b-256 9f26aa1efb036cdd3a7ad9754427eb66cfe37d07ed3cce3b27b47013951e1b22

See more details on using hashes here.

Provenance

The following attestation bundles were made for f2py_cmake-0.2.0-py3-none-any.whl:

Publisher: cd.yml on scikit-build/f2py-cmake

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page