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