|
| 1 | +#.rst: |
| 2 | +# |
| 3 | +# The purpose of the F2PY –Fortran to Python interface generator– project is to provide a |
| 4 | +# connection between Python and Fortran languages. |
| 5 | +# |
| 6 | +# F2PY is a Python package (with a command line tool f2py and a module f2py2e) that facilitates |
| 7 | +# creating/building Python C/API extension modules that make it possible to call Fortran 77/90/95 |
| 8 | +# external subroutines and Fortran 90/95 module subroutines as well as C functions; to access Fortran |
| 9 | +# 77 COMMON blocks and Fortran 90/95 module data, including allocatable arrays from Python. |
| 10 | +# |
| 11 | +# For more information on the F2PY project, see http://www.f2py.com/. |
| 12 | +# |
| 13 | +# The following variables are defined: |
| 14 | +# |
| 15 | +# :: |
| 16 | +# |
| 17 | +# F2PY_EXECUTABLE - absolute path to the F2PY executable |
| 18 | +# |
| 19 | +# :: |
| 20 | +# |
| 21 | +# F2PY_VERSION_STRING - the version of F2PY found |
| 22 | +# F2PY_VERSION_MAJOR - the F2PY major version |
| 23 | +# F2PY_VERSION_MINOR - the F2PY minor version |
| 24 | +# F2PY_VERSION_PATCH - the F2PY patch version |
| 25 | +# |
| 26 | +# |
| 27 | +# .. note:: |
| 28 | +# |
| 29 | +# By default, the module finds the F2PY program associated with the installed NumPy package. |
| 30 | +# |
| 31 | +# Example usage |
| 32 | +# ^^^^^^^^^^^^^ |
| 33 | +# |
| 34 | +# Assuming that a package named ``method`` is declared in ``setup.py`` and that the corresponding directory |
| 35 | +# containing ``__init__.py`` also exists, the following CMake code can be added to ``method/CMakeLists.txt`` |
| 36 | +# to ensure the C sources associated with ``cylinder_methods.f90`` are generated and the corresponding module |
| 37 | +# is compiled: |
| 38 | +# |
| 39 | +# .. code-block:: cmake |
| 40 | +# |
| 41 | +# find_package(F2PY REQUIRED) |
| 42 | +# |
| 43 | +# set(f2py_module_name "_cylinder_methods") |
| 44 | +# set(fortran_src_file "${CMAKE_CURRENT_SOURCE_DIR}/cylinder_methods.f90") |
| 45 | +# |
| 46 | +# set(generated_module_file ${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_name}${PYTHON_EXTENSION_MODULE_SUFFIX}) |
| 47 | +# |
| 48 | +# add_custom_target(${f2py_module_name} ALL |
| 49 | +# DEPENDS ${generated_module_file} |
| 50 | +# ) |
| 51 | +# |
| 52 | +# add_custom_command( |
| 53 | +# OUTPUT ${generated_module_file} |
| 54 | +# COMMAND ${F2PY_EXECUTABLE} |
| 55 | +# -m ${f2py_module_name} |
| 56 | +# -c |
| 57 | +# ${fortran_src_file} |
| 58 | +# WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| 59 | +# ) |
| 60 | +# |
| 61 | +# install(FILES ${generated_module_file} DESTINATION methods) |
| 62 | +# |
| 63 | +# .. warning:: |
| 64 | +# |
| 65 | +# Using ``f2py`` with ``-c`` argument means that f2py is also responsible to build the module. In that |
| 66 | +# case, CMake is not used to find the compiler and configure the associated build system. |
| 67 | +# |
| 68 | + |
| 69 | +find_program(F2PY_EXECUTABLE NAMES f2py${PYTHON_VERSION_MAJOR} f2py) |
| 70 | + |
| 71 | +# XXX This is required to support NumPy < v0.15.0. See note in module documentation above. |
| 72 | +if(NOT F2PY_EXECUTABLE) |
| 73 | + find_package(NumPy) |
| 74 | + set(F2PY_EXECUTABLE "${PYTHON_EXECUTABLE}" "-m" "numpy.f2py") |
| 75 | +endif() |
| 76 | + |
| 77 | +if(NOT F2PY_INCLUDE_DIR) |
| 78 | + execute_process( |
| 79 | + COMMAND "${PYTHON_EXECUTABLE}" |
| 80 | + -c "import os; from numpy import f2py; print(f2py.get_include() if hasattr(f2py, 'get_include') else os.path.join(os.path.dirname(f2py.__file__), 'src'))" |
| 81 | + OUTPUT_VARIABLE _f2py_directory |
| 82 | + OUTPUT_STRIP_TRAILING_WHITESPACE |
| 83 | + ERROR_QUIET |
| 84 | + ) |
| 85 | + string(REPLACE "\\" "/" _f2py_directory ${_f2py_directory}) |
| 86 | + |
| 87 | + set(F2PY_INCLUDE_DIR "${_f2py_directory}" CACHE STRING "F2PY source directory location" FORCE) |
| 88 | +endif() |
| 89 | + |
| 90 | +# Set-up the F2PY libraries and include directories |
| 91 | +file(GLOB _f2py_sources "${F2PY_INCLUDE_DIR}/*.c") |
| 92 | +add_library(_f2py_runtime_library STATIC ${_f2py_sources}) |
| 93 | +target_include_directories( |
| 94 | + _f2py_runtime_library |
| 95 | + PRIVATE ${PYTHON_INCLUDE_DIRS} ${NumPy_INCLUDE_DIRS} |
| 96 | + ) |
| 97 | + |
| 98 | +set_target_properties(_f2py_runtime_library PROPERTIES POSITION_INDEPENDENT_CODE ON) |
| 99 | + |
| 100 | +set(F2PY_LIBRARIES _f2py_runtime_library) |
| 101 | +set(F2PY_INCLUDE_DIRS "${F2PY_INCLUDE_DIR}" "${NumPy_INCLUDE_DIRS}") |
| 102 | + |
| 103 | +if(F2PY_EXECUTABLE) |
| 104 | + # extract the version string |
| 105 | + execute_process(COMMAND "${F2PY_EXECUTABLE}" -v |
| 106 | + OUTPUT_VARIABLE F2PY_VERSION_STRING |
| 107 | + OUTPUT_STRIP_TRAILING_WHITESPACE) |
| 108 | + if("${F2PY_VERSION_STRING}" MATCHES "^([0-9]+)(.([0-9+]))?(.([0-9+]))?$") |
| 109 | + set(F2PY_VERSION_MAJOR ${CMAKE_MATCH_1}) |
| 110 | + set(F2PY_VERSION_MINOR "${CMAKE_MATCH_3}") |
| 111 | + set(F2PY_VERSION_PATCH "${CMAKE_MATCH_5}") |
| 112 | + endif() |
| 113 | +endif() |
| 114 | + |
| 115 | +# handle the QUIETLY and REQUIRED arguments and set F2PY_FOUND to TRUE if |
| 116 | +# all listed variables are TRUE |
| 117 | +include(FindPackageHandleStandardArgs) |
| 118 | +find_package_handle_standard_args(F2PY |
| 119 | + REQUIRED_VARS F2PY_EXECUTABLE |
| 120 | + VERSION_VAR F2PY_VERSION_STRING |
| 121 | + ) |
| 122 | + |
| 123 | +mark_as_advanced(F2PY_EXECUTABLE) |
| 124 | + |
| 125 | +include(UseF2PY) |
0 commit comments