1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
|
# swiglpk - Swig Python bindings for the GNU Linear Programming Kit (GLPK)
# Copyright (C) 2015 The Novo Nordisk Foundation Center for Biosustainability
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# http://stackoverflow.com/questions/12491328/python-distutils-not-include-the-swig-generated-module
import os
import warnings
from setuptools import setup, Extension
from distutils.command.build import build
import versioneer
ENV_GLPK_HEADER_PATH = 'GLPK_HEADER_PATH'
GLPK_HEADER_NAME = 'glpk.h'
GLPSOL_BINARY_NAME = 'glpsol'
INCLUDE_DIRS = (
'/usr/local/include',
'/usr/include',
'/include',
)
class CustomBuild(build):
sub_commands = [
('build_ext', build.has_ext_modules),
('build_py', build.has_pure_modules),
('build_clib', build.has_c_libraries),
('build_scripts', build.has_scripts),
]
def find_glpk_header():
# If a path is provded by the environment, expect the GLPK header there.
given_path = os.environ.get(ENV_GLPK_HEADER_PATH, None)
if given_path:
if os.path.isfile(given_path):
if os.path.basename(given_path) == GLPK_HEADER_NAME:
return os.path.abspath(os.path.dirname(given_path))
else:
warnings.warn(
'The environment variable {}="{}" points to a file not '
'named {}.'.format(ENV_GLPK_HEADER_PATH, given_path,
GLPK_HEADER_NAME), stacklevel=2
)
elif os.path.isdir(given_path):
header = os.path.join(given_path, GLPK_HEADER_NAME)
if os.path.isfile(header):
return os.path.abspath(given_path)
else:
warnings.warn(
'The environment variable {}="{}" is set to a directory '
'that does not contain {}.'.format(ENV_GLPK_HEADER_PATH,
given_path, GLPK_HEADER_NAME), stacklevel=2
)
else:
warnings.warn(
'The environment variable {}="{}" does not point to a '
'directory or file.'.format(ENV_GLPK_HEADER_PATH, given_path),
stacklevel=2
)
# Look for a drop-in header file next.
if os.path.isfile(GLPK_HEADER_NAME):
return os.getcwd()
include_dirs = list(INCLUDE_DIRS)
# If glpsol is found, look for an include directory in its vicinity.
try:
from shutil import which
except ImportError: # Python < 3.3.
pass
else:
glpsol = which(GLPSOL_BINARY_NAME)
if glpsol:
glpsol_path = os.path.dirname(glpsol)
glpsol_root = os.path.dirname(glpsol_path)
glpsol_include_path = os.path.join(glpsol_root, "include")
include_dirs.insert(0, glpsol_include_path)
# Look at common places.
for path in include_dirs:
if os.path.isdir(path):
header = os.path.join(path, GLPK_HEADER_NAME)
if os.path.isfile(header):
return os.path.abspath(path)
raise FileNotFoundError('Failed to locate {}.'.format(GLPK_HEADER_NAME))
# Warn users installing via pip that this is a source build.
print(
'='*30,
'BUILDING SWIGLPK FROM SOURCE.',
'If you are installing SWIGLPK via pip, this means that no wheels are'
' offered for your platform or Python version yet.',
'This can be the case if you adopt a new Python version early.',
'A source build requires GLPK, SWIG, and GMP (Linux/Mac) to be installed!',
'='*30,
sep='\n'
)
# Find the GLPK header.
try:
print('Looking for {}...'.format(GLPK_HEADER_NAME))
glpk_header_dirname = find_glpk_header()
except FileNotFoundError as error:
raise RuntimeError(
'A source build of SWIGLPK requires GLPK to be installed but we could'
' not find {0}. You may put {0} inside the current directory or link'
' to its parent folder via {1}.'
.format(GLPK_HEADER_NAME, ENV_GLPK_HEADER_PATH)
) from error
else:
print('Found {} in {}.'.format(GLPK_HEADER_NAME, glpk_header_dirname))
# Make sure SWIG is available.
try:
from shutil import which
except ImportError:
pass # This check is not critical given the warning above.
else:
print('Making sure SWIG is available...')
if which('swig'):
print('Found the swig executable.')
else:
raise RuntimeError(
'A source build of SWIGLPK requires SWIG to be installed but we '
'could not find the swig executable.')
# Assemble custom_cmd_class.
custom_cmd_class = versioneer.get_cmdclass()
custom_cmd_class['build'] = CustomBuild
try:
from wheel.bdist_wheel import bdist_wheel
class CustomBdistWheel(bdist_wheel):
def run(self):
self.run_command('build_ext')
bdist_wheel.run(self)
custom_cmd_class['bdist_wheel'] = CustomBdistWheel
except ImportError:
pass # Custom command not needed if wheel is not installed.
# Read long description from README.rst.
try:
with open('README.rst', 'r') as f:
long_description = f.read()
except Exception:
long_description = ''
# Run setup.
setup(
name='swiglpk',
version=versioneer.get_version(),
cmdclass=custom_cmd_class,
packages=['swiglpk'],
package_dir={'swiglpk': 'swiglpk'},
author='Nikolaus Sonnenschein',
author_email='niko.sonnenschein@gmail.com',
description='swiglpk - Simple swig bindings for the GNU Linear Programming Kit',
license='GPL v3',
keywords='optimization swig glpk',
url='https://github.com/biosustain/swiglpk',
long_description=long_description,
classifiers=[
'Development Status :: 5 - Production/Stable',
'Topic :: Scientific/Engineering',
'Topic :: Software Development',
'Intended Audience :: Science/Research',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.4',
'License :: OSI Approved :: GNU General Public License v3 (GPLv3)'
],
ext_modules=[
Extension(
"swiglpk._swiglpk",
sources=["swiglpk/glpk.i"],
include_dirs=[glpk_header_dirname],
swig_opts=["-I"+glpk_header_dirname],
libraries=['glpk'])
],
include_package_data=True
)
|