Translate F2PY compile steps in setup.py

I inherited Fortran 77 code that implements several subroutines that are run through a program block that requires a significant amount of user input through an interactive command line each time the program is run. Since I would like to automate the running of the code, I moved all the subroutines to a module and wrote the wrapper code via F2PY. Everything works fine after a two-step compilation:

gfortran -c my_module.f90 -o my_module.o -ffixed-form
f2py -c my_module.o -m my_wrapper my_wrapper.f90

      

As a result, it creates three files: my_module.o

, my_wrapper.o

, my_module.mod

and my_wrapper.so

. my_wrapper.so

is a module that I import into Python to access legacy Fortran code.

My goal is to include this code for use in a larger scientific code package that I already have setup.py

using distutils

Cython to create a module. Completely ignoring the Cython code for now, how am I supposed to translate a two-step build into an extension in setup.py

? The closure I was able to figure out looks like this:

from numpy.distutils.core import setup, Extension
wrapper = Extension('my_wrapper', ['my_wrapper.f90', ])
setup(
    libraries = [('my_module', dict(sources=['my_module.f90']],
                                    extra_f90_compile_args=["-ffixed-form", ])))],
    ext_modules = [wrapper, ]
)

      

This does not work. My compiler throws a lot of warnings on my_module.f90

, but it still compiles (it doesn't throw any warnings if I use the compiler call above). However, when it tries to compile the shell, it cannot find my_module.mod

it even though it is successfully created.

Any thoughts? I have a feeling that I am missing something trivial, but the documentation just doesn't seem to be enough to indicate what it might be.

+5


source to share


2 answers


Maybe a little late, but your problem is that you are not linking in my_module

when building my_wrapper

:

wrapper = Extension('my_wrapper', sources=['my_wrapper.f90'], libraries=['my_module'])

setup(
    libraries = [('my_module', dict(sources=['my_module.f90'],
                                    extra_f90_compile_args=["-ffixed-form"]))],
    ext_modules = [wrapper]
)

      

If your use is my_module

for my_wrapper

, you can simply add it to sources my_wrapper

:



wrapper = Extension('my_wrapper', sources=['my_wrapper.f90', 'my_module.f90'],
                                  extra_f90_compile_args=["-ffixed-form"])
setup(
    ext_modules = [wrapper]
)

      

Note that this also exports everything in my_module

Python, which you probably don't want.

I am dealing with such a two-layer library structure outside of Python, using cmake

as a top-level build system. I have a setup so that it make python

calls distutils to create Python wrappers. setup.py

can safely assume that all external libraries have already been created and installed. This strategy is beneficial if you want to have a general-purpose libraries that are installed on the system level, and then wrapped for different applications, such as Python

, Matlab

, Octave

, IDL

, ..., which all have different ways to create extensions.

+5


source


I would like to revisit the OP's question as I have a slightly more complex case.

I am working on a package that includes many subpackages, some of which contain Fortran source code that I compiled with f2py during development.

Now I want to write a file setup.py

for a package for distribution.

Let's say I used the following f2py command to compile:

f2py -c --fcompiler='intelem' --opt='-xhost -O3 -ipo' \
    --f90flags='-qopenmp -qopenmp-link=static -static-intel' \
    -I/opt/intel/include -L/opt/intel/lib -liomp5 \
    -m module_name module_name.f90 \
    only: subroutine_1 subroutine_2 ... subroutine_n :

      



Can I transfer the whole argument this command keyword f2py_options

in numpy.distutils.core.Extension

or do I need to break it up: include_dirs

, library_dirs

, libraries

, extra_f90_compile_args

and so on?

Where are the --opt

flags --opt

? and only:... :

announcement?

One more question: can I have a different set of compiler options (gnu / intel) and pass the keyword argument to setup.py? is this best practice?

Thank!

0


source







All Articles