From 11caa97e75bf1a038ce789d42107be3c0013ed0b Mon Sep 17 00:00:00 2001 From: Marco Galardini Date: Tue, 26 Nov 2019 17:06:38 -0500 Subject: [PATCH 1/2] Fix build by invoking gfortran directly Relatively ugly hack to allow downstream packages to use the library --- setup.py | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/setup.py b/setup.py index c48cb2d..30707f1 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,26 @@ import os, sys from setuptools import setup, find_packages +from setuptools.command.build_py import build_py import subprocess +class Compile(build_py): + """Custom build setup to help run needed shell commands + + Inspired by https://stackoverflow.com/a/27953695/1237531""" + def run(self): + dir_path = os.path.dirname(os.path.realpath(__file__)) + source_path = os.path.join(dir_path, 'glmnet_python/GLMnet.f') + output_path = os.path.join(dir_path, 'glmnet_python/GLMnet.so') + compile = subprocess.check_output(['gfortran', + source_path, + '-fPIC', + '-fdefault-real-8', + '-shared', + '-o', + output_path + ]) + build_py.run(self) + setup(name='glmnet_python', version = '0.2.2', description = 'Python version of glmnet, from Stanford University', @@ -22,5 +41,6 @@ 'Programming Language :: Python :: 3.4', 'Operating System :: Unix', ], - keywords='glm glmnet ridge lasso elasticnet' - ) + keywords='glm glmnet ridge lasso elasticnet', + cmdclass={'build_py': Compile}, +) From 6a7257fad8bcee6bf77f4eaf0321203427db08b2 Mon Sep 17 00:00:00 2001 From: Marco Galardini Date: Wed, 27 Nov 2019 10:32:57 -0500 Subject: [PATCH 2/2] Clean up the build process --- setup.py | 53 ++++++++++++++++++++++++++++++++++------------------- 1 file changed, 34 insertions(+), 19 deletions(-) diff --git a/setup.py b/setup.py index 30707f1..febc562 100644 --- a/setup.py +++ b/setup.py @@ -1,28 +1,41 @@ import os, sys -from setuptools import setup, find_packages -from setuptools.command.build_py import build_py +from setuptools import setup, Extension +from setuptools.command.build_ext import build_ext import subprocess -class Compile(build_py): - """Custom build setup to help run needed shell commands +class GfortranExtension(Extension): + def __init__(self, name, sourcedir='', input='', output=''): + Extension.__init__(self, name, sources=[]) + self.sourcedir = os.path.abspath(sourcedir) + self.input = os.path.join(self.sourcedir, input) + self.output = os.path.join(self.sourcedir, output) - Inspired by https://stackoverflow.com/a/27953695/1237531""" +class GfortranBuild(build_ext): def run(self): - dir_path = os.path.dirname(os.path.realpath(__file__)) - source_path = os.path.join(dir_path, 'glmnet_python/GLMnet.f') - output_path = os.path.join(dir_path, 'glmnet_python/GLMnet.so') - compile = subprocess.check_output(['gfortran', - source_path, - '-fPIC', - '-fdefault-real-8', - '-shared', - '-o', - output_path - ]) - build_py.run(self) + try: + out = subprocess.check_output(['gfortran', '--version']) + except OSError: + raise RuntimeError("gfortran must be installed to build the following extensions: " + + ", ".join(e.name for e in self.extensions)) + + for ext in self.extensions: + self.build_extension(ext) + + def build_extension(self, ext): + gfortran_args = ['-fPIC', + '-fdefault-real-8', + '-shared', + '-o', + ext.output] + + if not os.path.exists(self.build_temp): + os.makedirs(self.build_temp) + + env = os.environ.copy() + subprocess.check_call(['gfortran', ext.input] + gfortran_args, cwd=self.build_temp, env=env) setup(name='glmnet_python', - version = '0.2.2', + version = '1.0.0', description = 'Python version of glmnet, from Stanford University', long_description=open('README.md').read(), url="https://github.com/johnlees/glmnet_python", @@ -42,5 +55,7 @@ def run(self): 'Operating System :: Unix', ], keywords='glm glmnet ridge lasso elasticnet', - cmdclass={'build_py': Compile}, + ext_modules=[GfortranExtension('GLMnet', 'glmnet_python', + 'GLMnet.f', 'GLMnet.so')], + cmdclass={'build_ext': GfortranBuild}, )