Использование через cmake
По сложности, cmake находится между make и meson. Кривая обучения круче, так как синтаксис CMake не является питоническим и ближе к make с переменными окружения.
Однако, это компенсируется повышенной гибкостью и поддержкой большинства архитектур и компиляторов. Введение в синтаксис выходит за рамки этого документа, но это обширная коллекция ресурсов по CMake отлично подходит.
Примечание
cmake очень популярен для систем смешанных языков, однако поддержка f2py не является особенно естественной или приятной; и более естественный подход заключается в рассмотрении Использование через scikit-build
Прохождение по Фибоначчи (F77)
Возвращаясь к примеру fib из раздела Три способа обертывания - начало работы.
C FILE: FIB1.F
SUBROUTINE FIB(A,N)
C
C CALCULATE FIRST N FIBONACCI NUMBERS
C
INTEGER N
REAL*8 A(N)
DO I=1,N
IF (I.EQ.1) THEN
A(I) = 0.0D0
ELSEIF (I.EQ.2) THEN
A(I) = 1.0D0
ELSE
A(I) = A(I-1) + A(I-2)
ENDIF
ENDDO
END
C END FILE FIB1.F
Нам не нужно явно генерировать выходной файл python -m numpy.f2py fib1.f, который является fib1module.c, что выгодно. С этим мы можем теперь инициализировать файл CMakeLists.txt следующим образом:
cmake_minimum_required(VERSION 3.18) # Needed to avoid requiring embedded Python libs too
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, 3.8 or newer
find_package(Python 3.8 REQUIRED
COMPONENTS Interpreter Development.Module NumPy)
# Grab the variables from a local Python installation
# F2PY headers
execute_process(
COMMAND "${Python_EXECUTABLE}"
-c "import numpy.f2py; print(numpy.f2py.get_include())"
OUTPUT_VARIABLE F2PY_INCLUDE_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# Print out the discovered paths
include(CMakePrintHelpers)
cmake_print_variables(Python_INCLUDE_DIRS)
cmake_print_variables(F2PY_INCLUDE_DIR)
cmake_print_variables(Python_NumPy_INCLUDE_DIRS)
# Common variables
set(f2py_module_name "fibby")
set(fortran_src_file "${CMAKE_SOURCE_DIR}/fib1.f")
set(f2py_module_c "${f2py_module_name}module.c")
# Generate sources
add_custom_target(
genpyf
DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_c}"
)
add_custom_command(
OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_c}"
COMMAND ${Python_EXECUTABLE} -m "numpy.f2py"
"${fortran_src_file}"
-m "fibby"
--lower # Important
DEPENDS fib1.f # Fortran source
)
# Set up target
Python_add_library(${CMAKE_PROJECT_NAME} MODULE WITH_SOABI
"${CMAKE_CURRENT_BINARY_DIR}/${f2py_module_c}" # Generated
"${F2PY_INCLUDE_DIR}/fortranobject.c" # From NumPy
"${fortran_src_file}" # Fortran source(s)
)
# Depend on sources
target_link_libraries(${CMAKE_PROJECT_NAME} PRIVATE Python::NumPy)
add_dependencies(${CMAKE_PROJECT_NAME} genpyf)
target_include_directories(${CMAKE_PROJECT_NAME} PRIVATE "${F2PY_INCLUDE_DIR}")
Ключевым элементом файла CMakeLists.txt выше является то, что add_custom_command используется для генерации файлов обёртки C и затем добавляется в качестве зависимости от фактического целевого файла общей библиотеки через директиву add_custom_target, что предотвращает выполнение команды каждый раз. Кроме того, метод получения файла fortranobject.c также может использоваться для получения заголовков numpy в старых версиях cmake.
Затем это работает так же, как и другие модули, хотя соглашения об именах отличаются, и выходная библиотека не снабжается автоматически префиксом cython информации.
ls . # CMakeLists.txt fib1.f cmake -S . -B build cmake --build build cd build 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.]
Это особенно полезно в тех случаях, где уже существует существующая цепочка инструментов и scikit-build или другие дополнительные python зависимости нежелательны.
© 2005–2024 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/2.0/f2py/buildtools/cmake.html