-
Notifications
You must be signed in to change notification settings - Fork 2
/
setup.py
176 lines (149 loc) · 6.3 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
import os
import re
import sys
import pkgutil
import pathlib
import versioneer
from sysconfig import get_platform
from distutils.version import LooseVersion
from subprocess import CalledProcessError, check_output, check_call, run, PIPE
from setuptools import setup, Extension, find_packages
from setuptools.command.build_ext import build_ext
# We can use cmake provided from pip which (normally) gets installed at /bin
# Except that in the manylinux builds it's placed at /opt/python/[version]/bin/
# (as a symlink at least) which is *not* on the path.
# If cmake is a known module, import it and use it tell us its binary directory
if pkgutil.find_loader('cmake') is not None:
import cmake
CMAKE_BIN = cmake.CMAKE_BIN_DIR + os.path.sep + 'cmake'
else:
CMAKE_BIN = 'cmake'
def get_cmake():
return CMAKE_BIN
def is_vsc():
platform = get_platform()
return platform.startswith("win")
def is_mingw():
platform = get_platform()
return platform.startswith("mingw")
def is_osx():
platform = get_platform()
return platform.startswith("macosx")
class CMakeExtension(Extension):
def __init__(self, name, sourcedir=''):
Extension.__init__(self, name, sources=[])
self.sourcedir = os.path.abspath(sourcedir)
class CMakeBuild(build_ext):
def run(self):
try:
out = check_output([get_cmake(), '--version'])
except OSError:
raise RuntimeError("CMake must be installed to build" +
" the following extensions: " +
", ".join(e.name for e in self.extensions))
rex = r'version\s*([\d.]+)'
cmake_version = LooseVersion(re.search(rex, out.decode()).group(1))
if cmake_version < '3.13.0':
raise RuntimeError("CMake >= 3.13.0 is required")
for ext in self.extensions:
self.build_extension(ext)
def build_extension(self, ext):
extdir = os.path.dirname(self.get_ext_fullpath(ext.name))
extdir = os.path.abspath(extdir)
cmake_args = []
if is_vsc():
if sys.maxsize > 2**32:
cmake_args += ['-A', 'x64']
else:
cmake_args += ['-A', 'Win32']
if is_mingw():
cmake_args += ['-G','Unix Makefiles'] # Must be two entries to work
cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir,
'-DPYTHON_EXECUTABLE=' + sys.executable]
cfg = 'Debug' if self.debug else 'Release'
#cfg = 'Debug' if self.debug else 'RelWithDebInfo'
build_args = ['--config', cfg]
# make sure all library files end up in one place
cmake_args += ["-DCMAKE_BUILD_WITH_INSTALL_RPATH=TRUE"]
cmake_args += ["-DCMAKE_INSTALL_RPATH={}".format("$ORIGIN")]
if is_vsc():
cmake_lib_out_dir = '-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'
cmake_args += [cmake_lib_out_dir.format(cfg.upper(), extdir)]
cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
build_args += ['--', '/m:4']
else:
cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
build_args += ['--', '-j']
env = os.environ.copy()
cxxflags = '{} -DVERSION_INFO=\\"{}\\"'.format(
env.get('CXXFLAGS', ''), self.distribution.get_version())
env['CXXFLAGS'] = cxxflags
if 'MATLAB_DIR' in env:
cmake_args += ['-DMatlab_ROOT_DIR=' + env['MATLAB_DIR']]
elif 'MATLABEXECUTABLE' in env:
ml_env = env['MATLABEXECUTABLE']
if is_vsc():
pp = ml_env.split('/')[1:]
ml_env = pp[0] + ':\\' + '\\'.join(pp[1:])
matlab_path = str(pathlib.Path(ml_env).resolve().parents[1])
if ml_env.startswith('/host') and not matlab_path.startswith('/host'):
matlab_path = '/host/' + matlab_path
cmake_args += ['-DMatlab_ROOT_DIR=' + matlab_path]
if is_osx():
# Matlab doesn't run well on _some_ Mac runners: force version else it times out
cmake_args += ['-DMatlab_VERSION_STRING_INTERNAL:INTERNAL=9.8']
if not os.path.exists(self.build_temp):
os.makedirs(self.build_temp)
check_call(
[get_cmake(), ext.sourcedir] + cmake_args,
cwd=self.build_temp, env=env)
check_call(
[get_cmake(), '--build', '.'] + build_args,
cwd=self.build_temp)
with open("README.md", "r") as fh:
LONG_DESCRIPTION = fh.read()
cmdclass = versioneer.get_cmdclass()
cmdclass['build_ext'] = CMakeBuild
KEYWORDARGS = dict(
name='libpymcr',
version=versioneer.get_version(),
author='Duc Le',
author_email='[email protected]',
description='A module to allow Python to call functions from a compiled Matlab archive',
long_description=LONG_DESCRIPTION,
long_description_content_type="text/markdown",
ext_modules=[CMakeExtension('libpymcr._libpymcr')],
packages=['libpymcr', 'libpymcr.scripts'],
package_data={'libpymcr.scripts': [os.path.join(os.path.dirname(__file__), 'libpymcr', 'scripts', 'parseclass.m')]},
install_requires = ['numpy>=1.7.1'],
cmdclass=cmdclass,
entry_points = {'console_scripts': [
'matlab2python = libpymcr.scripts.matlab2python:main']},
url="https://github.com/pace-neutrons/libpymcr",
zip_safe=False,
classifiers=[
"Development Status :: 2 - Pre-Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
"Operating System :: Microsoft :: Windows :: Windows 10",
"Operating System :: POSIX :: Linux",
"Programming Language :: C++",
"Programming Language :: Python :: 3",
"Topic :: Software Development",
]
)
try:
setup(**KEYWORDARGS)
except CalledProcessError:
print("Failed to build the extension!")
else:
if 'MATLABEXECUTABLE' in os.environ and 'HOSTDIRECTORY' in os.environ:
# Running in CI, copy mex file out
import shutil, glob
outdir = os.environ['HOSTDIRECTORY']
if is_vsc():
pp = outdir.split('/')[1:]
outdir = pp[0] + ':\\' + '\\'.join(pp[1:])
for mex in glob.glob('**/call_python*.mex*', recursive=True):
if not os.path.exists(os.path.join(outdir, mex)):
shutil.copy(mex, outdir)