Sunday 26 June 2022

How to build Python package with fortran extension

I've made a Python package that contains a fortran extension. When i run pip install -e . to test it locally works, but when I build the wheels and upload them to PyPI, and then pip install my_package this is what I get when I import it:

ImportError: DLL load failed while importing functions: The specified module could not be found.

The setup.py looks like this:

from numpy.distutils.core import Extension, setup
...
extension = Extension(name='my_package.fortran.functions',
                          sources=['my_package/fortran/erf.f', 'my_package/fortran/erf.pyf'],
                          extra_link_args=["-static", "-static-libgfortran", "-static-libgcc"],)
                          #extra_compile_args=['/d2FH4-'] if sys.platform == 'win32' else [])

setup(
...
ext_modules=[extension]
...
)

And the workflow looks like this:

name: Build

on:
  release:
    types: [created]

jobs:
  build_wheels:
    name: Build wheels on $
    runs-on: $
    strategy:
      matrix:
        #os: [ubuntu-latest, windows-latest, macos-latest]
        os: [windows-latest]
        gcc_v: [10]
    env:
      FC: gfortran-$
      GCC_V: $

    steps:
      - uses: actions/checkout@v3

      # Used to host cibuildwheel
      - uses: actions/setup-python@v3

      - name: Install dependencies
        run: pip install -e ../intelligen

      - name: Install cibuildwheel
        run: python -m pip install cibuildwheel==2.4.0

      - name: Install GFortran Linux
        if: contains(matrix.os, 'ubuntu')
        run: |
          sudo add-apt-repository ppa:ubuntu-toolchain-r/test
          sudo apt-get update
          sudo apt-get install -y gcc-${GCC_V} gfortran-${GCC_V}
          sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_V} 100 \
          --slave /usr/bin/gfortran gfortran /usr/bin/gfortran-${GCC_V} \
          --slave /usr/bingcov gcov /usr/bin/gcov-${GCC_V}

      - name: Install GFortran macos
        if: contains(matrix.os, 'macos')
        run: brew install gcc@${GCC_V} || brew upgrade gcc@${GCC_V} || true

      - name: Build wheels
        run: python -m cibuildwheel --output-dir dist
        # to supply options, put them in 'env', like:
        # env:
        #   CIBW_SOME_OPTION: value
        env:
          CIBW_BEFORE_BUILD: pip install certifi oldest-supported-numpy
          CIBW_BUILD: cp36-* cp37-* cp38-* cp39-* cp310-*
          #CIBW_BEFORE_BUILD_WINDOWS: pip install delvewheel
          #CIBW_REPAIR_WHEEL_COMMAND_WINDOWS: delvewheel repair -w {dest_dir} {wheel}

      - uses: actions/upload-artifact@v3
        with:
          path: ./dist/*.whl

I was having problems with ubuntu and macos so those os are commented, but I would like to build for those too.

The install dependencies is there trying to resolve this issue.

I'm only building for CPython because Pypy was giving problems.

delvewheel is commented because this error was poping:

FileNotFoundError: Unable to find library: liberf.qnh5sc52t4pc5446h2dbxzj22hkv2erk.gfortran-win32.dll

How can I avoid the first error with the dll?

How can I build a python package with compiled code for all platforms?

This is the package for what it's worth



from How to build Python package with fortran extension

No comments:

Post a Comment