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