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]
)
|