Использование с помощью scikit-build
scikit-build предоставляет два отдельных понятия, ориентированные на пользователей модулей расширения Python.
- Замена
setuptools(поведение по умолчанию) - Ряд модулей
cmakeс определениями, которые помогают в создании модулей расширения Python
Примечание
Можно использовать модули scikit-build для cmake полностью обойти механизм настройки cmake и создать цели, которые вызывают f2py
-c. Такое использование не рекомендуется, поскольку цель этих документов по системам сборки — перейти от внутренних методов numpy.distutils.
В ситуациях, когда не требуются или не нужны замены setuptools (то есть если wheels не нужны), рекомендуется использовать стандартную настройку cmake, описанную в Использование с помощью cmake.
Пример Fibonacci (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
CMake модули только
Рассмотрим использование следующих CMakeLists.txt.
### setup project ###
cmake_minimum_required(VERSION 3.9)
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()
# Ensure scikit-build modules
if (NOT SKBUILD)
find_package(PythonInterp 3.8 REQUIRED)
# 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 "${PYTHON_EXECUTABLE}"
-c "import os, skbuild; print(os.path.dirname(skbuild.__file__))"
OUTPUT_VARIABLE SKBLD_DIR
OUTPUT_STRIP_TRAILING_WHITESPACE
)
list(APPEND CMAKE_MODULE_PATH "${SKBLD_DIR}/resources/cmake")
message(STATUS "Looking in ${SKBLD_DIR}/resources/cmake for CMake modules")
endif()
# scikit-build style includes
find_package(PythonExtensions REQUIRED) # for ${PYTHON_EXTENSION_MODULE_SUFFIX}
# Grab the variables from a local Python installation
# NumPy headers
execute_process(
COMMAND "${PYTHON_EXECUTABLE}"
-c "import numpy; print(numpy.get_include())"
OUTPUT_VARIABLE NumPy_INCLUDE_DIRS
OUTPUT_STRIP_TRAILING_WHITESPACE
)
# 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
)
# Prepping the module
set(f2py_module_name "fibby")
set(fortran_src_file "${CMAKE_SOURCE_DIR}/fib1.f")
set(f2py_module_c "${f2py_module_name}module.c")
# Target for enforcing dependencies
add_custom_target(genpyf
DEPENDS "${fortran_src_file}"
)
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
)
add_library(${CMAKE_PROJECT_NAME} MODULE
"${f2py_module_name}module.c"
"${F2PY_INCLUDE_DIR}/fortranobject.c"
"${fortran_src_file}")
target_include_directories(${CMAKE_PROJECT_NAME} PUBLIC
${F2PY_INCLUDE_DIR}
${NumPy_INCLUDE_DIRS}
${PYTHON_INCLUDE_DIRS})
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES SUFFIX "${PYTHON_EXTENSION_MODULE_SUFFIX}")
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES PREFIX "")
# Linker fixes
if (UNIX)
if (APPLE)
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES
LINK_FLAGS '-Wl,-dylib,-undefined,dynamic_lookup')
else()
set_target_properties(${CMAKE_PROJECT_NAME} PROPERTIES
LINK_FLAGS '-Wl,--allow-shlib-undefined')
endif()
endif()
add_dependencies(${CMAKE_PROJECT_NAME} genpyf)
install(TARGETS ${CMAKE_PROJECT_NAME} DESTINATION fibby)
Большая часть логики такая же, как в Использование с помощью cmake, однако здесь суффикс модуля генерируется с помощью sysconfig.get_config_var("SO"). Результирующее расширение можно создать и загрузить в стандартном потоке работы.
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.]
Замена setuptools
Примечание
По состоянию на ноябрь 2021 года
Поведение, описанное здесь, по управлению процессом сборки cmake модуля, считается устаревшим и не должно использоваться.
Полезность scikit-build заключается в возможности управления генерацией не только модулей расширения, но и, в частности, общих шаблонов создания дистрибутивов Python (например, для PyPI).
Поток работы с scikit-build без проблем поддерживает такие требования к упаковке. Рассмотрите возможность дополнения проекта setup.py как определено:
from skbuild import setup
setup(
name="fibby",
version="0.0.1",
description="a minimal example package (fortran version)",
license="MIT",
packages=['fibby'],
python_requires=">=3.7",
)
Вместе с соответствующим pyproject.toml
[build-system] requires = ["setuptools>=42", "wheel", "scikit-build", "cmake>=3.9", "numpy>=1.21"] build-backend = "setuptools.build_meta"
Вместе они могут создать расширение с помощью cmake в сочетании с другими стандартными выходами setuptools. Запуск cmake через setup.py в основном используется, когда необходимо интегрироваться с модулями расширения, не созданными с помощью cmake.
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.]
Там, где мы изменили путь к модулю, так как --inplace помещает модуль расширения в подпапку.
© 2005–2024 NumPy Developers
Licensed under the 3-clause BSD License.
https://numpy.org/doc/2.0/f2py/buildtools/skbuild.html