-
Notifications
You must be signed in to change notification settings - Fork 10
/
setup.py
205 lines (177 loc) · 6.77 KB
/
setup.py
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
205
# 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='[email protected]',
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,
test_suite='nose.collector',
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
)