How To Build A Python Wheel With Compiled Fortran Extension Module Without Requiring A Specific Mingw Version On The User's System?
Solution 1:
I recently ran into this issue by writing my own f2py building tool chain by compiling and linking all the components individually. The script was finding or installing required compilers automatically if they werent already found on the path. For cases where the gfortran tools werent on the path, but were present on the machine, I was able to inject the correct environment variables to os.environ
and spawn compiler calls using Popen
and the set of environment variables so that the pyd would compile. But outside of that python instance the environment variables were not correct for the pyd to run, I was getting the same DLL load failed
error even on the same computer that compiled the pyds but which didnt have the correct paths setup.
So, since I'm compiling all steps separately, only using f2py to generate the f and c wrappers, I simply added -static -static-libgfortran -static-libgcc
to my link step, and this causes the pyd to include the required libraries to run on those machines without the correct environment variables.
Achieving the same using numpy.distutils is possible (thanks to https://github.com/numpy/numpy/issues/3405):
from numpy.distutils.core import Extension, setup
if__name__== "__main__":
setup(
name="this",
ext_modules=[
Extension("fortmod_nostatic",
["src/code.f90"],
),
Extension("fortmod_withstatic",
["src/code.f90"],
extra_link_args=["-static", "-static-libgfortran", "-static-libgcc"]
)
]
)
I put the above in a file test.py
and built with python test.py build_ext --inplace --compiler=mingw32 --fcompiler=gnu95 -f
For comparison there is a clear size difference. Inspecting the pyd's with dependency walker shows the nostatic one depends on libgfortran-4.dll
whereas the extra flags generate a pyd that does not depend on this library. In my case after adding the static flags the machine without correct environment variables is able to run the pyds, and I suspect this case will be similar to yours since the dependency on libgfortran is removed.
Hope that helps! my first SO post..
Solution 2:
I can confirm that the steps described in rmar_'s answer create a pyd file that can be imported from a machine that has no MinGW installed. This is really helpful!
In order to create a binary wheel, I do the following:
- Follow the steps described in rmar_'s answer in order to generate statically linked pyd files in place.
- Run
python setup.py bdist_wheel
afterwards.
For the second step, I switch off the compilation of the pyd file (e.g., by removing the ext_modules
keyword from the setup()
call), because I want that the pyd file created in the first step is used (and not a newly created, which might be not statically linked).
I don't know if this makes sense at all, but it seems to work ...
Post a Comment for "How To Build A Python Wheel With Compiled Fortran Extension Module Without Requiring A Specific Mingw Version On The User's System?"