forked from tskit-dev/msprime
-
Notifications
You must be signed in to change notification settings - Fork 2
/
setup.py
211 lines (192 loc) · 7.59 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
206
207
208
209
210
211
#
# Copyright (C) 2015-2017 University of Oxford
#
# This file is part of msprime.
#
# msprime 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.
#
# msprime 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 msprime. If not, see <http://www.gnu.org/licenses/>.
#
from __future__ import division
from __future__ import print_function
from setuptools import setup, Extension
import subprocess
import platform
import os
import os.path
from warnings import warn
CONDA_PREFIX = os.getenv("MSP_CONDA_PREFIX", None)
IS_WINDOWS = platform.system() == "Windows"
# NOTE: sadly these warnings won't work to warn users installing with pip
# https://github.com/pypa/pip/issues/2933
HAVE_NUMPY = False
try:
import numpy as np
version = tuple(map(int, np.__version__.split(".")))
if version < (1, 7, 0):
warn("numpy version is too old: version 1.7 or newer needed")
else:
HAVE_NUMPY = True
except ImportError:
warn("numpy not available. Some features will not work.")
class PathConfigurator(object):
"""
A class to attempt configuration of the compile search paths
on various platforms.
"""
def __init__(self):
self.include_dirs = []
self.library_dirs = []
if HAVE_NUMPY:
self.include_dirs = [np.get_include()]
try:
self._check_hdf5_version()
except OSError as e:
warn("Error occured checking HDF5 version: {}".format(e))
# On Unix systems with the correct tools installed we can detect the
# paths for include and library files.
try:
self._configure_hdf5()
except OSError as e:
warn("Error occured getting HDF5 path config: {}".format(e))
try:
self._configure_gsl()
except OSError as e:
warn("Error occured getting GSL path config: {}".format(e))
# If the conda prefix is defined, then we are compiling in a conda
# context. All include and lib paths should come from within this prefix.
if CONDA_PREFIX is not None:
prefix = CONDA_PREFIX
if IS_WINDOWS:
prefix = os.path.join(prefix, "Library")
self.library_dirs.append(os.path.join(prefix, "lib"))
self.include_dirs.append(os.path.join(prefix, "include"))
def _run_command(self, args):
return subprocess.check_output(args, universal_newlines=True)
def _check_hdf5_version(self):
output = self._run_command(["h5ls", "-V"]).split()
version_str = output[2]
version = list(map(int, version_str.split(".")[:2]))
if version < [1, 8]:
# TODO is there a better exception to raise here?
raise ValueError(
"hdf5 version {} found; we need 1.8.0 or greater".format(
version_str))
def _configure_hdf5(self):
output = self._run_command(["h5cc", "-show"]).split()
for token in output:
if token.startswith("-I"):
self.include_dirs.append(token[2:])
elif token.startswith("-L"):
self.library_dirs.append(token[2:])
def _configure_gsl(self):
output = self._run_command(["gsl-config", "--cflags"]).split()
if len(output) > 0:
token = output[0]
self.include_dirs.append(token[2:])
output = self._run_command(["gsl-config", "--libs"]).split()
for token in output:
if token.startswith("-L"):
self.library_dirs.append(token[2:])
# Now, setup the extension module. We have to do some quirky workarounds
# here so that we can get the current version number from setuptools_scm
# and also get this version provided as a compile time parameter to the
# extension module.
class DefineMacros(object):
def __init__(self):
self._msprime_version = None
def __getitem__(self, index):
if self._msprime_version is None:
import setuptools_scm
version = setuptools_scm.get_version()
if IS_WINDOWS:
self._msprime_version = '\\"{}\\"'.format(version)
else:
self._msprime_version = '"{}"'.format(version)
defines = [
# We define this macro to ensure we're using the v18 versions of
# the HDF5 API and not earlier deprecated versions.
("H5_NO_DEPRECATED_SYMBOLS", None),
# Define the library version
("MSP_LIBRARY_VERSION_STR", '{}'.format(self._msprime_version)),
]
if IS_WINDOWS:
defines += [
# These two are required for GSL to compile and link against the
# conda-forge version.
("GSL_DLL", None), ("WIN32", None),
# This is needed for HDF5 to link properly.
("H5_BUILT_AS_DYNAMIC_LIB", None)]
if HAVE_NUMPY:
defines += [("HAVE_NUMPY", None)]
return defines[index]
configurator = PathConfigurator()
source_files = [
"msprime.c", "fenwick.c", "avl.c", "tree_sequence.c",
"object_heap.c", "newick.c", "hapgen.c", "recomb_map.c", "mutgen.c",
"vargen.c", "vcf.c", "ld.c", "tables.c", "util.c"]
libdir = "lib"
_msprime_module = Extension(
'_msprime',
sources=["_msprimemodule.c"] + [os.path.join(libdir, f) for f in source_files],
# Enable asserts by default.
undef_macros=["NDEBUG"],
extra_compile_args=["-std=c99"],
define_macros=DefineMacros(),
libraries=["gsl", "gslcblas", "hdf5"],
include_dirs=[libdir] + configurator.include_dirs,
library_dirs=configurator.library_dirs,
)
with open("README.rst") as f:
long_description = f.read()
setup(
name="msprime",
description="A fast and accurate coalescent simulator.",
long_description=long_description,
packages=["msprime"],
author="Jerome Kelleher",
author_email="[email protected]",
url="http://pypi.python.org/pypi/msprime",
entry_points={
'console_scripts': [
'mspms=msprime.cli:mspms_main',
'msp=msprime.cli:msp_main',
]
},
install_requires=["svgwrite", "six"],
ext_modules=[_msprime_module],
keywords=["Coalescent simulation", "ms"],
license="GNU GPLv3+",
platforms=["POSIX", "Windows", "MacOS X"],
classifiers=[
"Programming Language :: C",
"Programming Language :: Python",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Development Status :: 4 - Beta",
"Environment :: Other Environment",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
"Operating System :: POSIX",
"Operating System :: MacOS :: MacOS X",
"Operating System :: Microsoft :: Windows",
"Topic :: Scientific/Engineering",
"Topic :: Scientific/Engineering :: Bio-Informatics",
],
setup_requires=['setuptools_scm'],
use_scm_version={"write_to": "msprime/_version.py"},
)