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