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