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