f2py with Intel Fortran compiler

前端 未结 2 637
我在风中等你
我在风中等你 2020-12-16 05:35

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

I am on a Win7 platform.

I use latest Anaconda 64 (1.7) as a Python+NumPy st

相关标签:
2条回答
  • 2020-12-16 06:26

    The library path is specified using /LIBPATH not /L

    0 讨论(0)
  • 2020-12-16 06:32

    I encountered similar problems with my own code some time ago. If I understand the comments correctly you already used the approach that worked for me, so this is just meant as clarification and summary for all those that struggle with f2py and dependencies:

    f2py seems to have problems resolving dependecies on external source files. If the external dependencies get passed to f2py as already compiled object files though, the linking works fine and the python library gets build without problems.

    The easiest solution therefore seems to be:

    1. compile all dependencies to object files (*.o) using your prefered compiler and compiler settings
    2. pass all object files to f2py, together with the source file of your main subroutine/ function/ module/ ...
    3. use generated python library as expected

    A simple python skript could 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 could be provided via Makefile, as dicussed by @bdforbes in the comments (for reference) or a custom CMake User Command in combination with the above skript:

    ###############################################################################
    # 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
    ...
    
    0 讨论(0)
提交回复
热议问题