F2py with Intel Fortran Compiler

I am trying to use f2py to interact with my python programs with my Fortran modules.

I am on a Win7 platform.

I am using the latest version of Anaconda 64 (1.7) as a Python + NumPy stack.

My Fortran compiler is the latest Intel Fortran 64 compiler (version 14.0.0.103 Build 20130728).

I had a lot of problems running f2py -c -m PyModule FortranModule.f90 --fcompiler=intelvem

The last one, which I do not seem to understand, is that it looks like the sequence of f2py / distutils flags passed to the compiler does not meet ifort expectations.

I get a series of warning messages about unknown parameters when calling ifort.

 ifort: command line warning #10006: ignoring unknown option '/LC:\Anaconda\libs' ifort: command line warning #10006: ignoring unknown option'/LC:\Anaconda\PCbuild\amd64' ifort: command line warning #10006: ignoring unknown option '/lpython27' 

I suspect this is due to errors that I get from the linker at the end

 error LNK2019: unresolved external symbol __imp_PyImport_ImportModule referenced in function _import_array error LNK2019... and so forth (there are about 30-40 lines like that, with different python modules missing) 

and ends simple

 fatal error LNK1120: 42 unresolved externals 

I assume this is because the / link flag is missing in the parameter sequence. Because of this, the / l / L options are not passed to the linker, and the compiler thinks they are addressed to it.

The ifort command generated by f2py looks like this:

 ifort.exe -dll -dll Pymodule.o fortranobject.o FortranModule.o module-f2pywrappers2.o -LC:\Anaconda\libs -LC:\Anaconda\PCbuild\amd64 -lPython27 

I do not know why "-dll" is repeated twice (I had to change this flag from the original "-shared").

Now I tried to learn the f2py and distutils codes, but did not understand how to add an extra / link to the output of the command. I could not even find where this output is generated.

If someone has encountered this problem in the past and / or may have some suggestions, I would really appreciate it.

thank you for your time

+6
source share
2 answers

I ran into similar problems with my own code some time ago. If I understand the comments correctly, you have already used the approach that worked for me, so this just means clarification and summary for all those struggling with f2py and dependencies:

f2py seems to have problems resolving dependencies in external source files. If external dependencies are passed to f2py as object files already compiled, then the connection works fine and the python library becomes no problem.

Thus, the simplest solution is:

  • compile all dependencies to object files (* .o) using preferred compiler and compiler options.
  • transfer all object files to the f2py file along with the source file of your main routine / function / module / ...
  • use the generated python library as expected

A simple python script might look like this (pycompile.py):

 #!python.exe # -*- coding: UTF-8 -*- import os import platform '''Uses f2py to compile needed library''' # build command-strings # command for compling *.o and *.mod files fortran_exe = "gfortran " # fortran compiler settings fortran_flags = "<some_gfortran_flags> " # add path to source code fortran_source = ("./relative/path/to/source_1.f90 " "C:/absolut/path/to/source_2.f90 " "...") # assemble fortran command fortran_cmd = fortran_exe + fortran_flags + fortran_source # command for compiling main source file using f2py f2py_exe = "f2py -c " # special compiler-options for Linux/ Windows if (platform.system() == 'Linux'): f2py_flags = "--compiler=unix --fcompiler=gnu95 " elif (platform.system() == 'Windows'): f2py_flags = "--compiler=mingw32 --fcompiler=gnu95 " # add path to source code/ dependencies f2py_source = ("-m for_to_py_lib " "./path/to/main_source.f90 " "source_1.o " "source_2.o " "... " ) # assemble f2py command f2py_cmd = f2py_exe + f2py_flags + f2py_source # compile .o and .mod files print "compiling object- and module-files..." print print fortran_cmd os.system(fortran_cmd) # compile main_source.f90 with f2py print "================================================================" print "start f2py..." print print f2py_cmd os.system(f2py_cmd) 

A more flexible solution for large projects can be provided through a Makefile, as @bdforbes says in the comments ( for reference ) or a custom CMake command command in combination with the above script:

 ############################################################################### # General project properties ################################################################################ # Set Project Name project (for_to_py_lib) # Set Version Number set (for_to_py_lib_VERSION_MAJOR 1) set (for_to_py_lib_VERSION_MINOR 0) # save folder locations for later use/ scripting (see pycompile.py) # relative to SOURCE folder set(source_root ${CMAKE_CURRENT_LIST_DIR}/SOURCE) # save top level source dir for later use set(lib_root ${CMAKE_CURRENT_LIST_DIR}/LIBRARIES) # save top level lib dir for later use # relative to BUILD folder set(build_root ${CMAKE_CURRENT_BINARY_DIR}) # save top level build dir for later use ### ### Fortran to Python library ### find_package(PythonInterp) if (PYTHONINTERP_FOUND) # copy python compile skript file to build folder and substitute CMake variables configure_file(${source_root}/pycompile.py ${build_root}/pycompile.py @ONLY) # define for_to_py library ending if (UNIX) set(CMAKE_PYTHON_LIBRARY_SUFFIX .so) elseif (WIN32) set(CMAKE_PYTHON_LIBRARY_SUFFIX .pyd) endif() # add custom target to ALL, building the for_to_py python library (using f2py) add_custom_target(for_to_py ALL DEPENDS ${build_root}/for_to_py${CMAKE_PYTHON_LIBRARY_SUFFIX}) # build command for python library (execute python script pycompile.py containing the actual build commands) add_custom_command(OUTPUT ${build_root}/for_to_py${CMAKE_PYTHON_LIBRARY_SUFFIX} COMMAND ${PYTHON_EXECUTABLE} ${build_root}/pycompile.py WORKING_DIRECTORY ${build_root} DEPENDS ${build_root}/pycompile.py ${source_root}/path/to/source_1.f90 ${source_root}/path/to/source_2.f90 ${source_root}/INOUT/s4binout.f90 COMMENT "Generating fortran to python library") # post build command for python library (copying of generated files) add_custom_command(TARGET for_to_py POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${build_root}/s4_to_py${CMAKE_PYTHON_LIBRARY_SUFFIX} ${lib_root}/for_to_py${CMAKE_PYTHON_LIBRARY_SUFFIX} COMMENT "\ ***************************************************************************************************\n\ copy of python library for_to_py${CMAKE_PYTHON_LIBRARY_SUFFIX} placed in ${lib_root}/for_to_py${CMAKE_PYTHON_LIBRARY_SUFFIX} \n\ ***************************************************************************************************" ) endif (PYTHONINTERP_FOUND) 

with modified pycompile:

 #!python.exe # -*- coding: UTF-8 -*- ... fortran_source = ("@ source_root@ /source_1.f90 " "@ source_root@ /source_2.f90 " "...") ... # add path to source code/ dependencies f2py_source = ("-m for_to_py_lib " "@ build_root@ /for_to_py.f90 " "source_1.o " "source_2.o " "... " ) ... # compile .o and .mod files ... 
+3
source

The library path is specified using / LIBPATH not / L

0
source

Source: https://habr.com/ru/post/955786/


All Articles