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