[Python] scikit-build-core ignores .pyf files when building Python modules: why?

Discussão em 'Python' iniciado por Stack, Junho 10, 2025.

  1. Stack

    Stack Membro Participativo

    I maintain a Python module here and I'm having difficulty getting it to build correctly.

    The following steps apparently successfully install the module and put a file called geopack_tsyganenko.cpython-313-darwin.so in my site-packages:

    git clone https://github.com/johncoxon/tsyganenko
    pip install ./tsyganenko


    This results in the following in IPython:

    In [1]: import geopack_tsyganenko

    In [2]: geopack_tsyganenko.igrf_gsw_08?
    Signature: geopack_tsyganenko.igrf_gsw_08(*args, **kwargs)
    Type: fortran
    String form: <fortran function igrf_gsw_08>
    Docstring:
    igrf_gsw_08(xgsw,ygsw,zgsw,hxgsw,hygsw,hzgsw)

    Wrapper for ``igrf_gsw_08``.

    Parameters
    ----------
    xgsw : input float
    ygsw : input float
    zgsw : input float
    hxgsw : input float
    hygsw : input float
    hzgsw : input float


    However, geopack.pyf specifies that the hxgsw, hygsw, and hzgsw variables should be outputs, and they are not. This indicates that the build process is not seeing the geopack.pyf file correctly.

    On the other hand, if I run:

    cd tsyganenko/src/tsyganenko
    python -m numpy.f2py -c --f77flags="-w" geopack.pyf geopack.f T96.f T02.f -m geopack_tsyganenko --lower


    It creates geopack_tsyganenko.cpython-313-darwin.so in /src/tsyganenko and then if I copy that file manually into my site-packages the following happens in IPython:

    In [1]: import geopack_tsyganenko

    In [2]: geopack_tsyganenko.igrf_gsw_08?
    Signature: geopack_tsyganenko.igrf_gsw_08(*args, **kwargs)
    Type: fortran
    String form: <fortran function igrf_gsw_08>
    Docstring:
    hxgsw,hygsw,hzgsw = igrf_gsw_08(xgsw,ygsw,zgsw)

    Wrapper for ``igrf_gsw_08``.

    Parameters
    ----------
    xgsw : input float
    ygsw : input float
    zgsw : input float

    Returns
    -------
    hxgsw : float
    hygsw : float
    hzgsw : float


    My question is, how do I need to change my CMakeLists.txt file to get the build process to take account of geopack.pyf and compile correctly? At the moment, CMakeLists.txt looks like this:

    cmake_minimum_required(VERSION 3.17.2...3.29)
    project(${SKBUILD_PROJECT_NAME} LANGUAGES C Fortran)

    find_package(
    Python
    COMPONENTS Interpreter Development.Module NumPy
    REQUIRED)

    set(CMAKE_VERBOSE_MAKEFILE ON)
    set(CMAKE_Fortran_FLAGS "-w")

    # 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)

    add_library(fortranobject OBJECT "${F2PY_INCLUDE_DIR}/fortranobject.c")
    target_link_libraries(fortranobject PUBLIC Python::NumPy)
    target_include_directories(fortranobject PUBLIC "${F2PY_INCLUDE_DIR}")
    set_property(TARGET fortranobject PROPERTY POSITION_INDEPENDENT_CODE ON)

    # Define variables
    set(FORTRAN_PYF_FILE ${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/geopack.pyf)
    set(FORTRAN_SRC_FILE ${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/geopack.f)
    set(FORTRAN_T96_FILE ${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/T96.f)
    set(FORTRAN_T02_FILE ${CMAKE_CURRENT_SOURCE_DIR}/src/tsyganenko/T02.f)
    set(MODULE_NAME geopack_tsyganenko)
    set(F2PY_MODULE ${CMAKE_CURRENT_BINARY_DIR}/${MODULE_NAME}module.c)
    set(F2PY_WRAPPERS ${CMAKE_CURRENT_BINARY_DIR}/${MODULE_NAME}-f2pywrappers.f)

    add_custom_command(
    OUTPUT ${F2PY_MODULE} ${F2PY_WRAPPERS}
    DEPENDS
    ${FORTRAN_PYF_FILE}
    ${FORTRAN_SRC_FILE}
    ${FORTRAN_T96_FILE}
    ${FORTRAN_T02_FILE}
    VERBATIM
    COMMAND "${PYTHON_EXECUTABLE}" -m numpy.f2py
    "${FORTRAN_PYF_FILE}"
    "${FORTRAN_SRC_FILE}"
    "${FORTRAN_T96_FILE}"
    "${FORTRAN_T02_FILE}"
    -m ${MODULE_NAME}
    --lower
    )

    python_add_library(
    geopack_tsyganenko MODULE "${F2PY_MODULE}"
    "${F2PY_WRAPPERS}"
    "${FORTRAN_PYF_FILE}"
    "${FORTRAN_SRC_FILE}"
    "${FORTRAN_T96_FILE}"
    "${FORTRAN_T02_FILE}"
    WITH_SOABI)
    target_link_libraries(${MODULE_NAME} PRIVATE fortranobject)

    install(TARGETS ${MODULE_NAME} DESTINATION .)

    Continue reading...

Compartilhe esta Página