##// END OF EJS Templates
setup: switch to with open as...
timeless -
r28418:121d2571 default
parent child Browse files
Show More
@@ -1,680 +1,673 b''
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 f = open("mercurial/__version__.py", "w")
211 f.write('# this file is autogenerated by setup.py\n')
212 f.write('version = "%s"\n' % version)
213 f.close()
214
210 with open("mercurial/__version__.py", "w") as f:
211 f.write('# this file is autogenerated by setup.py\n')
212 f.write('version = "%s"\n' % version)
215 213
216 214 try:
217 215 from mercurial import __version__
218 216 version = __version__.version
219 217 except ImportError:
220 218 version = 'unknown'
221 219
222 220 class hgbuild(build):
223 221 # Insert hgbuildmo first so that files in mercurial/locale/ are found
224 222 # when build_py is run next.
225 223 sub_commands = [('build_mo', None)] + build.sub_commands
226 224
227 225 class hgbuildmo(build):
228 226
229 227 description = "build translations (.mo files)"
230 228
231 229 def run(self):
232 230 if not find_executable('msgfmt'):
233 231 self.warn("could not find msgfmt executable, no translations "
234 232 "will be built")
235 233 return
236 234
237 235 podir = 'i18n'
238 236 if not os.path.isdir(podir):
239 237 self.warn("could not find %s/ directory" % podir)
240 238 return
241 239
242 240 join = os.path.join
243 241 for po in os.listdir(podir):
244 242 if not po.endswith('.po'):
245 243 continue
246 244 pofile = join(podir, po)
247 245 modir = join('locale', po[:-3], 'LC_MESSAGES')
248 246 mofile = join(modir, 'hg.mo')
249 247 mobuildfile = join('mercurial', mofile)
250 248 cmd = ['msgfmt', '-v', '-o', mobuildfile, pofile]
251 249 if sys.platform != 'sunos5':
252 250 # msgfmt on Solaris does not know about -c
253 251 cmd.append('-c')
254 252 self.mkpath(join('mercurial', modir))
255 253 self.make_file([pofile], mobuildfile, spawn, (cmd,))
256 254
257 255
258 256 class hgdist(Distribution):
259 257 pure = ispypy
260 258
261 259 global_options = Distribution.global_options + \
262 260 [('pure', None, "use pure (slow) Python "
263 261 "code instead of C extensions"),
264 262 ]
265 263
266 264 def has_ext_modules(self):
267 265 # self.ext_modules is emptied in hgbuildpy.finalize_options which is
268 266 # too late for some cases
269 267 return not self.pure and Distribution.has_ext_modules(self)
270 268
271 269 class hgbuildext(build_ext):
272 270
273 271 def build_extension(self, ext):
274 272 try:
275 273 build_ext.build_extension(self, ext)
276 274 except CCompilerError:
277 275 if not getattr(ext, 'optional', False):
278 276 raise
279 277 log.warn("Failed to build optional extension '%s' (skipping)",
280 278 ext.name)
281 279
282 280 class hgbuildscripts(build_scripts):
283 281 def run(self):
284 282 if os.name != 'nt' or self.distribution.pure:
285 283 return build_scripts.run(self)
286 284
287 285 exebuilt = False
288 286 try:
289 287 self.run_command('build_hgexe')
290 288 exebuilt = True
291 289 except (DistutilsError, CCompilerError):
292 290 log.warn('failed to build optional hg.exe')
293 291
294 292 if exebuilt:
295 293 # Copying hg.exe to the scripts build directory ensures it is
296 294 # installed by the install_scripts command.
297 295 hgexecommand = self.get_finalized_command('build_hgexe')
298 296 dest = os.path.join(self.build_dir, 'hg.exe')
299 297 self.mkpath(self.build_dir)
300 298 self.copy_file(hgexecommand.hgexepath, dest)
301 299
302 300 # Remove hg.bat because it is redundant with hg.exe.
303 301 self.scripts.remove('contrib/win32/hg.bat')
304 302
305 303 return build_scripts.run(self)
306 304
307 305 class hgbuildpy(build_py):
308 306 def finalize_options(self):
309 307 build_py.finalize_options(self)
310 308
311 309 if self.distribution.pure:
312 310 self.distribution.ext_modules = []
313 311 else:
314 312 h = os.path.join(get_python_inc(), 'Python.h')
315 313 if not os.path.exists(h):
316 314 raise SystemExit('Python headers are required to build '
317 315 'Mercurial but weren\'t found in %s' % h)
318 316
319 317 def copy_file(self, *args, **kwargs):
320 318 dst, copied = build_py.copy_file(self, *args, **kwargs)
321 319
322 320 if copied and dst.endswith('__init__.py'):
323 321 if self.distribution.pure:
324 322 modulepolicy = 'py'
325 323 else:
326 324 modulepolicy = 'c'
327 325 content = open(dst, 'rb').read()
328 326 content = content.replace(b'@MODULELOADPOLICY@',
329 327 modulepolicy.encode(libdir_escape))
330 328 with open(dst, 'wb') as fh:
331 329 fh.write(content)
332 330
333 331 return dst, copied
334 332
335 333 class buildhgextindex(Command):
336 334 description = 'generate prebuilt index of hgext (for frozen package)'
337 335 user_options = []
338 336 _indexfilename = 'hgext/__index__.py'
339 337
340 338 def initialize_options(self):
341 339 pass
342 340
343 341 def finalize_options(self):
344 342 pass
345 343
346 344 def run(self):
347 345 if os.path.exists(self._indexfilename):
348 f = open(self._indexfilename, 'w')
349 f.write('# empty\n')
350 f.close()
346 with open(self._indexfilename, 'w') as f:
347 f.write('# empty\n')
351 348
352 349 # here no extension enabled, disabled() lists up everything
353 350 code = ('import pprint; from mercurial import extensions; '
354 351 'pprint.pprint(extensions.disabled())')
355 352 out, err = runcmd([sys.executable, '-c', code], env)
356 353 if err:
357 354 raise DistutilsExecError(err)
358 355
359 f = open(self._indexfilename, 'w')
360 f.write('# this file is autogenerated by setup.py\n')
361 f.write('docs = ')
362 f.write(out)
363 f.close()
356 with open(self._indexfilename, 'w') as f:
357 f.write('# this file is autogenerated by setup.py\n')
358 f.write('docs = ')
359 f.write(out)
364 360
365 361 class buildhgexe(build_ext):
366 362 description = 'compile hg.exe from mercurial/exewrapper.c'
367 363
368 364 def build_extensions(self):
369 365 if os.name != 'nt':
370 366 return
371 367 if isinstance(self.compiler, HackedMingw32CCompiler):
372 368 self.compiler.compiler_so = self.compiler.compiler # no -mdll
373 369 self.compiler.dll_libraries = [] # no -lmsrvc90
374 370 hv = sys.hexversion
375 371 pythonlib = 'python%d%d' % (hv >> 24, (hv >> 16) & 0xff)
376 f = open('mercurial/hgpythonlib.h', 'wb')
377 f.write('/* this file is autogenerated by setup.py */\n')
378 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
379 f.close()
372 with open('mercurial/hgpythonlib.h', 'wb') as f:
373 f.write('/* this file is autogenerated by setup.py */\n')
374 f.write('#define HGPYTHONLIB "%s"\n' % pythonlib)
380 375 objects = self.compiler.compile(['mercurial/exewrapper.c'],
381 376 output_dir=self.build_temp)
382 377 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
383 378 target = os.path.join(dir, 'hg')
384 379 self.compiler.link_executable(objects, target,
385 380 libraries=[],
386 381 output_dir=self.build_temp)
387 382
388 383 @property
389 384 def hgexepath(self):
390 385 dir = os.path.dirname(self.get_ext_fullpath('dummy'))
391 386 return os.path.join(self.build_temp, dir, 'hg.exe')
392 387
393 388 class hginstalllib(install_lib):
394 389 '''
395 390 This is a specialization of install_lib that replaces the copy_file used
396 391 there so that it supports setting the mode of files after copying them,
397 392 instead of just preserving the mode that the files originally had. If your
398 393 system has a umask of something like 027, preserving the permissions when
399 394 copying will lead to a broken install.
400 395
401 396 Note that just passing keep_permissions=False to copy_file would be
402 397 insufficient, as it might still be applying a umask.
403 398 '''
404 399
405 400 def run(self):
406 401 realcopyfile = file_util.copy_file
407 402 def copyfileandsetmode(*args, **kwargs):
408 403 src, dst = args[0], args[1]
409 404 dst, copied = realcopyfile(*args, **kwargs)
410 405 if copied:
411 406 st = os.stat(src)
412 407 # Persist executable bit (apply it to group and other if user
413 408 # has it)
414 409 if st[stat.ST_MODE] & stat.S_IXUSR:
415 410 setmode = int('0755', 8)
416 411 else:
417 412 setmode = int('0644', 8)
418 413 m = stat.S_IMODE(st[stat.ST_MODE])
419 414 m = (m & ~int('0777', 8)) | setmode
420 415 os.chmod(dst, m)
421 416 file_util.copy_file = copyfileandsetmode
422 417 try:
423 418 install_lib.run(self)
424 419 finally:
425 420 file_util.copy_file = realcopyfile
426 421
427 422 class hginstallscripts(install_scripts):
428 423 '''
429 424 This is a specialization of install_scripts that replaces the @LIBDIR@ with
430 425 the configured directory for modules. If possible, the path is made relative
431 426 to the directory for scripts.
432 427 '''
433 428
434 429 def initialize_options(self):
435 430 install_scripts.initialize_options(self)
436 431
437 432 self.install_lib = None
438 433
439 434 def finalize_options(self):
440 435 install_scripts.finalize_options(self)
441 436 self.set_undefined_options('install',
442 437 ('install_lib', 'install_lib'))
443 438
444 439 def run(self):
445 440 install_scripts.run(self)
446 441
447 442 # It only makes sense to replace @LIBDIR@ with the install path if
448 443 # the install path is known. For wheels, the logic below calculates
449 444 # the libdir to be "../..". This is because the internal layout of a
450 445 # wheel archive looks like:
451 446 #
452 447 # mercurial-3.6.1.data/scripts/hg
453 448 # mercurial/__init__.py
454 449 #
455 450 # When installing wheels, the subdirectories of the "<pkg>.data"
456 451 # directory are translated to system local paths and files therein
457 452 # are copied in place. The mercurial/* files are installed into the
458 453 # site-packages directory. However, the site-packages directory
459 454 # isn't known until wheel install time. This means we have no clue
460 455 # at wheel generation time what the installed site-packages directory
461 456 # will be. And, wheels don't appear to provide the ability to register
462 457 # custom code to run during wheel installation. This all means that
463 458 # we can't reliably set the libdir in wheels: the default behavior
464 459 # of looking in sys.path must do.
465 460
466 461 if (os.path.splitdrive(self.install_dir)[0] !=
467 462 os.path.splitdrive(self.install_lib)[0]):
468 463 # can't make relative paths from one drive to another, so use an
469 464 # absolute path instead
470 465 libdir = self.install_lib
471 466 else:
472 467 common = os.path.commonprefix((self.install_dir, self.install_lib))
473 468 rest = self.install_dir[len(common):]
474 469 uplevel = len([n for n in os.path.split(rest) if n])
475 470
476 471 libdir = uplevel * ('..' + os.sep) + self.install_lib[len(common):]
477 472
478 473 for outfile in self.outfiles:
479 fp = open(outfile, 'rb')
480 data = fp.read()
481 fp.close()
474 with open(outfile, 'rb') as fp:
475 data = fp.read()
482 476
483 477 # skip binary files
484 478 if b'\0' in data:
485 479 continue
486 480
487 481 # During local installs, the shebang will be rewritten to the final
488 482 # install path. During wheel packaging, the shebang has a special
489 483 # value.
490 484 if data.startswith(b'#!python'):
491 485 log.info('not rewriting @LIBDIR@ in %s because install path '
492 486 'not known' % outfile)
493 487 continue
494 488
495 489 data = data.replace(b'@LIBDIR@', libdir.encode(libdir_escape))
496 fp = open(outfile, 'wb')
497 fp.write(data)
498 fp.close()
490 with open(outfile, 'wb') as fp:
491 fp.write(data)
499 492
500 493 cmdclass = {'build': hgbuild,
501 494 'build_mo': hgbuildmo,
502 495 'build_ext': hgbuildext,
503 496 'build_py': hgbuildpy,
504 497 'build_scripts': hgbuildscripts,
505 498 'build_hgextindex': buildhgextindex,
506 499 'install_lib': hginstalllib,
507 500 'install_scripts': hginstallscripts,
508 501 'build_hgexe': buildhgexe,
509 502 }
510 503
511 504 packages = ['mercurial', 'mercurial.hgweb', 'mercurial.httpclient',
512 505 'mercurial.pure',
513 506 'hgext', 'hgext.convert', 'hgext.highlight', 'hgext.zeroconf',
514 507 'hgext.largefiles']
515 508
516 509 common_depends = ['mercurial/util.h']
517 510
518 511 osutil_ldflags = []
519 512
520 513 if sys.platform == 'darwin':
521 514 osutil_ldflags += ['-framework', 'ApplicationServices']
522 515
523 516 extmodules = [
524 517 Extension('mercurial.base85', ['mercurial/base85.c'],
525 518 depends=common_depends),
526 519 Extension('mercurial.bdiff', ['mercurial/bdiff.c'],
527 520 depends=common_depends),
528 521 Extension('mercurial.diffhelpers', ['mercurial/diffhelpers.c'],
529 522 depends=common_depends),
530 523 Extension('mercurial.mpatch', ['mercurial/mpatch.c'],
531 524 depends=common_depends),
532 525 Extension('mercurial.parsers', ['mercurial/dirs.c',
533 526 'mercurial/manifest.c',
534 527 'mercurial/parsers.c',
535 528 'mercurial/pathencode.c'],
536 529 depends=common_depends),
537 530 Extension('mercurial.osutil', ['mercurial/osutil.c'],
538 531 extra_link_args=osutil_ldflags,
539 532 depends=common_depends),
540 533 ]
541 534
542 535 try:
543 536 from distutils import cygwinccompiler
544 537
545 538 # the -mno-cygwin option has been deprecated for years
546 539 compiler = cygwinccompiler.Mingw32CCompiler
547 540
548 541 class HackedMingw32CCompiler(cygwinccompiler.Mingw32CCompiler):
549 542 def __init__(self, *args, **kwargs):
550 543 compiler.__init__(self, *args, **kwargs)
551 544 for i in 'compiler compiler_so linker_exe linker_so'.split():
552 545 try:
553 546 getattr(self, i).remove('-mno-cygwin')
554 547 except ValueError:
555 548 pass
556 549
557 550 cygwinccompiler.Mingw32CCompiler = HackedMingw32CCompiler
558 551 except ImportError:
559 552 # the cygwinccompiler package is not available on some Python
560 553 # distributions like the ones from the optware project for Synology
561 554 # DiskStation boxes
562 555 class HackedMingw32CCompiler(object):
563 556 pass
564 557
565 558 packagedata = {'mercurial': ['locale/*/LC_MESSAGES/hg.mo',
566 559 'help/*.txt',
567 560 'help/internals/*.txt',
568 561 'default.d/*.rc',
569 562 'dummycert.pem']}
570 563
571 564 def ordinarypath(p):
572 565 return p and p[0] != '.' and p[-1] != '~'
573 566
574 567 for root in ('templates',):
575 568 for curdir, dirs, files in os.walk(os.path.join('mercurial', root)):
576 569 curdir = curdir.split(os.sep, 1)[1]
577 570 dirs[:] = filter(ordinarypath, dirs)
578 571 for f in filter(ordinarypath, files):
579 572 f = os.path.join(curdir, f)
580 573 packagedata['mercurial'].append(f)
581 574
582 575 datafiles = []
583 576 setupversion = version
584 577 extra = {}
585 578
586 579 if py2exeloaded:
587 580 extra['console'] = [
588 581 {'script':'hg',
589 582 'copyright':'Copyright (C) 2005-2016 Matt Mackall and others',
590 583 'product_version':version}]
591 584 # sub command of 'build' because 'py2exe' does not handle sub_commands
592 585 build.sub_commands.insert(0, ('build_hgextindex', None))
593 586 # put dlls in sub directory so that they won't pollute PATH
594 587 extra['zipfile'] = 'lib/library.zip'
595 588
596 589 if os.name == 'nt':
597 590 # Windows binary file versions for exe/dll files must have the
598 591 # form W.X.Y.Z, where W,X,Y,Z are numbers in the range 0..65535
599 592 setupversion = version.split('+', 1)[0]
600 593
601 594 if sys.platform == 'darwin' and os.path.exists('/usr/bin/xcodebuild'):
602 595 version = runcmd(['/usr/bin/xcodebuild', '-version'], {})[0].splitlines()
603 596 if version:
604 597 version = version[0]
605 598 if sys.version_info[0] == 3:
606 599 version = version.decode('utf-8')
607 600 xcode4 = (version.startswith('Xcode') and
608 601 StrictVersion(version.split()[1]) >= StrictVersion('4.0'))
609 602 xcode51 = re.match(r'^Xcode\s+5\.1', version) is not None
610 603 else:
611 604 # xcodebuild returns empty on OS X Lion with XCode 4.3 not
612 605 # installed, but instead with only command-line tools. Assume
613 606 # that only happens on >= Lion, thus no PPC support.
614 607 xcode4 = True
615 608 xcode51 = False
616 609
617 610 # XCode 4.0 dropped support for ppc architecture, which is hardcoded in
618 611 # distutils.sysconfig
619 612 if xcode4:
620 613 os.environ['ARCHFLAGS'] = ''
621 614
622 615 # XCode 5.1 changes clang such that it now fails to compile if the
623 616 # -mno-fused-madd flag is passed, but the version of Python shipped with
624 617 # OS X 10.9 Mavericks includes this flag. This causes problems in all
625 618 # C extension modules, and a bug has been filed upstream at
626 619 # http://bugs.python.org/issue21244. We also need to patch this here
627 620 # so Mercurial can continue to compile in the meantime.
628 621 if xcode51:
629 622 cflags = get_config_var('CFLAGS')
630 623 if cflags and re.search(r'-mno-fused-madd\b', cflags) is not None:
631 624 os.environ['CFLAGS'] = (
632 625 os.environ.get('CFLAGS', '') + ' -Qunused-arguments')
633 626
634 627 setup(name='mercurial',
635 628 version=setupversion,
636 629 author='Matt Mackall and many others',
637 630 author_email='mercurial@selenic.com',
638 631 url='https://mercurial-scm.org/',
639 632 download_url='https://mercurial-scm.org/release/',
640 633 description=('Fast scalable distributed SCM (revision control, version '
641 634 'control) system'),
642 635 long_description=('Mercurial is a distributed SCM tool written in Python.'
643 636 ' It is used by a number of large projects that require'
644 637 ' fast, reliable distributed revision control, such as '
645 638 'Mozilla.'),
646 639 license='GNU GPLv2 or any later version',
647 640 classifiers=[
648 641 'Development Status :: 6 - Mature',
649 642 'Environment :: Console',
650 643 'Intended Audience :: Developers',
651 644 'Intended Audience :: System Administrators',
652 645 'License :: OSI Approved :: GNU General Public License (GPL)',
653 646 'Natural Language :: Danish',
654 647 'Natural Language :: English',
655 648 'Natural Language :: German',
656 649 'Natural Language :: Italian',
657 650 'Natural Language :: Japanese',
658 651 'Natural Language :: Portuguese (Brazilian)',
659 652 'Operating System :: Microsoft :: Windows',
660 653 'Operating System :: OS Independent',
661 654 'Operating System :: POSIX',
662 655 'Programming Language :: C',
663 656 'Programming Language :: Python',
664 657 'Topic :: Software Development :: Version Control',
665 658 ],
666 659 scripts=scripts,
667 660 packages=packages,
668 661 ext_modules=extmodules,
669 662 data_files=datafiles,
670 663 package_data=packagedata,
671 664 cmdclass=cmdclass,
672 665 distclass=hgdist,
673 666 options={'py2exe': {'packages': ['hgext', 'email']},
674 667 'bdist_mpkg': {'zipdist': False,
675 668 'license': 'COPYING',
676 669 'readme': 'contrib/macosx/Readme.html',
677 670 'welcome': 'contrib/macosx/Welcome.html',
678 671 },
679 672 },
680 673 **extra)
General Comments 0
You need to be logged in to leave comments. Login now