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