2013-10-11 16 views
6

Sto cercando di usare f2py per interfacciare i miei programmi python con i miei moduli Fortran.f2py con il compilatore Intel Fortran

Sono su una piattaforma Win7.

Io uso l'ultimo Anaconda 64 (1.7) come stack Python + NumPy.

Il mio compilatore Fortran è l'ultimo compilatore Intel Fortran 64 (versione 14.0.0.103 Build 20130728).

Ho sperimentato una serie di questioni durante l'esecuzione f2py -c -m PyModule FortranModule.f90 --fcompiler=intelvem

L'ultimo, che non riesco a risolvere è che sembra che la sequenza delle bandiere f2py/distutils passa al compilatore non lo fa corrisponde a ciò che ifort si aspetta.

Ricevo una serie di messaggi di avviso relativi alle opzioni sconosciute quando viene invocato 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' 

ho il sospetto questo è legato agli errori che ricevo da linker alla fine

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) 

e si conclude con una pianura

fatal error LNK1120: 42 unresolved externals 

La mia ipotesi è che questo è dovuto al fatto il flag/link manca nella sequenza di opzioni. Per questo motivo, le opzioni/l/L non vengono passate al linker e il compilatore crede che queste siano indirizzate a lui.

Il comando ifort generato da f2py assomiglia a questo:

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

ho idea perché il "-dll" viene ripetuto due volte (ho dovuto cambiare quella bandiera da un originale "-shared").

Ora, ho cercato di esaminare i codici f2py e distutils ma non ho capito come schiacciare un ulteriore/link nell'output del comando. Non sono nemmeno stato in grado di individuare dove viene generato questo output.

Se qualcuno ha riscontrato questo problema in passato e/o potrebbe avere qualche suggerimento, lo apprezzerei molto.

Grazie per il vostro tempo

+1

ho incontrato problemi come questi, ma sfortunatamente non sono riuscito a trovare un modo per aggirarli; Ho finito per creare un Makefile che ha accartocciato tutto insieme. Ecco il Makefile: http://pastebin.com/ChSxLzSb. – bdforbes

+0

Grazie per il file! Ho avuto la possibilità di vederlo solo oggi. Finì per essere un problema enorme per farlo funzionare a causa di un sacco di percorsi giocherellando e vari file da recuperare. Ma alla fine sono stato in grado di fare ciò che volevo. Penso che sia molto difficile trovare una risposta definitiva in quanto sembra altamente dipendente dalla piattaforma e dalle catene di strumenti installate. – Tesla

+0

Quindi qual è stato il tuo approccio alla fine? Sei riuscito a incidere le distutili nella sottomissione? – bdforbes

risposta

0

Il percorso della libreria viene specificato utilizzando/LIBPATH non/L

+0

Grazie. Scusate per il feedback tardivo, non avevo notato il commento di febbraio ... Questo in realtà non risponde alla domanda. Infatti, per ifort, sarebbe/libdir. La vera domanda è "come si cambia il modo in cui dist-utils genera l'elenco degli argomenti del compilatore?". Al momento, la soluzione di bdforbes di usare un makefile funziona, ma sarebbe bello se f2py potesse gestire tutto il problema. – Tesla

3

ho incontrato problemi simili con il mio proprio codice di qualche tempo fa. Se capisco correttamente i commenti hai già utilizzato l'approccio che ha funzionato per me, quindi questo è solo inteso come chiarimento e sintesi per tutti coloro che lottano con f2py e dipendenze:

f2py sembra avere problemi a risolvere dipendenze su file di origine esterni . Se le dipendenze esterne vengono passate a f2py come file di oggetti già compilati, il collegamento funziona correttamente e la libreria Python viene creata senza problemi.

La soluzione più semplice sembra quindi essere:

  1. compilazione tutte le dipendenze per oggetto i file (*.o) utilizzando le impostazioni del compilatore e del compilatore di prefered
  2. passaggio tutti i file oggetto di f2py, insieme con il file di origine della vostra// modulo principale subroutine funzione/...
  3. uso generato libreria Python come previsto

Un semplice Skript pitone potrebbe essere il seguente (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) 

Una soluzione più flessibile per l progetti arge potrebbero essere forniti tramite Makefile, come dicussed dalle @bdforbes nei commenti (for reference) o un costume CMake comando utente in combinazione con lo Skript sopra:

############################################################################### 
# 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) 

con pycompile modificata:

#!python.exe 
# -*- coding: UTF-8 -*- 
... 
fortran_source = ("@[email protected]/source_1.f90 " 
        "@[email protected]/source_2.f90 "     
        "...") 
... 
# add path to source code/ dependencies 
f2py_source = ("-m for_to_py_lib " 
       "@[email protected]/for_to_py.f90 " 
       "source_1.o " 
       "source_2.o " 
       "... " 
       ) 
... 

# compile .o and .mod files 
...