File: setup.py

package info (click to toggle)
python-gmpy2 2.0.3-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 1,628 kB
  • ctags: 1,123
  • sloc: ansic: 21,036; python: 5,846; makefile: 163
file content (399 lines) | stat: -rw-r--r-- 14,063 bytes parent folder | download
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
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
import sys
import os
from distutils.core import setup, Extension
from distutils.command.clean import clean
from distutils.command.build_ext import build_ext
from distutils.sysconfig import get_python_inc, get_python_lib

def writeln(s):
    sys.stdout.write('%s\n' % s)
    sys.stdout.flush()

# Some operating systems may use a different library directory under the
# prefix specified by --prefix. It must be manually changed.

lib_path = '/lib'

# Extract the version from MPFR/MPC

def get_mpfr_version(fname):
    result = []
    try:
        with open(fname) as f:
            for line in f:
                if line.startswith('#define MPFR_VERSION_MAJOR'):
                    result.append(int(line.split()[-1]))
                if line.startswith('#define MPFR_VERSION_MINOR'):
                    result.append(int(line.split()[-1]))
                if line.startswith('#define MPFR_VERSION_PATCHLEVEL'):
                    result.append(int(line.split()[-1]))
        return tuple(result)
    except:
        return (0,0,0)

def get_mpc_version(fname):
    result = []
    try:
        with open(fname) as f:
            for line in f:
                if line.startswith('#define MPC_VERSION_MAJOR'):
                    result.append(int(line.split()[-1]))
                if line.startswith('#define MPC_VERSION_MINOR'):
                    result.append(int(line.split()[-1]))
                if line.startswith('#define MPC_VERSION_PATCHLEVEL'):
                    result.append(int(line.split()[-1]))
        return tuple(result)
    except:
        return (0,0,0)

# Fail gracefully for old versions of Python.

if sys.version[:3] < '2.6':
    writeln("GMPY2 requires Python 2.6 or later.")
    writeln("Please use GMPY 1.x for earlier versions of Python.")
    sys.exit()

# Improved clean command.

class gmpy_clean(clean):

    def run(self):
        self.all = True
        clean.run(self)

# Define a custom build class to force a new build.

class gmpy_build_ext(build_ext):

    # Extract the version information from the various header files. Since header
    # store the information differently, a separate function is provided for each
    # library.

    def check_versions(self):
        # Check the specified list of include directories to verify that valid
        # versions of MPFR and MPC are available. If so, add entries to the
        # appropriate lists

        # Find the directory specfied for PREFIX.
        prefix = ''
        for i,d in enumerate(self.extensions[0].define_macros[:]):
            if d[0] == 'PREFIX':
                prefix = d[1]
                try:
                    self.extensions[0].define_macros.remove(d)
                except ValueError:
                    pass

        if sys.version.find('MSC') == -1:
            windows = False
            base_dir = ['/usr']
            addin_dirs = ['/usr/local']
        else:
            windows = True
            base_dir = []
            addin_dirs = []

        if prefix:
            search_dirs =  base_dir + addin_dirs + [prefix]
        else:
            search_dirs = base_dir + addin_dirs

        if 'gmp' in self.extensions[0].libraries:
            mplib = 'gmp'
        else:
            mplib = 'mpir'

        use_mpfr = 'mpfr' in self.extensions[0].libraries
        use_mpc = 'mpc' in self.extensions[0].libraries

        # Try to find a directory prefix that contains valid MPFR and MPC
        # libraries. Only the version numbers of MPFR and MPC are checked.
        # Don't bother checking for GMP version since it is effectively a
        # prerequisite for MPFR and MPC.

        if not search_dirs:
            return

        mpfr_found = ''
        mpfr_version = (0,0,0)
        mpc_found = ''
        mpc_version = (0,0,0)

        for adir in search_dirs:
            lookin = adir + '/include'

            # If MPFR and MPC support is required, verify that the header files
            # exist in the same directory. If not, generate an error message.
            # If header isn't found, go to the next directory.

            # For debugging information, uncomment the following lines.
            # writeln('looking in: %s' % lookin)
            # writeln('mpfr.h found: %s' % os.path.isfile(lookin + '/mpfr.h'))
            # writeln('mpfr.h version %s' % repr(get_mpfr_version(lookin + '/mpfr.h')))
            # writeln('mpc.h found: %s' % os.path.isfile(lookin + '/mpc.h'))
            # writeln('mpc.h version %s' % repr(get_mpc_version(lookin + '/mpc.h')))

            if use_mpfr and os.path.isfile(lookin + '/mpfr.h'):
                v = get_mpfr_version(lookin + '/mpfr.h')
                if v >= mpfr_version:
                    mpfr_found = adir
                    mpfr_version = v

            if use_mpc and os.path.isfile(lookin + '/mpc.h'):
                v = get_mpc_version(lookin + '/mpc.h')
                if v >=mpc_version:
                    mpc_found = adir
                    mpc_version = v

        if mpfr_version < (3,1,0):
            mpfr_found = False
        if mpc_version < (1,0,0):
            mpc_found = False

        if (use_mpfr and not mpfr_found) or (use_mpc and not mpc_found):
            writeln('----------------------------------------------------------------')
            writeln('setup.py was not able to detect the required versions of MPFR')
            writeln('and/or MPC. gmpy2 requires MPFR version 3.1.0 or greater and')
            writeln('MPC version 1.0.0 or greater. To specify a directory prefix that')
            writeln('contains the proper versions, use the --prefix=<dir> option.')
            writeln('')
            writeln('In some circumstances, the correct versions may be present and')
            writeln('this warning can be ignored. If you have difficulties compiling')
            writeln('or running gmpy2, please try compiling with the --prefix option.')
            writeln('')
            writeln('It is possible to compile gmpy2 without support for MPFR and MPC')
            writeln('but that is not a supported configuration. Beginning with v2.1.0,')
            writeln('MPFR and MPC will be required.')
            writeln('')
            writeln('setup.py will continue and attempt to compile gmpy2.')
            writeln('-----------------------------------------------------------------')

        # Add the directory information for location where valid versions were
        # found. This can cause confusion if there are multiple installations of
        # the same version of Python on the system.

        for adir in (mpfr_found, mpc_found):
            if not adir:
                continue
            if adir in base_dir:
                continue
            if adir + '/include' in self.extensions[0].include_dirs:
                continue
            self.extensions[0].include_dirs += [adir + '/include']
            self.extensions[0].library_dirs += [adir + lib_path]
            if not windows:
                self.extensions[0].runtime_library_dirs += [adir + lib_path]

        # If the instance of Python used to compile gmpy2 not found in 'prefix',
        # then specify the Python shared library to use.
        if not windows and not get_python_lib(standard_lib=True).startswith(prefix):
            self.extensions[0].libraries = [get_python_lib(standard_lib=True)] \
                                            + self.extensions[0].libraries

        # For debugging information, uncomment the following lines.
        # writeln([mpfr_found, mpc_found])
        # writeln(self.extensions[0].include_dirs)
        # writeln(self.extensions[0].library_dirs)
        # writeln(self.extensions[0].runtime_library_dirs)
        # writeln(self.extensions[0].libraries)

    def finalize_options(self):
        build_ext.finalize_options(self)
        gmpy_build_ext.check_versions(self)
        # Check if --force was specified.
        for i,d in enumerate(self.extensions[0].define_macros[:]):
            if d[0] == 'FORCE':
                self.force = 1
                try:
                    self.extensions[0].define_macros.remove(d)
                except ValueError:
                    pass

# Several command line options can be used to modify compilation of GMPY2. To
# maintain backwards compatibility with older versions of setup.py, the old
# options are still supported.
#
# New-style options
#
#  --force         -> ignore timestamps and recompile
#  --mpir          -> use MPIR instead of GMP (GMP is the default on
#                     non-Windows operating systems)
#  --gmp           -> use GMP instead of MPIR
#  --nompfr        -> disable MPFR and MPC library support
#  --nompc         -> disable MPC support (MPFR should still work)
#  --lib64         -> use /prefix/lib64 instead of /prefix/lib
#  --prefix=<...>  -> add the specified directory prefix to the beginning of
#                     the list of directories that are searched for GMP, MPFR,
#                     and MPC
#
# Old-stype options
#
#   -DMPIR       -> use MPIR instead of GMP
#   -DGMP        -> use GMP instead of MPIR
#   -DNOMPFR     -> disable MPFR and MPC library support
#   -DNOMPC      -> disable MPC support (MPFR should still work)
#   -Ddir=<...>  -> add the specified directory to beginning of the list of
#                   directories that are searched for GMP, MPFR, and MPC

# Windows build defaults to using MPIR.

if sys.version.find('MSC') == -1:
    mplib='gmp'
else:
    mplib='mpir'

# If 'clean' is the only argument to setup.py then we want to skip looking for
# header files.

if sys.argv[1].lower() in ['build', 'install']:
    do_search = True
else:
    do_search = False

# Parse command line arguments. If custom prefix location is specified, it is
# passed as a define so it can be processed in the custom build_ext defined
# above.

defines = []

# Beginning with v2.1.0, MPFR and MPC will be required.

use_mpc = True
use_mpfr = True
force = False

for token in sys.argv[:]:
    if token.lower() == '--force':
        defines.append( ('FORCE', 1) )
        sys.argv.remove(token)

    if token.lower() == '--lib64':
        lib_path = '/lib64'
        sys.argv.remove(token)

    if token.lower() == '--mpir':
        mplib = 'mpir'
        sys.argv.remove(token)

    if token.lower() == '--gmp':
        mplib = 'gmp'
        sys.argv.remove(token)

    if token.lower() == '--nompc':
        use_mpc = False
        sys.argv.remove(token)

    if token.lower() == '--nompfr':
        use_mpfr = False
        use_mpc = False
        sys.argv.remove(token)

    if token.lower().startswith('--prefix'):
        try:
            defines.append( ('PREFIX', token.split('=')[1]) )
        except:
            writeln('Please include a directory location.')
        sys.argv.remove(token)

    # The following options are deprecated and will be removed in the future.
    if token.upper().startswith('-DMPIR'):
        mplib='mpir'
        sys.argv.remove(token)
        writeln('The -DMPIR option is deprecated. Use --mpir instead.')

    if token.upper().startswith('-DGMP'):
        mplib='gmp'
        sys.argv.remove(token)
        writeln('The -DGMP option is deprecated. Use --gmp instead.')

    if token.upper().startswith('-DNOMPC'):
        use_mpc = False
        sys.argv.remove(token)
        writeln('The -DNOMPC option is deprecated. Use --nompc instead.')

    if token.upper().startswith('-DNOMPFR'):
        use_mpfr = False
        use_mpc = False
        sys.argv.remove(token)
        writeln('The -DNOMPFR option is deprecated. Use --nompfr instead.')

    if token.upper().startswith('-DDIR'):
        try:
            defines.append( ('PREFIX', token.split('=')[1]) )
        except:
            writeln('Please include a directory location.')
        sys.argv.remove(token)
        writeln('The -DDIR option is deprecated. Use --prefix instead.')

incdirs = ['./src']
libdirs = []
rundirs = []

# Specify extra link arguments for Windows.

if sys.version.find('MSC') == -1:
    my_extra_link_args = None
else:
    my_extra_link_args = ["/MANIFEST"]

mp_found = False

# Configure the defines...

if mplib == 'mpir':
    defines.append( ('MPIR', None) )
    libs = ['mpir']
else:
    libs = ['gmp']

if use_mpfr:
    defines.append( ('WITHMPFR', None) )
    libs.append('mpfr')

if use_mpc:
    defines.append( ('WITHMPC', None) )
    libs.append('mpc')



# decomment next line (w/gcc, only!) to support gcov
#   os.environ['CFLAGS'] = '-fprofile-arcs -ftest-coverage -O0'

# prepare the extension for building

my_commands = {'clean' : gmpy_clean, 'build_ext' : gmpy_build_ext}

gmpy2_ext = Extension('gmpy2',
                      sources=['src/gmpy2.c'],
                      include_dirs=incdirs,
                      library_dirs=libdirs,
                      libraries=libs,
                      runtime_library_dirs=rundirs,
                      define_macros = defines,
                      extra_link_args = my_extra_link_args)

setup(name = "gmpy2",
      version = "2.0.3",
      maintainer = "Case Van Horsen",
      maintainer_email = "casevh@gmail.com",
      url = "http://code.google.com/p/gmpy/",
      description = "GMP/MPIR, MPFR, and MPC interface to Python 2.6+ and 3.x",
      classifiers = [
        'Development Status :: 4 - Beta',
        'Intended Audience :: Developers',
        'Intended Audience :: Science/Research'
        'License :: OSI Approved :: GNU Lesser General Public License v3 or later (LGPLv3+)',
        'Natural Language :: English',
        'Operating System :: MacOS :: MacOS X',
        'Operating System :: Microsoft :: Windows',
        'Operating System :: POSIX',
        'Programming Language :: C',
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: Implementation :: CPython',
        'Topic :: Scientific/Engineering :: Mathematics',
        'Topic :: Software Development :: Libraries :: Python Modules',
      ],
      cmdclass = my_commands,
      ext_modules = [gmpy2_ext]
)