Cython und fortran - wie man ohne f2py zusammen kompiliert
ENDGÜLTIGES UPDATE
In dieser Frage geht es darum, wie man einesetup.py
Dadurch wird ein Cython-Modul kompiliert, das wie C direkt auf FORTRAN-Code zugreift. Es war ein ziemlich langer und mühsamer Weg zur Lösung, aber das ganze Durcheinander ist unten für den Kontext aufgeführt.
URSPRÜNGLICHE FRAGE
Ich habe eine Erweiterung, die eine Cython-Datei ist, die einen Heap-Speicher einrichtet und ihn an den fortran-Code übergibt, und eine fortran-Datei, die ein ehrwürdiges altes Modul ist, das ich gerne vermeiden würde, wenn ich kann, neu zu implementieren.
Das.pyx
Datei kompiliert gut zu C, aber der Cython-Compiler drosselt auf der.f90
Datei mit folgendem Fehler:
$ python setup.py build_ext --inplace
running build_ext
cythoning delaunay/__init__.pyx to delaunay/__init__.c
building 'delaunay' extension
error: unknown file type '.f90' (from 'delaunay/stripack.f90')
Hier ist (die obere Hälfte von) meiner Setup-Datei:
from distutils.core import setup, Extension
from Cython.Distutils import build_ext
ext_modules = [
Extension("delaunay",
sources=["delaunay/__init__.pyx",
"delaunay/stripack.f90"])
]
setup(
cmdclass = {'build_ext': build_ext},
ext_modules = ext_modules,
...
)
ANMERKUNG: Ich hatte ursprünglich den Speicherort der fortran-Datei falsch angegeben (ohne das Verzeichnispräfix), aber dies bricht genauso ab, nachdem ich das behoben habe.
Dinge, die ich versucht habe:
ich fanddieseund haben versucht, den Namen des fortran-Compilers (d. h. gfortran) wie folgt einzugeben:
$ python setup.py config --fcompiler=gfortran build_ext --inplace
usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
or: setup.py --help [cmd1 cmd2 ...]
or: setup.py --help-commands
or: setup.py cmd --help
error: option --fcompiler not recognized
Und ich habe auch versucht, zu entfernen--inplace
, falls das das Problem war (es war nicht dasselbe wie die oberste Fehlermeldung).
Wie kompiliere ich dieses Fortran? Kann ich es in eine hacken?.o
mich und mit dem Verlinken davonkommen? OderIst das ein Fehler in Cython?, was mich zwingt, distutils neu zu implementieren oder mit dem Präprozessor herumzuhacken?
AKTUALISIEREN
Also nach dem Auschecken dernumpy.distutils
Pakete verstehe ich das Problem ein bisschen mehr. Es scheint, dass Sie müssen
Extension
/setup()
Kombination, die fortran unterstützt, wienumpy
's.Nachdem ich das versucht habe, meine Gütesetup.py
sieht jetzt so aus:
from numpy.distutils.core import setup
from Cython.Build import cythonize
from numpy.distutils.extension import Extension
cy_modules = cythonize('delaunay/sphere.pyx')
e = cy_modules[0]
ext_modules = [
Extension("delaunay.sphere",
sources=e.sources + ['delaunay/stripack.f90'])
]
setup(
ext_modules = ext_modules,
name="delaunay",
...
)
(beachte, dass ich das Modul auch ein wenig umstrukturiert habe, da es anscheinend eine__init__.pyx
ist nicht erlaubt ...)
Jetzt werden die Dinge fehlerhaft und plattformabhängig. Ich habe zwei Testsysteme zur Verfügung - ein Mac OS X 10.6 (Snow Leopard) mit Macports Python 2.7 und ein Mac OS X 10.7 (Lion) mit System Python 2.7.
Auf Snow Leopard gilt Folgendes:
Dies bedeutet, dass das Modul kompiliert (Hurra!) (Obwohl es keine gibt--inplace
Für Numpy, so scheint es, musste ich das Testmodul systemweit installieren: /), aber ich bekomme immer noch einen Absturz aufimport
wie folgt:
>>> import delaunay
Traceback (most recent call last):
File "<input>", line 1, in <module>
File "<snip>site-packages/delaunay/__init__.py", line 1, in <module>
from sphere import delaunay_mesh
ImportError: dlopen(<snip>site-packages/delaunay/sphere.so, 2): no suitable image found. Did find:
<snip>site-packages/delaunay/sphere.so: mach-o, but wrong architecture
und auf Lion erhalte ich einen Kompilierungsfehler, der einer ziemlich verwirrend aussehenden Kompilierungszeile folgt:
gfortran:f77: build/src.macosx-10.7-intel-2.7/delaunay/sphere-f2pywrappers.f
/usr/local/bin/gfortran -Wall -arch i686 -arch x86_64 -Wall -undefined dynamic_lookup -bundle build/temp.macosx-10.7-intel-2.7/delaunay/sphere.o build/temp.macosx-10.7-intel-2.7/build/src.macosx-10.7-intel-2.7/delaunay/spheremodule.o build/temp.macosx-10.7-intel-2.7/build/src.macosx-10.7-intel-2.7/fortranobject.o build/temp.macosx-10.7-intel-2.7/delaunay/stripack.o build/temp.macosx-10.7-intel-2.7/build/src.macosx-10.7-intel-2.7/delaunay/sphere-f2pywrappers.o -lgfortran -o build/lib.macosx-10.7-intel-2.7/delaunay/sphere.so
ld: duplicate symbol _initsphere in build/temp.macosx-10.7-intel-2.7/build/src.macosx-10.7-intel-2.7/delaunay/spheremodule.o ldand :build /temp.macosx-10.7-intelduplicate- 2.7symbol/ delaunay/sphere.o _initsphere in forbuild architecture /i386
temp.macosx-10.7-intel-2.7/build/src.macosx-10.7-intel-2.7/delaunay/spheremodule.o and build/temp.macosx-10.7-intel-2.7/delaunay/sphere.o for architecture x86_64
Lassen Sie uns jetzt einen Moment zurücktreten, bevor wir uns hier mit den Details befassen. Erstens weiß ich, dass Architekturkonflikte unter 64-Bit-Mac OS X Kopfzerbrechen bereiten. Ich musste sehr hart arbeiten, um Macports Python auf dem Snow Leopard-Computer zum Laufen zu bringen (nur um ein Upgrade von System Python 2.6 durchzuführen). Das weiß ich auch, wenn du es siehstgfortran -arch i686 -arch x86_64
Sie senden gemischte Nachrichten an Ihren Compiler. Dort stecken alle möglichen plattformspezifischen Probleme, über die wir uns im Zusammenhang mit dieser Frage keine Gedanken machen müssen.
Aber schauen wir uns nur diese Zeile an: gfortran:f77: build/src.macosx-10.7-intel-2.7/delaunay/sphere-f2pywrappers.f
Was macht Numpy ?! Ich benötige keine f2py-Funktionen in diesem Build! Ich habe tatsächlich ein Cython-Modul geschriebenum zu vermeiden Umgang mit dem Wahnsinn von f2py (Ich brauche 4 oder 5 Ausgangsvariablen sowie weder In- noch Out-Argumente - beides wird in f2py nicht gut unterstützt.) Ich möchte nur, dass es kompiliert wird.c
->.o
, und.f90
->.o
und verknüpfe sie. Ich könnte diese Compiler-Zeile selbst schreiben, wenn ich wüsste, wie man alle relevanten Header einfügt.
Bitte sagen Sie mir, dass ich dafür kein eigenes Makefile schreiben muss ... oder dass es eine Möglichkeit gibt, fortran in (ausgangskompatibles) C zu übersetzen, damit Python die .f90-Erweiterung nie sieht (was das Ganze behebt) Problem.) Beachten Sie, dassf2c
ist dafür nicht geeignet, da es nur auf F77 funktioniert und dies ein moderner Dialekt ist (daher das.f90
Dateierweiterung).
UPDATE 2 Das folgende Bash-Skript kompiliert und verknüpft den Code problemlos:
PYTHON_H_LOCATION="/opt/local/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7/"
cython sphere.pyx
gcc -arch x86_64 -c sphere.c -I$PYTHON_H_LOCATION
gfortran -arch x86_64 -c stripack.f90
gfortran -arch x86_64 -bundle -undefined dynamic_lookup -L/opt/local/lib *.o -o sphere.so
Irgendwelche Ratschläge, wie man diese Art von Hack mit einem setup.py kompatibel macht? Ich muss niemanden finden, der dieses Modul installiertPython.h
manuell...