f2py 与英特尔 Fortran 编译器 [英] f2py with Intel Fortran compiler

查看:25
本文介绍了f2py 与英特尔 Fortran 编译器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 f2py 将我的 python 程序与我的 Fortran 模块接口.

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

我在 Win7 平台上.

I am on a Win7 platform.

我使用最新的 Anaconda 64 (1.7) 作为 Python+NumPy 堆栈.

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

我的 Fortran 编译器是最新的 Intel Fortran 编译器 64(版本 14.0.0.103 Build 20130728).

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

我在执行 f2py -c -m PyModule FortranModule.f90 --fcompiler=intelvem

我似乎无法理清的最后一个问题是 f2py/distutils 传递给编译器的标志序列与 ifort 期望的不匹配.

The last one, which I can't seem to sort out is that it looks like the sequence of flags f2py/distutils passes to the compiler does not match what ifort expects.

在调用 ifort 时,我收到一系列有关未知选项的警告消息.

I get a series of warning messages regarding unknown options when ifort is invoked.

ifort: command line warning #10006: ignoring unknown option '/LC:Anacondalibs'
ifort: command line warning #10006: ignoring unknown option'/LC:AnacondaPCbuildamd64'
ifort: command line warning #10006: ignoring unknown option '/lpython27'

我怀疑这与我最后从链接器得到的错误有关

I suspect this is related to the errors 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)

它以一个简单的结尾

fatal error LNK1120: 42 unresolved externals

我的猜测是,这是因为选项序列中缺少/link 标志.因此,/l/L 选项不会传递给链接器,编译器认为这些选项是针对他的.

My guess is that this is because the /link flag is missing in the sequence of options. Because of this, the /l /L options are not passed to the linker and the compiler believes these are addressed to him.

f2py生成的ifort命令如下:

The ifort command generated by f2py looks like this:

ifort.exe -dll -dll Pymodule.o fortranobject.o FortranModule.o module-f2pywrappers2.o -LC:Anacondalibs -LC:AnacondaPCbuildamd64 -lPython27

我不知道为什么-dll"重复了两次(我不得不从原来的-shared"更改那个标志).

I have no idea why the "-dll" is repeated twice (I had to change that flag from an original "-shared").

现在,我尝试查看 f2py 和 distutils 代码,但还没有弄清楚如何在命令输出中添加额外的/link.我什至无法找到生成此输出的位置.

Now, I have tried to look into the f2py and distutils codes but haven't figured out how to bodge an additional /link in the command output. I haven't even been able to locate where this output is generated.

如果有人过去遇到过这个问题和/或可能有一些建议,我将非常感激.

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

感谢您的宝贵时间

推荐答案

前段时间我自己的代码也遇到过类似的问题.如果我正确理解评论,您已经使用了对我有用的方法,所以这只是对所有与 f2py 和依赖关系斗争的人的澄清和总结:

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 似乎无法解决对外部源文件的依赖问题.如果外部依赖项作为已编译的目标文件传递给 f2py,则链接工作正常,python 库构建没有问题.

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. 使用您喜欢的编译器和编译器设置将所有依赖项编译为目标文件 (*.o)
  2. 将所有目标文件连同主子例程/函数/模块/的源文件一起传递给 f2py ...
  3. 按预期使用生成的 python 库
  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

一个简单的 python 脚本可能如下所示(pycompile.py):

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)

<小时>

可以通过 Makefile 为大型项目提供更灵活的解决方案,正如 @bdforbes 在评论中所讨论的(供参考)或自定义CMake用户命令结合上述脚本:


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 "
***************************************************************************************************

 copy of python library for_to_py${CMAKE_PYTHON_LIBRARY_SUFFIX} placed in ${lib_root}/for_to_py${CMAKE_PYTHON_LIBRARY_SUFFIX} 

***************************************************************************************************"
                       )
endif (PYTHONINTERP_FOUND)

修改后的 pycompile:

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
...

这篇关于f2py 与英特尔 Fortran 编译器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆