Использование через meson
Примечание
Большая часть этого документа устарела, можно запустить f2py с --build-dir для получения скелетного проекта meson с базовыми зависимостями.
Изменено в версии 1.26.x: По умолчанию система сборки для f2py теперь meson, см. Состояние numpy.distutils и рекомендации по миграции для получения дополнительной информации.
Ключевое преимущество использования meson по сравнению с методами, описанными в Использование через numpy.distutils, заключается в том, что это позволяет легко интегрироваться в существующие системы и крупные проекты. meson имеет довольно питоновский синтаксис, что делает его более удобным и допускающим расширение для пользователей python.
Прохождение по Fibonacci (F77)
Нам понадобится сгенерированный C обёртки, прежде чем мы сможем использовать общую систему сборки, такую как meson. Мы получим её следующим образом:
python -m numpy.f2py fib1.f -m fib2
Теперь рассмотрим следующий meson.build файл для примеров fib и scalar из раздела Три способа обертки - начало работы:
project('f2py_examples', 'c',
version : '0.1',
license: 'BSD-3',
meson_version: '>=0.64.0',
default_options : ['warning_level=2'],
)
add_languages('fortran')
py_mod = import('python')
py = py_mod.find_installation(pure: false)
py_dep = py.dependency()
incdir_numpy = run_command(py,
['-c', 'import os; os.chdir(".."); import numpy; print(numpy.get_include())'],
check : true
).stdout().strip()
incdir_f2py = run_command(py,
['-c', 'import os; os.chdir(".."); import numpy.f2py; print(numpy.f2py.get_include())'],
check : true
).stdout().strip()
inc_np = include_directories(incdir_numpy, incdir_f2py)
py.extension_module('fib2',
[
'fib1.f',
'fib2module.c', # note: this assumes f2py was manually run before!
],
incdir_f2py / 'fortranobject.c',
include_directories: inc_np,
dependencies : py_dep,
install : true
)
На этом этапе сборка завершится, но импорт завершится ошибкой:
meson setup builddir meson compile -C builddir cd builddir python -c 'import fib2' Traceback (most recent call last): File "<string>", line 1, in <module> ImportError: fib2.cpython-39-x86_64-linux-gnu.so: undefined symbol: FIB_ # Check this isn't a false positive nm -A fib2.cpython-39-x86_64-linux-gnu.so | grep FIB_ fib2.cpython-39-x86_64-linux-gnu.so: U FIB_
Вспомните, что исходный пример, как воспроизведённый ниже, был в стиле SCREAMCASE:
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, является fib, а не FIB. Это означает, что у нас есть несколько вариантов. Один подход (если это возможно) заключается в приведении исходного файла Fortran к нижнему регистру, например:
tr "[:upper:]" "[:lower:]" < fib1.f > fib1.f python -m numpy.f2py fib1.f -m fib2 meson --wipe builddir meson compile -C builddir cd builddir python -c 'import fib2'
Однако это требует возможности модифицировать исходный код, что не всегда возможно. Самый простой способ решения этой проблемы — позволить f2py справиться с этим:
python -m numpy.f2py fib1.f -m fib2 --lower meson --wipe builddir meson compile -C builddir cd builddir python -c 'import fib2'
Автоматизация генерации обёртки
Основной проблемой в описанном выше рабочем процессе является ручная отслеживание входов. Хотя это потребовало бы больше усилий для определения фактических выходов по причинам, обсуждаемым в F2PY и системы сборки.
Примечание
Начиная с NumPy 1.22.4 и далее, f2py будет детерминированно генерировать файлы обёртки на основе стандартного Fortran входного файла (F77 или выше). --skip-empty-wrappers можно передать f2py для восстановления предыдущего поведения, при котором обёртки генерируются только при необходимости для входного файла.
Однако мы можем дополнить наш рабочий процесс простым способом, чтобы учесть файлы, для которых выходы известны при настройке системы сборки.
project('f2py_examples', 'c',
version : '0.1',
license: 'BSD-3',
meson_version: '>=0.64.0',
default_options : ['warning_level=2'],
)
add_languages('fortran')
py_mod = import('python')
py = py_mod.find_installation(pure: false)
py_dep = py.dependency()
incdir_numpy = run_command(py,
['-c', 'import os; os.chdir(".."); import numpy; print(numpy.get_include())'],
check : true
).stdout().strip()
incdir_f2py = run_command(py,
['-c', 'import os; os.chdir(".."); import numpy.f2py; print(numpy.f2py.get_include())'],
check : true
).stdout().strip()
fibby_source = custom_target('fibbymodule.c',
input : ['fib1.f'], # .f so no F90 wrappers
output : ['fibbymodule.c', 'fibby-f2pywrappers.f'],
command : [py, '-m', 'numpy.f2py', '@INPUT@', '-m', 'fibby', '--lower']
)
inc_np = include_directories(incdir_numpy, incdir_f2py)
py.extension_module('fibby',
['fib1.f', fibby_source],
incdir_f2py / 'fortranobject.c',
include_directories: inc_np,
dependencies : py_dep,
install : true
)
Это можно скомпилировать и запустить как раньше.
rm -rf builddir meson setup builddir meson compile -C builddir cd builddir 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.]
Основные моменты
Стоит учитывать следующее:
- В данном контексте использовать SCREAMCASE невозможно, поэтому содержимое файла
.fили сгенерированная обёртка.cдолжна быть приведена к нижнему регистру; что можно сделать с помощью параметра--lowerF2PY
© 2005–2024 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/2.0/f2py/buildtools/meson.html