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