##// END OF EJS Templates
setup: show how to set the module policy for imports...
timeless -
r28431:a7e3b72c default
parent child Browse files
Show More
@@ -1,668 +1,675
1 1 #
2 2 # This is the mercurial setup script.
3 3 #
4 4 # 'python setup.py install', or
5 5 # 'python setup.py --help' for more options
6 6
7 7 import sys, platform
8 8 if getattr(sys, 'version_info', (0, 0, 0)) < (2, 6, 0, 'final'):
9 9 raise SystemExit("Mercurial requires Python 2.6 or later.")
10 10
11 11 if sys.version_info[0] >= 3:
12 12 printf = eval('print')
13 13 libdir_escape = 'unicode_escape'
14 14 else:
15 15 libdir_escape = 'string_escape'
16 16 def printf(*args, **kwargs):
17 17 f = kwargs.get('file', sys.stdout)
18 18 end = kwargs.get('end', '\n')
19 19 f.write(b' '.join(args) + end)
20 20
21 21 # Solaris Python packaging brain damage
22 22 try:
23 23 import hashlib
24 24 sha = hashlib.sha1()
25 25 except ImportError:
26 26 try:
27 27 import sha
28 28 sha.sha # silence unused import warning
29 29 except ImportError:
30 30 raise SystemExit(
31 31 "Couldn't import standard hashlib (incomplete Python install).")
32 32
33 33 try:
34 34 import zlib
35 35 zlib.compressobj # silence unused import warning
36 36 except ImportError:
37 37 raise SystemExit(
38 38 "Couldn't import standard zlib (incomplete Python install).")
39 39
40 40 # The base IronPython distribution (as of 2.7.1) doesn't support bz2
41 41 isironpython = False
42 42 try:
43 43 isironpython = (platform.python_implementation()
44 44 .lower().find("ironpython") != -1)
45 45 except AttributeError:
46 46 pass
47 47
48 48 if isironpython:
49 49 sys.stderr.write("warning: IronPython detected (no bz2 support)\n")
50 50 else:
51 51 try:
52 52 import bz2
53 53 bz2.BZ2Compressor # silence unused import warning
54 54 except ImportError:
55 55 raise SystemExit(
56 56 "Couldn't import standard bz2 (incomplete Python install).")
57 57
58 58 ispypy = "PyPy" in sys.version
59 59
60 60 import os, stat, subprocess, time
61 61 import re
62 62 import shutil
63 63 import tempfile
64 64 from distutils import log
65 65 if 'FORCE_SETUPTOOLS' in os.environ:
66 66 from setuptools import setup
67 67 else:
68 68 from distutils.core import setup
69 69 from distutils.core import Command, Extension
70 70 from distutils.dist import Distribution
71 71 from distutils.command.build import build
72 72 from distutils.command.build_ext import build_ext
73 73 from distutils.command.build_py import build_py
74 74 from distutils.command.build_scripts import build_scripts
75 75 from distutils.command.install_lib import install_lib
76 76 from distutils.command.install_scripts import install_scripts
77 77 from distutils.spawn import spawn, find_executable
78 78 from distutils import file_util
79 79 from distutils.errors import (
80 80 CCompilerError,
81 81 DistutilsError,
82 82 DistutilsExecError,
83 83 )
84 84 from distutils.sysconfig import get_python_inc, get_config_var
85 85 from distutils.version import StrictVersion
86 86
87 87 scripts = ['hg']
88 88 if os.name == 'nt':
89 89 # We remove hg.bat if we are able to build hg.exe.
90 90 scripts.append('contrib/win32/hg.bat')
91 91
92 92 # simplified version of distutils.ccompiler.CCompiler.has_function
93 93 # that actually removes its temporary files.
94 94 def hasfunction(cc, funcname):
95 95 tmpdir = tempfile.mkdtemp(prefix='hg-install-')
96 96 devnull = oldstderr = None
97 97 try:
98 98 fname = os.path.join(tmpdir, 'funcname.c')
99 99 f = open(fname, 'w')
100 100 f.write('int main(void) {\n')
101 101 f.write(' %s();\n' % funcname)
102 102 f.write('}\n')
103 103 f.close()
104 104 # Redirect stderr to /dev/null to hide any error messages
105 105 # from the compiler.
106 106 # This will have to be changed if we ever have to check
107 107 # for a function on Windows.
108 108 devnull = open('/dev/null', 'w')
109 109 oldstderr = os.dup(sys.stderr.fileno())
110 110 os.dup2(devnull.fileno(), sys.stderr.fileno())
111 111 objects = cc.compile([fname], output_dir=tmpdir)
112 112 cc.link_executable(objects, os.path.join(tmpdir, "a.out"))
113 113 return True
114 114 except Exception:
115 115 return False
116 116 finally:
117 117 if oldstderr is not None:
118 118 os.dup2(oldstderr, sys.stderr.fileno())
119 119 if devnull is not None:
120 120 devnull.close()
121 121 shutil.rmtree(tmpdir)
122 122
123 123 # py2exe needs to be installed to work
124 124 try:
125 125 import py2exe
126 126 py2exe.Distribution # silence unused import warning
127 127 py2exeloaded = True
128 128 # import py2exe's patched Distribution class
129 129 from distutils.core import Distribution
130 130 except ImportError:
131 131 py2exeloaded = False
132 132
133 133 def runcmd(cmd, env):
134 134 if (sys.platform == 'plan9'
135 135 and (sys.version_info[0] == 2 and sys.version_info[1] < 7)):
136 136 # subprocess kludge to work around issues in half-baked Python
137 137 # ports, notably bichued/python:
138 138 _, out, err = os.popen3(cmd)
139 139 return str(out), str(err)
140 140 else:
141 141 p = subprocess.Popen(cmd, stdout=subprocess.PIPE,
142 142 stderr=subprocess.PIPE, env=env)
143 143 out, err = p.communicate()
144 144 return out, err
145 145
146 146 def runhg(cmd, env):
147 147 out, err = runcmd(cmd, env)
148 148 # If root is executing setup.py, but the repository is owned by
149 149 # another user (as in "sudo python setup.py install") we will get
150 150 # trust warnings since the .hg/hgrc file is untrusted. That is
151 151 # fine, we don't want to load it anyway. Python may warn about
152 152 # a missing __init__.py in mercurial/locale, we also ignore that.
153 153 err = [e for e in err.splitlines()
154 154 if not e.startswith(b'not trusting file') \
155 155 and not e.startswith(b'warning: Not importing') \
156 156 and not e.startswith(b'obsolete feature not enabled')]
157 157 if err:
158 158 printf("stderr from '%s':" % (' '.join(cmd)), file=sys.stderr)
159 159 printf(b'\n'.join([b' ' + e for e in err]), file=sys.stderr)
160 160 return ''
161 161 return out
162 162
163 163 version = ''
164 164
165 165 # Execute hg out of this directory with a custom environment which takes care
166 166 # to not use any hgrc files and do no localization.
167 167 env = {'HGMODULEPOLICY': 'py',
168 168 'HGRCPATH': '',
169 169 'LANGUAGE': 'C'}
170 170 if 'LD_LIBRARY_PATH' in os.environ:
171 171 env['LD_LIBRARY_PATH'] = os.environ['LD_LIBRARY_PATH']
172 172 if 'SystemRoot' in os.environ:
173 173 # Copy SystemRoot into the custom environment for Python 2.6
174 174 # under Windows. Otherwise, the subprocess will fail with
175 175 # error 0xc0150004. See: http://bugs.python.org/issue3440
176 176 env['SystemRoot'] = os.environ['SystemRoot']
177 177
178 178 if os.path.isdir('.hg'):
179 179 cmd = [sys.executable, 'hg', 'log', '-r', '.', '--template', '{tags}\n']
180 180 numerictags = [t for t in runhg(cmd, env).split() if t[0].isdigit()]
181 181 hgid = runhg([sys.executable, 'hg', 'id', '-i'], env).strip()
182 182 if numerictags: # tag(s) found
183 183 version = numerictags[-1]
184 184 if hgid.endswith('+'): # propagate the dirty status to the tag
185 185 version += '+'
186 186 else: # no tag found
187 187 ltagcmd = [sys.executable, 'hg', 'parents', '--template',
188 188 '{latesttag}']
189 189 ltag = runhg(ltagcmd, env)
190 190 changessincecmd = [sys.executable, 'hg', 'log', '-T', 'x\n', '-r',
191 191 "only(.,'%s')" % ltag]
192 192 changessince = len(runhg(changessincecmd, env).splitlines())
193 193 version = '%s+%s-%s' % (ltag, changessince, hgid)
194 194 if version.endswith('+'):
195 195 version += time.strftime('%Y%m%d')
196 196 elif os.path.exists('.hg_archival.txt'):
197 197 kw = dict([[t.strip() for t in l.split(':', 1)]
198 198 for l in open('.hg_archival.txt')])
199 199 if 'tag' in kw:
200 200 version = kw['tag']
201 201 elif 'latesttag' in kw:
202 202 if 'changessincelatesttag' in kw:
203 203 version = '%(latesttag)s+%(changessincelatesttag)s-%(node).12s' % kw
204 204 else:
205 205 version = '%(latesttag)s+%(latesttagdistance)s-%(node).12s' % kw
206 206 else:
207 207 version = kw.get('node', '')[:12]
208 208
209 209 if version:
210 210 with open("mercurial/__version__.py", "w") as f:
211 211 f.write('# this file is autogenerated by setup.py\n')
212 212 f.write('version = "%s"\n' % version)
213 213
214 214 try:
215 oldpolicy = os.environ.get('HGMODULEPOLICY', None)
216 os.environ['HGMODULEPOLICY'] = 'py'
215 217 from mercurial import __version__
216 218 version = __version__.version
217 219 except ImportError:
218 220 version = 'unknown'
221 finally:
222 if oldpolicy is None:
223 del os.environ['HGMODULEPOLICY']
224 else:
225 os.environ['HGMODULEPOLICY'] = oldpolicy
219 226
220 227 class hgbuild(build):
221 228 # Insert hgbuildmo first so that files in mercurial/locale/ are found
222 229 # when build_py is run next.
223 230 sub_commands = [('build_mo', None)] + build.sub_commands
224 231
225 232 class hgbuildmo(build):
226 233
227 234 description = "build translations (.mo files)"
228 235
229 236 def run(self):
230 237 if not find_executable('msgfmt'):
231 238 self.warn("could not find msgfmt executable, no translations "
232 239 "will be built")
233 240 return
234 241
235 242 podir = 'i18n'
236 243 if not os.path.isdir(podir):
237 244 self.warn("could not find %s/ directory" % podir)
238 245 return
239 246
240 247 join = os.path.join
241 248 for po in os.listdir(podir):
242 249 if not po.endswith('.po'):
243 250 continue
244 251 pofile = join(podir, po)
245 252 modir = join('locale', po[:-3], 'LC_MESSAGES')
246 253 mofile = join(modir, 'hg.mo')
247 254 mobuildfile = join('mercurial', mofile)
248 255 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
249 256 if sys.platform != 'sunos5':
250 257 # msgfmt on Solaris does not know about -c
251 258 cmd.append('-c')
252 259 self.mkpath(join('mercurial', modir))
253 260 self.make_file([pofile], mobuildfile, spawn, (cmd,))
254 261
255 262
256 263 class hgdist(Distribution):
257 264 pure = ispypy
258 265
259 266 global_options = Distribution.global_options + \
260 267 [('pure', None, "use pure (slow) Python "
261 268 "code instead of C extensions"),
262 269 ]
263 270
264 271 def has_ext_modules(self):
265 272 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
266 273 # too late for some cases
267 274 return not self.pure and Distribution.has_ext_modules(self)
268 275
269 276 class hgbuildext(build_ext):
270 277
271 278 def build_extension(self, ext):
272 279 try:
273 280 build_ext.build_extension(self, ext)
274 281 except CCompilerError:
275 282 if not getattr(ext, 'optional', False):
276 283 raise
277 284 log.warn("Failed to build optional extension '%s' (skipping)",
278 285 ext.name)
279 286
280 287 class hgbuildscripts(build_scripts):
281 288 def run(self):
282 289 if os.name != 'nt' or self.distribution.pure:
283 290 return build_scripts.run(self)
284 291
285 292 exebuilt = False
286 293 try:
287 294 self.run_command('build_hgexe')
288 295 exebuilt = True
289 296 except (DistutilsError, CCompilerError):
290 297 log.warn('failed to build optional hg.exe')
291 298
292 299 if exebuilt:
293 300 # Copying hg.exe to the scripts build directory ensures it is
294 301 # installed by the install_scripts command.
295 302 hgexecommand = self.get_finalized_command('build_hgexe')
296 303 dest = os.path.join(self.build_dir, 'hg.exe')
297 304 self.mkpath(self.build_dir)
298 305 self.copy_file(hgexecommand.hgexepath, dest)
299 306
300 307 # Remove hg.bat because it is redundant with hg.exe.
301 308 self.scripts.remove('contrib/win32/hg.bat')
302 309
303 310 return build_scripts.run(self)
304 311
305 312 class hgbuildpy(build_py):
306 313 def finalize_options(self):
307 314 build_py.finalize_options(self)
308 315
309 316 if self.distribution.pure:
310 317 self.distribution.ext_modules = []
311 318 else:
312 319 h = os.path.join(get_python_inc(), 'Python.h')
313 320 if not os.path.exists(h):
314 321 raise SystemExit('Python headers are required to build '
315 322 'Mercurial but weren\'t found in %s' % h)
316 323
317 324 def run(self):
318 325 if self.distribution.pure:
319 326 modulepolicy = 'py'
320 327 else:
321 328 modulepolicy = 'c'
322 329 with open("mercurial/__modulepolicy__.py", "w") as f:
323 330 f.write('# this file is autogenerated by setup.py\n')
324 331 f.write('modulepolicy = "%s"\n' % modulepolicy)
325 332
326 333 build_py.run(self)
327 334
328 335 class buildhgextindex(Command):
329 336 description = 'generate prebuilt index of hgext (for frozen package)'
330 337 user_options = []
331 338 _indexfilename = 'hgext/__index__.py'
332 339
333 340 def initialize_options(self):
334 341 pass
335 342
336 343 def finalize_options(self):
337 344 pass
338 345
339 346 def run(self):
340 347 if os.path.exists(self._indexfilename):
341 348 with open(self._indexfilename, 'w') as f:
342 349 f.write('# empty\n')
343 350
344 351 # here no extension enabled, disabled() lists up everything
345 352 code = ('import pprint; from mercurial import extensions; '
346 353 'pprint.pprint(extensions.disabled())')
347 354 out, err = runcmd([sys.executable, '-c', code], env)
348 355 if err:
349 356 raise DistutilsExecError(err)
350 357
351 358 with open(self._indexfilename, 'w') as f:
352 359 f.write('# this file is autogenerated by setup.py\n')
353 360 f.write('docs = ')
354 361 f.write(out)
355 362
356 363 class buildhgexe(build_ext):
357 364 description = 'compile hg.exe from mercurial/exewrapper.c'
358 365
359 366 def build_extensions(self):
360 367 if os.name != 'nt':
361 368 return
362 369 if isinstance(self.compiler, HackedMingw32CCompiler):
363 370 self.compiler.compiler_so = self.compiler.compiler # no -mdll
364 371 self.compiler.dll_libraries = [] # no -lmsrvc90
365 372 hv = sys.hexversion
366 373 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
367 374 with open('mercurial/hgpythonlib.h', 'wb') as f:
368 375 f.write('/* this file is autogenerated by setup.py */\n')
369 376 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
370 377 objects = self.compiler.compile(['mercurial/exewrapper.c'],
371 378 output_dir=self.build_temp)
372 379 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
373 380 target = os.path.join(dir, 'hg')
374 381 self.compiler.link_executable(objects, target,
375 382 libraries=[],
376 383 output_dir=self.build_temp)
377 384
378 385 @property
379 386 def hgexepath(self):
380 387 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
381 388 return os.path.join(self.build_temp, dir, 'hg.exe')
382 389
383 390 class hginstalllib(install_lib):
384 391 '''
385 392 This is a specialization of install_lib that replaces the copy_file used
386 393 there so that it supports setting the mode of files after copying them,
387 394 instead of just preserving the mode that the files originally had. If your
388 395 system has a umask of something like 027, preserving the permissions when
389 396 copying will lead to a broken install.
390 397
391 398 Note that just passing keep_permissions=False to copy_file would be
392 399 insufficient, as it might still be applying a umask.
393 400 '''
394 401
395 402 def run(self):
396 403 realcopyfile = file_util.copy_file
397 404 def copyfileandsetmode(*args, **kwargs):
398 405 src, dst = args[0], args[1]
399 406 dst, copied = realcopyfile(*args, **kwargs)
400 407 if copied:
401 408 st = os.stat(src)
402 409 # Persist executable bit (apply it to group and other if user
403 410 # has it)
404 411 if st[stat.ST_MODE] & stat.S_IXUSR:
405 412 setmode = int('0755', 8)
406 413 else:
407 414 setmode = int('0644', 8)
408 415 m = stat.S_IMODE(st[stat.ST_MODE])
409 416 m = (m & ~int('0777', 8)) | setmode
410 417 os.chmod(dst, m)
411 418 file_util.copy_file = copyfileandsetmode
412 419 try:
413 420 install_lib.run(self)
414 421 finally:
415 422 file_util.copy_file = realcopyfile
416 423
417 424 class hginstallscripts(install_scripts):
418 425 '''
419 426 This is a specialization of install_scripts that replaces the @LIBDIR@ with
420 427 the configured directory for modules. If possible, the path is made relative
421 428 to the directory for scripts.
422 429 '''
423 430
424 431 def initialize_options(self):
425 432 install_scripts.initialize_options(self)
426 433
427 434 self.install_lib = None
428 435
429 436 def finalize_options(self):
430 437 install_scripts.finalize_options(self)
431 438 self.set_undefined_options('install',
432 439 ('install_lib', 'install_lib'))
433 440
434 441 def run(self):
435 442 install_scripts.run(self)
436 443
437 444 # It only makes sense to replace @LIBDIR@ with the install path if
438 445 # the install path is known. For wheels, the logic below calculates
439 446 # the libdir to be "../..". This is because the internal layout of a
440 447 # wheel archive looks like:
441 448 #
442 449 # mercurial-3.6.1.data/scripts/hg
443 450 # mercurial/__init__.py
444 451 #
445 452 # When installing wheels, the subdirectories of the "<pkg>.data"
446 453 # directory are translated to system local paths and files therein
447 454 # are copied in place. The mercurial/* files are installed into the
448 455 # site-packages directory. However, the site-packages directory
449 456 # isn't known until wheel install time. This means we have no clue
450 457 # at wheel generation time what the installed site-packages directory
451 458 # will be. And, wheels don't appear to provide the ability to register
452 459 # custom code to run during wheel installation. This all means that
453 460 # we can't reliably set the libdir in wheels: the default behavior
454 461 # of looking in sys.path must do.
455 462
456 463 if (os.path.splitdrive(self.install_dir)[0] !=
457 464 os.path.splitdrive(self.install_lib)[0]):
458 465 # can't make relative paths from one drive to another, so use an
459 466 # absolute path instead
460 467 libdir = self.install_lib
461 468 else:
462 469 common = os.path.commonprefix((self.install_dir, self.install_lib))
463 470 rest = self.install_dir[len(common):]
464 471 uplevel = len([n for n in os.path.split(rest) if n])
465 472
466 473 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
467 474
468 475 for outfile in self.outfiles:
469 476 with open(outfile, 'rb') as fp:
470 477 data = fp.read()
471 478
472 479 # skip binary files
473 480 if b'\0' in data:
474 481 continue
475 482
476 483 # During local installs, the shebang will be rewritten to the final
477 484 # install path. During wheel packaging, the shebang has a special
478 485 # value.
479 486 if data.startswith(b'#!python'):
480 487 log.info('not rewriting @LIBDIR@ in %s because install path '
481 488 'not known' % outfile)
482 489 continue
483 490
484 491 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape))
485 492 with open(outfile, 'wb') as fp:
486 493 fp.write(data)
487 494
488 495 cmdclass = {'build': hgbuild,
489 496 'build_mo': hgbuildmo,
490 497 'build_ext': hgbuildext,
491 498 'build_py': hgbuildpy,
492 499 'build_scripts': hgbuildscripts,
493 500 'build_hgextindex': buildhgextindex,
494 501 'install_lib': hginstalllib,
495 502 'install_scripts': hginstallscripts,
496 503 'build_hgexe': buildhgexe,
497 504 }
498 505
499 506 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
500 507 'mercurial.pure',
501 508 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
502 509 'hgext.largefiles']
503 510
504 511 common_depends = ['mercurial/util.h']
505 512
506 513 osutil_ldflags = []
507 514
508 515 if sys.platform == 'darwin':
509 516 osutil_ldflags += ['-framework', 'ApplicationServices']
510 517
511 518 extmodules = [
512 519 Extension('mercurial.base85', ['mercurial/base85.c'],
513 520 depends=common_depends),
514 521 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
515 522 depends=common_depends),
516 523 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
517 524 depends=common_depends),
518 525 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
519 526 depends=common_depends),
520 527 Extension('mercurial.parsers', ['mercurial/dirs.c',
521 528 'mercurial/manifest.c',
522 529 'mercurial/parsers.c',
523 530 'mercurial/pathencode.c'],
524 531 depends=common_depends),
525 532 Extension('mercurial.osutil', ['mercurial/osutil.c'],
526 533 extra_link_args=osutil_ldflags,
527 534 depends=common_depends),
528 535 ]
529 536
530 537 try:
531 538 from distutils import cygwinccompiler
532 539
533 540 # the -mno-cygwin option has been deprecated for years
534 541 compiler = cygwinccompiler.Mingw32CCompiler
535 542
536 543 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
537 544 def __init__(self, *args, **kwargs):
538 545 compiler.__init__(self, *args, **kwargs)
539 546 for i in 'compiler compiler_so linker_exe linker_so'.split():
540 547 try:
541 548 getattr(self, i).remove('-mno-cygwin')
542 549 except ValueError:
543 550 pass
544 551
545 552 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
546 553 except ImportError:
547 554 # the cygwinccompiler package is not available on some Python
548 555 # distributions like the ones from the optware project for Synology
549 556 # DiskStation boxes
550 557 class HackedMingw32CCompiler(object):
551 558 pass
552 559
553 560 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
554 561 'help/*.txt',
555 562 'help/internals/*.txt',
556 563 'default.d/*.rc',
557 564 'dummycert.pem']}
558 565
559 566 def ordinarypath(p):
560 567 return p and p[0] != '.' and p[-1] != '~'
561 568
562 569 for root in ('templates',):
563 570 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
564 571 curdir = curdir.split(os.sep, 1)[1]
565 572 dirs[:] = filter(ordinarypath, dirs)
566 573 for f in filter(ordinarypath, files):
567 574 f = os.path.join(curdir, f)
568 575 packagedata['mercurial'].append(f)
569 576
570 577 datafiles = []
571 578 setupversion = version
572 579 extra = {}
573 580
574 581 if py2exeloaded:
575 582 extra['console'] = [
576 583 {'script':'hg',
577 584 'copyright':'Copyright (C) 2005-2016 Matt Mackall and others',
578 585 'product_version':version}]
579 586 # sub command of 'build' because 'py2exe' does not handle sub_commands
580 587 build.sub_commands.insert(0, ('build_hgextindex', None))
581 588 # put dlls in sub directory so that they won't pollute PATH
582 589 extra['zipfile'] = 'lib/library.zip'
583 590
584 591 if os.name == 'nt':
585 592 # Windows binary file versions for exe/dll files must have the
586 593 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
587 594 setupversion = version.split('+', 1)[0]
588 595
589 596 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
590 597 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
591 598 if version:
592 599 version = version[0]
593 600 if sys.version_info[0] == 3:
594 601 version = version.decode('utf-8')
595 602 xcode4 = (version.startswith('Xcode') and
596 603 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
597 604 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
598 605 else:
599 606 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
600 607 # installed, but instead with only command-line tools. Assume
601 608 # that only happens on >= Lion, thus no PPC support.
602 609 xcode4 = True
603 610 xcode51 = False
604 611
605 612 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
606 613 # distutils.sysconfig
607 614 if xcode4:
608 615 os.environ['ARCHFLAGS'] = ''
609 616
610 617 # XCode 5.1 changes clang such that it now fails to compile if the
611 618 # -mno-fused-madd flag is passed, but the version of Python shipped with
612 619 # OS X 10.9 Mavericks includes this flag. This causes problems in all
613 620 # C extension modules, and a bug has been filed upstream at
614 621 # http://bugs.python.org/issue21244. We also need to patch this here
615 622 # so Mercurial can continue to compile in the meantime.
616 623 if xcode51:
617 624 cflags = get_config_var('CFLAGS')
618 625 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
619 626 os.environ['CFLAGS'] = (
620 627 os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
621 628
622 629 setup(name='mercurial',
623 630 version=setupversion,
624 631 author='Matt Mackall and many others',
625 632 author_email='mercurial@selenic.com',
626 633 url='https://mercurial-scm.org/',
627 634 download_url='https://mercurial-scm.org/release/',
628 635 description=('Fast scalable distributed SCM (revision control, version '
629 636 'control) system'),
630 637 long_description=('Mercurial is a distributed SCM tool written in Python.'
631 638 ' It is used by a number of large projects that require'
632 639 ' fast, reliable distributed revision control, such as '
633 640 'Mozilla.'),
634 641 license='GNU GPLv2 or any later version',
635 642 classifiers=[
636 643 'Development Status :: 6 - Mature',
637 644 'Environment :: Console',
638 645 'Intended Audience :: Developers',
639 646 'Intended Audience :: System Administrators',
640 647 'License :: OSI Approved :: GNU General Public License (GPL)',
641 648 'Natural Language :: Danish',
642 649 'Natural Language :: English',
643 650 'Natural Language :: German',
644 651 'Natural Language :: Italian',
645 652 'Natural Language :: Japanese',
646 653 'Natural Language :: Portuguese (Brazilian)',
647 654 'Operating System :: Microsoft :: Windows',
648 655 'Operating System :: OS Independent',
649 656 'Operating System :: POSIX',
650 657 'Programming Language :: C',
651 658 'Programming Language :: Python',
652 659 'Topic :: Software Development :: Version Control',
653 660 ],
654 661 scripts=scripts,
655 662 packages=packages,
656 663 ext_modules=extmodules,
657 664 data_files=datafiles,
658 665 package_data=packagedata,
659 666 cmdclass=cmdclass,
660 667 distclass=hgdist,
661 668 options={'py2exe': {'packages': ['hgext', 'email']},
662 669 'bdist_mpkg': {'zipdist': False,
663 670 'license': 'COPYING',
664 671 'readme': 'contrib/macosx/Readme.html',
665 672 'welcome': 'contrib/macosx/Welcome.html',
666 673 },
667 674 },
668 675 **extra)
General Comments 0
You need to be logged in to leave comments. Login now