Here's my directory structure,
├── test
│ ├── test.f90
│ ├── __init__.py
│ └── test.py
Now I want to make a package from this with an command line tool test
.
Now I have two options, 1. numpy distutils and 2. setuptools.
Problem with distutils
is that it doesn't support entry points and it is also not recomended now. But it does compile the fortran code perfectly.
Now as for setuptools I'm trying to use this code,
mod = Extension(name = 'foo.adt', sources = ['test/test.f90'])
setup(
name = 'foo',
packages = ['foo'],
package_dir = {'foo':'test'},
ext_modules = [mod],
entry_points={
'console_scripts': [
'hello = foo.test:main',
],
}
)
If I try to use this, it's throwing this error
error: unknown file type '.f90' (from 'test/test.f90')
So, I guess setuptools doesn't support fortran files? So, how do I compile the fortran code, create the package and create a entry point for that?
It's actually a pretty simple trick. Just import setuptools
before importing setup
from numpy.distutils.core
and you're good to go. The explanation for this is that numpy.distutils
is much more than just the vanilla distutils
with some package-specific tweaks. In particular, numpy.distutils
checks whether setuptools
is available and if so, uses it where possible under the hood. If you're interested, look at the module's source code, paying attention to the usages of have_setuptools
flag.
As usual, a Minimal, Complete, and Verifiable example:
so-55352409/
├── spam
│ ├── __init__.py
│ ├── cli.py
│ └── libfib.f90
└── setup.py
setup.py
:import setuptools # this is the "magic" import
from numpy.distutils.core import setup, Extension
lib = Extension(name='spam.libfib', sources=['spam/libfib.f90'])
setup(
name = 'spamlib',
packages = ['spam'],
ext_modules = [lib],
entry_points={
'console_scripts': [
'hello = spam.cli:main',
],
}
)
spam/cli.py
:from spam.libfib import fib
def main():
print(fib(10))
spam/libfib.f90
:C FILE: LIBFIB.F90
SUBROUTINE FIB(A,N)
C
C CALCULATE FIRST N FIBONACCI NUMBERS
C
INTEGER N
REAL*8 A(N)
Cf2py intent(in) n
Cf2py intent(out) a
Cf2py depend(n) a
DO I=1,N
IF (I.EQ.1) THEN
A(I) = 0.0D0
ELSEIF (I.EQ.2) THEN
A(I) = 1.0D0
ELSE
A(I) = A(I-1) + A(I-2)
ENDIF
ENDDO
END
C END FILE LIBFIB.F90
Build and install the package:
$ cd so-55352409
$ python setup.py bdist_wheel
...
$ pip install dist/spamlib-0.0.0-cp36-cp36m-linux_x86_64.whl
...
$ hello
[ 0. 1. 1. 2. 3. 5. 8. 13. 21. 34.]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With