setup.py 8 KB
Newer Older
Berk Onat's avatar
Berk Onat committed
1
2
#!/usr/bin/env python

3
import os
4
import re
Berk Onat's avatar
Berk Onat committed
5
import sys
6
7
8
import sysconfig
import platform
import subprocess
9
10
11

from distutils.version import LooseVersion

Berk Onat's avatar
Berk Onat committed
12
try:
Berk Onat's avatar
Berk Onat committed
13
    from setuptools import setup, Extension, Command, find_packages
14
    from setuptools.command.install import install
Berk Onat's avatar
Berk Onat committed
15
16
    from Cython.Build import cythonize
    from Cython.Distutils import build_ext
Berk Onat's avatar
Berk Onat committed
17
except:
Berk Onat's avatar
Berk Onat committed
18
    from distutils import setup, Extension, Command, find_packages
19
    from distutils.command.install import install
Berk Onat's avatar
Berk Onat committed
20
21
    from Cython.Build import cythonize
    from Cython.Distutils import build_ext
22
23
24
25
26
    
try:
    from setuptools.command.build_clib import build_clib as _build_clib
except:
    from distutils.command.build_clib import build_clib as _build_clib
Berk Onat's avatar
Berk Onat committed
27

Berk Onat's avatar
Berk Onat committed
28
29
30
31
32
class CMakeExtension(Extension):
    def __init__(self, name, sourcedir=''):
        Extension.__init__(self, name, sources=[])
        self.sourcedir = os.path.abspath(sourcedir)

33
class build_clib(_build_clib):
Berk Onat's avatar
Berk Onat committed
34
    def run(self):
35
36
37
38
        buildflag = True
        if buildflag:
            ext = CMakeExtension('molfile', sourcedir='pymolfile/molfile/'),
            self.my_build_extension(ext)
Berk Onat's avatar
Berk Onat committed
39

40
    def my_build_extension(self, ext):
Berk Onat's avatar
Berk Onat committed
41
        extdir = os.path.abspath(
42
            os.path.dirname('pymolfile/molfile'))
Berk Onat's avatar
Berk Onat committed
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
        cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir,
                      '-DPYTHON_EXECUTABLE=' + sys.executable]

        cfg = 'Debug' if self.debug else 'Release'
        build_args = ['--config', cfg]

        if platform.system() == "Windows":
            cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(
                cfg.upper(),
                extdir)]
            if sys.maxsize > 2**32:
                cmake_args += ['-A', 'x64']
            build_args += ['--', '/m']
        else:
            cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
58
            build_args += ['--', '-j1']
Berk Onat's avatar
Berk Onat committed
59
60
61
62
63
64
65

        env = os.environ.copy()
        env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(
            env.get('CXXFLAGS', ''),
            self.distribution.get_version())
        if not os.path.exists(self.build_temp):
            os.makedirs(self.build_temp)
66
67
        subprocess.check_call(['cmake', '../pymolfile/molfile'] + cmake_args,
                                cwd=self.build_temp + '/../', env=env)
Berk Onat's avatar
Berk Onat committed
68
        subprocess.check_call(['cmake', '--build', '.'] + build_args,
69
70
                                cwd=self.build_temp + '/../')

Berk Onat's avatar
Berk Onat committed
71
72
        print()  # Add an empty line for cleaner output

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
def get_ext_filename_without_platform_suffix(filename):
    name, ext = os.path.splitext(filename)
    ext_suffix = sysconfig.get_config_var('EXT_SUFFIX')

    if ext_suffix == ext:
        return filename

    ext_suffix = ext_suffix.replace(ext, '')
    idx = name.find(ext_suffix)

    if idx == -1:
        return filename
    else:
        return name[:idx] + ext

class BuildExtWithoutPlatformSuffix(build_ext):
    def get_ext_filename(self, ext_name):
        filename = super().get_ext_filename(ext_name)
        return get_ext_filename_without_platform_suffix(filename)
Berk Onat's avatar
Berk Onat committed
92
93
94
95
96
97

VERSION = "0.0.1"
CLASSIFIERS = [
    "Development Status :: 1 - Alpha",
    "Intended Audience :: Science/Research",
    "Intended Audience :: Developers",
Berk Onat's avatar
Berk Onat committed
98
    "License :: OSI Approved :: University of Illinois Open Source License (UIUC)",
Berk Onat's avatar
Berk Onat committed
99
    "Programming Language :: C",
Berk Onat's avatar
Berk Onat committed
100
    "Programming Language :: C++",
Berk Onat's avatar
Berk Onat committed
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
    "Programming Language :: Python",
    "Programming Language :: Python :: 3",
    "Topic :: Scientific/Engineering :: Physics",
    "Topic :: Scientific/Engineering :: Chemistry",
    "Topic :: Scientific/Engineering :: Bio-Informatics",
    "Topic :: Scientific/Engineering :: Material Science",
    "Operating System :: MacOS",
    "Operating System :: POSIX",
    "Operating System :: Unix",
    "Operating System :: Microsoft :: Windows",
]


# from MDAnalysis setup.py (http://www.mdanalysis.org/)
class NumpyExtension(Extension, object):
    """Derived class to cleanly handle setup-time (numpy) dependencies.
    """
    # The only setup-time numpy dependency comes when setting up its
    #  include dir.
    # The actual numpy import and call can be delayed until after pip
    #  has figured it must install numpy.
    # This is accomplished by passing the get_numpy_include function
    #  as one of the include_dirs. This derived Extension class takes
    #  care of calling it when needed.
    def __init__(self, *args, **kwargs):
        self._np_include_dirs = []
        super(NumpyExtension, self).__init__(*args, **kwargs)

    @property
    def include_dirs(self):
        if not self._np_include_dirs:
            for item in self._np_include_dir_args:
                try:
                    self._np_include_dirs.append(item())  # The numpy callable
                except TypeError:
                    self._np_include_dirs.append(item)
        return self._np_include_dirs

    @include_dirs.setter
    def include_dirs(self, val):
        self._np_include_dir_args = val


# from MDAnalysis setup.py (http://www.mdanalysis.org/)
def get_numpy_include():
    try:
        # Obtain the numpy include directory. This logic works across numpy
        # versions.
        # setuptools forgets to unset numpy's setup flag and we get a crippled
        # version of it unless we do it ourselves.
        try:
            import __builtin__  # py2
            __builtin__.__NUMPY_SETUP__ = False
        except:
            import builtins  # py3
            builtins.__NUMPY_SETUP__ = False
        import numpy as np
    except ImportError as e:
        print(e)
        print('*** package "numpy" not found ***')
        print('pymolfile requires a version of NumPy, even for setup.')
        print('Please get it from http://numpy.scipy.org/ or install it through '
              'your package manager.')
        sys.exit(-1)
    try:
        numpy_include = np.get_include()
    except AttributeError:
        numpy_include = np.get_numpy_include()
    return numpy_include

Berk Onat's avatar
Berk Onat committed
171
172
# from SimpleTraj setup.py (https://github.com/arose/simpletraj)

Berk Onat's avatar
Berk Onat committed
173
if __name__ == '__main__':
174

Berk Onat's avatar
Berk Onat committed
175
    libpymolfile_module = Extension(
Berk Onat's avatar
Berk Onat committed
176
            'pymolfile/molfile/_libpymolfile', 
Berk Onat's avatar
Berk Onat committed
177
178
            sources=[
                'pymolfile/molfile/libpymolfile.i' , 
179
                'pymolfile/molfile/pymolfile.cxx',
Berk Onat's avatar
Berk Onat committed
180
                ],
181
            swig_opts=['-py3', '-Wall', '-c++'],
Berk Onat's avatar
Berk Onat committed
182
            library_dirs=[
183
184
                'build/external/tng/lib',
                'build/molfile_plugins/compile/lib/'
Berk Onat's avatar
Berk Onat committed
185
                ],
186
187
            #libraries=['netcdf','expat','tcl'],
            libraries=['netcdf','expat'],
Berk Onat's avatar
Berk Onat committed
188
            include_dirs = [
Berk Onat's avatar
Berk Onat committed
189
                get_numpy_include(),
Berk Onat's avatar
Berk Onat committed
190
                'pymolfile/molfile',
Berk Onat's avatar
Berk Onat committed
191
192
                'pymolfile/molfile/molfile_plugins/include',
                'pymolfile/molfile/molfile_plugins/molfile_plugin/include',
193
194
                'build/molfile_plugins/compile/lib/',
                'build/external/tng/include',
Berk Onat's avatar
Berk Onat committed
195
196
                ],
            extra_compile_args = [
Berk Onat's avatar
Berk Onat committed
197
                '-fPIC', '-shared', '-O0', '-g', '-w' 
198
199
                ],
            extra_link_args = [
Berk Onat's avatar
Berk Onat committed
200
201
                'build/molfile_plugins/compile/lib/libmolfile_plugin.a',
                'build/external/tng/lib/libtng_io.a',
202
                ],
Berk Onat's avatar
Berk Onat committed
203
204
            )

Berk Onat's avatar
Berk Onat committed
205
206
207
208
    setup(
        name = "pymolfile",
        author = "Berk Onat",
        author_email = "b.onat@warwick.ac.uk",
209
        description = "Not just a Python interface for VMD molfile plugins.",
Berk Onat's avatar
Berk Onat committed
210
211
        version = VERSION,
        classifiers = CLASSIFIERS,
Berk Onat's avatar
Berk Onat committed
212
213
        license = "UIUC",
        url = "https://gitlab.mpcdf.mpg.de/berko/pymolfile",
Berk Onat's avatar
Berk Onat committed
214
215
        zip_safe = False,
        packages = find_packages(),
Berk Onat's avatar
Berk Onat committed
216
        libraries = [('molfile_plugin', { 'sources' : ['build/molfile_plugins/compile/lib/libmolfile_plugin.a']})],
217
218
        cmdclass= {
            'build_clib' : build_clib,
Berk Onat's avatar
Berk Onat committed
219
            'build_ext'  : build_ext,
220
        },
Berk Onat's avatar
Berk Onat committed
221
        ext_modules = [
Berk Onat's avatar
Berk Onat committed
222
            libpymolfile_module,
Berk Onat's avatar
Berk Onat committed
223
        ],
Berk Onat's avatar
Berk Onat committed
224
        package_data={'pymolfile': ['LICENSE', 'pymolfile/molfile/libpymolfile.py']},
Berk Onat's avatar
Berk Onat committed
225
        py_modules=["pymolfile"],
Berk Onat's avatar
Berk Onat committed
226
227
228
        requires = [ "numpy" ],
        setup_requires = [ "numpy" ],
        install_requires = [ "numpy" ],
229
        extras_require = {}
Berk Onat's avatar
Berk Onat committed
230
    )