forked from arbor-sim/arbor
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsetup.py
184 lines (158 loc) · 6.98 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
import os
import sys
import setuptools
import pathlib
from setuptools import Extension
from setuptools.command.build_ext import build_ext
from setuptools.command.install import install
import subprocess
# Singleton class that holds the settings configured using command line
# options. This information has to be stored in a singleton so that it
# can be passed between different stages of the build, and because pip
# has strange behavior between different versions.
class CL_opt:
instance = None
def __init__(self):
if not CL_opt.instance:
CL_opt.instance = {'mpi': False,
'gpu': 'none',
'vec': False,
'arch': 'native',
'bundled': True}
def settings(self):
return CL_opt.instance
def cl_opt():
return CL_opt().settings()
# VERSION is in the same path as setup.py
here = os.path.abspath(os.path.dirname(__file__))
with open(os.path.join(here, 'VERSION')) as version_file:
version_ = version_file.read().strip()
# Get the contents of the readme
with open(os.path.join(here, 'python/readme.md'), encoding='utf-8') as f:
long_description = f.read()
def check_cmake():
try:
out = subprocess.check_output(['cmake', '--version'])
return True
except OSError:
return False
# Extend the command line options available to the install phase.
# These arguments must come after `install` on the command line, e.g.:
# python3 setup.py install --mpi --arch=skylake
# pip3 install --install-option '--mpi' --install-option '--arch=skylake' .
class install_command(install):
user_options = install.user_options + [
('mpi', None, 'enable mpi support (requires MPI library)'),
('gpu=', None, 'enable nvidia cuda support (requires cudaruntime and nvcc) or amd hip support. Supported values: '
'none, cuda, cuda-clang, hip'),
('vec', None, 'enable vectorization'),
('arch=', None, 'cpu architecture, e.g. haswell, skylake, armv8.2-a+sve, znver2 (default native).'),
('sysdeps', None, 'don\'t use bundled 3rd party C++ dependencies (pybind11 and json). This flag forces use of dependencies installed on the system.')
]
def initialize_options(self):
install.initialize_options(self)
self.mpi = None
self.gpu = None
self.arch = None
self.vec = None
self.sysdeps = None
def finalize_options(self):
install.finalize_options(self)
def run(self):
# The options are stored in global variables:
opt = cl_opt()
# mpi : build with MPI support (boolean).
opt['mpi'] = self.mpi is not None
# gpu : compile for AMD/NVIDIA GPUs and choose compiler (string).
opt['gpu'] = "none" if self.gpu is None else self.gpu
# vec : generate SIMD vectorized kernels for CPU micro-architecture (boolean).
opt['vec'] = self.vec is not None
# arch : target CPU micro-architecture (string).
opt['arch'] = "native" if self.arch is None else self.arch
# bundled : use bundled/git-submoduled 3rd party libraries.
# By default use bundled libs.
opt['bundled'] = self.sysdeps is None
install.run(self)
class cmake_extension(Extension):
def __init__(self, name):
Extension.__init__(self, name, sources=[])
class cmake_build(build_ext):
def run(self):
if not check_cmake():
raise RuntimeError('CMake is not available. CMake 3.12 is required.')
# The path where CMake will be configured and Arbor will be built.
build_directory = os.path.abspath(self.build_temp)
# The path where the package will be copied after building.
lib_directory = os.path.abspath(self.build_lib)
# The path where the Python package will be compiled.
source_path = build_directory + '/python/arbor'
# Where to copy the package after it is built, so that whatever the next phase is
# can copy it into the target 'prefix' path.
dest_path = lib_directory + '/arbor'
opt = cl_opt()
cmake_args = [
'-DARB_WITH_PYTHON=on',
'-DPYTHON_EXECUTABLE=' + sys.executable,
'-DARB_WITH_MPI={}'.format( 'on' if opt['mpi'] else 'off'),
'-DARB_VECTORIZE={}'.format('on' if opt['vec'] else 'off'),
'-DARB_ARCH={}'.format(opt['arch']),
'-DARB_GPU={}'.format(opt['gpu']),
'-DARB_USE_BUNDLED_LIBS={}'.format('on' if opt['bundled'] else 'off'),
'-DCMAKE_BUILD_TYPE=Release' # we compile with debug symbols in release mode.
]
print('-'*5, 'command line arguments: {}'.format(opt))
print('-'*5, 'cmake arguments: {}'.format(cmake_args))
build_args = ['--config', 'Release']
# Assuming Makefiles
build_args += ['--', '-j2']
env = os.environ.copy()
env['CXXFLAGS'] = '{}'.format(env.get('CXXFLAGS', ''))
if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)
# CMakeLists.txt is in the same directory as this setup.py file
cmake_list_dir = os.path.abspath(os.path.dirname(__file__))
print('-'*20, 'Configure CMake')
subprocess.check_call(['cmake', cmake_list_dir] + cmake_args,
cwd=self.build_temp, env=env)
print('-'*20, 'Build')
cmake_cmd = ['cmake', '--build', '.'] + build_args
subprocess.check_call(cmake_cmd,
cwd=self.build_temp)
# Copy from build path to some other place from whence it will later be installed.
# ... or something like that
# ... setuptools is an enigma monkey patched on a mystery
if not os.path.exists(dest_path):
os.makedirs(dest_path, exist_ok=True)
self.copy_tree(source_path, dest_path)
setuptools.setup(
name='arbor',
version=version_,
python_requires='>=3.6',
install_requires=['numpy'],
setup_requires=[],
zip_safe=False,
ext_modules=[cmake_extension('arbor')],
cmdclass={
'build_ext': cmake_build,
'install': install_command,
},
author='The Arbor dev team.',
url='https://github.com/arbor-sim/arbor',
description='High performance simulation of networks of multicompartment neurons.',
long_description=long_description,
long_description_content_type='text/markdown',
classifiers=[
'Development Status :: 5 - Production/Stable',
'Intended Audience :: Science/Research',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: C++',
],
project_urls={
'Source': 'https://github.com/arbor-sim/arbor',
'Documentation': 'https://arbor.readthedocs.io',
'Bug Reports': 'https://github.com/arbor-sim/arbor/issues',
},
)