setup.py
branchstable
changeset 44729 26ce8e751503
parent 44692 539490756a72
parent 44661 e147748f750b
child 44742 380959c6f75e
equal deleted inserted replaced
44692:539490756a72 44729:26ce8e751503
     1 #
     1 #
     2 # This is the mercurial setup script.
     2 # This is the mercurial setup script.
     3 #
     3 #
     4 # 'python setup.py install', or
     4 # 'python setup.py install', or
     5 # 'python setup.py --help' for more options
     5 # 'python setup.py --help' for more options
     6 
       
     7 import os
     6 import os
     8 
     7 
     9 # Mercurial will never work on Python 3 before 3.5 due to a lack
     8 # Mercurial will never work on Python 3 before 3.5 due to a lack
    10 # of % formatting on bytestrings, and can't work on 3.6.0 or 3.6.1
     9 # of % formatting on bytestrings, and can't work on 3.6.0 or 3.6.1
    11 # due to a bug in % formatting in bytestrings.
    10 # due to a bug in % formatting in bytestrings.
   134         raise SystemExit(
   133         raise SystemExit(
   135             "Couldn't import standard bz2 (incomplete Python install)."
   134             "Couldn't import standard bz2 (incomplete Python install)."
   136         )
   135         )
   137 
   136 
   138 ispypy = "PyPy" in sys.version
   137 ispypy = "PyPy" in sys.version
   139 
       
   140 hgrustext = os.environ.get('HGWITHRUSTEXT')
       
   141 # TODO record it for proper rebuild upon changes
       
   142 # (see mercurial/__modulepolicy__.py)
       
   143 if hgrustext != 'cpython' and hgrustext is not None:
       
   144     hgrustext = 'direct-ffi'
       
   145 
   138 
   146 import ctypes
   139 import ctypes
   147 import errno
   140 import errno
   148 import stat, subprocess, time
   141 import stat, subprocess, time
   149 import re
   142 import re
   321     # Run a simple "hg log" command just to see if using hg from the user's
   314     # Run a simple "hg log" command just to see if using hg from the user's
   322     # path works and can successfully interact with this repository.  Windows
   315     # path works and can successfully interact with this repository.  Windows
   323     # gives precedence to hg.exe in the current directory, so fall back to the
   316     # gives precedence to hg.exe in the current directory, so fall back to the
   324     # python invocation of local hg, where pythonXY.dll can always be found.
   317     # python invocation of local hg, where pythonXY.dll can always be found.
   325     check_cmd = ['log', '-r.', '-Ttest']
   318     check_cmd = ['log', '-r.', '-Ttest']
   326     if os.name != 'nt':
   319     if os.name != 'nt' or not os.path.exists("hg.exe"):
   327         try:
   320         try:
   328             retcode, out, err = runcmd(hgcmd + check_cmd, hgenv)
   321             retcode, out, err = runcmd(hgcmd + check_cmd, hgenv)
   329         except EnvironmentError:
   322         except EnvironmentError:
   330             retcode = -1
   323             retcode = -1
   331         if retcode == 0 and not filterhgerr(err):
   324         if retcode == 0 and not filterhgerr(err):
   475             self.make_file([pofile], mobuildfile, spawn, (cmd,))
   468             self.make_file([pofile], mobuildfile, spawn, (cmd,))
   476 
   469 
   477 
   470 
   478 class hgdist(Distribution):
   471 class hgdist(Distribution):
   479     pure = False
   472     pure = False
   480     rust = hgrustext is not None
   473     rust = False
       
   474     no_rust = False
   481     cffi = ispypy
   475     cffi = ispypy
   482 
   476 
   483     global_options = Distribution.global_options + [
   477     global_options = Distribution.global_options + [
   484         ('pure', None, "use pure (slow) Python code instead of C extensions"),
   478         ('pure', None, "use pure (slow) Python code instead of C extensions"),
   485         ('rust', None, "use Rust extensions additionally to C extensions"),
   479         ('rust', None, "use Rust extensions additionally to C extensions"),
       
   480         (
       
   481             'no-rust',
       
   482             None,
       
   483             "do not use Rust extensions additionally to C extensions",
       
   484         ),
   486     ]
   485     ]
       
   486 
       
   487     negative_opt = Distribution.negative_opt.copy()
       
   488     boolean_options = ['pure', 'rust', 'no-rust']
       
   489     negative_opt['no-rust'] = 'rust'
       
   490 
       
   491     def _set_command_options(self, command_obj, option_dict=None):
       
   492         # Not all distutils versions in the wild have boolean_options.
       
   493         # This should be cleaned up when we're Python 3 only.
       
   494         command_obj.boolean_options = (
       
   495             getattr(command_obj, 'boolean_options', []) + self.boolean_options
       
   496         )
       
   497         return Distribution._set_command_options(
       
   498             self, command_obj, option_dict=option_dict
       
   499         )
       
   500 
       
   501     def parse_command_line(self):
       
   502         ret = Distribution.parse_command_line(self)
       
   503         if not (self.rust or self.no_rust):
       
   504             hgrustext = os.environ.get('HGWITHRUSTEXT')
       
   505             # TODO record it for proper rebuild upon changes
       
   506             # (see mercurial/__modulepolicy__.py)
       
   507             if hgrustext != 'cpython' and hgrustext is not None:
       
   508                 if hgrustext:
       
   509                     msg = 'unkown HGWITHRUSTEXT value: %s' % hgrustext
       
   510                     printf(msg, file=sys.stderr)
       
   511                 hgrustext = None
       
   512             self.rust = hgrustext is not None
       
   513             self.no_rust = not self.rust
       
   514         return ret
   487 
   515 
   488     def has_ext_modules(self):
   516     def has_ext_modules(self):
   489         # self.ext_modules is emptied in hgbuildpy.finalize_options which is
   517         # self.ext_modules is emptied in hgbuildpy.finalize_options which is
   490         # too late for some cases
   518         # too late for some cases
   491         return not self.pure and Distribution.has_ext_modules(self)
   519         return not self.pure and Distribution.has_ext_modules(self)
   541             ]
   569             ]
   542 
   570 
   543         # Build Rust standalon extensions if it'll be used
   571         # Build Rust standalon extensions if it'll be used
   544         # and its build is not explictely disabled (for external build
   572         # and its build is not explictely disabled (for external build
   545         # as Linux distributions would do)
   573         # as Linux distributions would do)
   546         if self.distribution.rust and self.rust and hgrustext != 'direct-ffi':
   574         if self.distribution.rust and self.rust:
   547             for rustext in ruststandalones:
   575             for rustext in ruststandalones:
   548                 rustext.build('' if self.inplace else self.build_lib)
   576                 rustext.build('' if self.inplace else self.build_lib)
   549 
   577 
   550         return build_ext.build_extensions(self)
   578         return build_ext.build_extensions(self)
   551 
   579 
   933                 )
   961                 )
   934 
   962 
   935             normalizecrlf('doc/%s.html' % root)
   963             normalizecrlf('doc/%s.html' % root)
   936 
   964 
   937         # This logic is duplicated in doc/Makefile.
   965         # This logic is duplicated in doc/Makefile.
   938         sources = set(
   966         sources = {
   939             f
   967             f
   940             for f in os.listdir('mercurial/helptext')
   968             for f in os.listdir('mercurial/helptext')
   941             if re.search(r'[0-9]\.txt$', f)
   969             if re.search(r'[0-9]\.txt$', f)
   942         )
   970         }
   943 
   971 
   944         # common.txt is a one-off.
   972         # common.txt is a one-off.
   945         gentxt('common')
   973         gentxt('common')
   946 
   974 
   947         for source in sorted(sources):
   975         for source in sorted(sources):
   977 
  1005 
   978     def get_sub_commands(self):
  1006     def get_sub_commands(self):
   979         # Screen out egg related commands to prevent egg generation.  But allow
  1007         # Screen out egg related commands to prevent egg generation.  But allow
   980         # mercurial.egg-info generation, since that is part of modern
  1008         # mercurial.egg-info generation, since that is part of modern
   981         # packaging.
  1009         # packaging.
   982         excl = set(['bdist_egg'])
  1010         excl = {'bdist_egg'}
   983         return filter(lambda x: x not in excl, install.get_sub_commands(self))
  1011         return filter(lambda x: x not in excl, install.get_sub_commands(self))
   984 
  1012 
   985 
  1013 
   986 class hginstalllib(install_lib):
  1014 class hginstalllib(install_lib):
   987     '''
  1015     '''
  1209     'hgext',
  1237     'hgext',
  1210     'hgext.convert',
  1238     'hgext.convert',
  1211     'hgext.fsmonitor',
  1239     'hgext.fsmonitor',
  1212     'hgext.fastannotate',
  1240     'hgext.fastannotate',
  1213     'hgext.fsmonitor.pywatchman',
  1241     'hgext.fsmonitor.pywatchman',
       
  1242     'hgext.git',
  1214     'hgext.highlight',
  1243     'hgext.highlight',
       
  1244     'hgext.hooklib',
  1215     'hgext.infinitepush',
  1245     'hgext.infinitepush',
  1216     'hgext.largefiles',
  1246     'hgext.largefiles',
  1217     'hgext.lfs',
  1247     'hgext.lfs',
  1218     'hgext.narrow',
  1248     'hgext.narrow',
  1219     'hgext.remotefilelog',
  1249     'hgext.remotefilelog',
  1239     'mercurial/bitmanipulation.h',
  1269     'mercurial/bitmanipulation.h',
  1240     'mercurial/compat.h',
  1270     'mercurial/compat.h',
  1241     'mercurial/cext/util.h',
  1271     'mercurial/cext/util.h',
  1242 ]
  1272 ]
  1243 common_include_dirs = ['mercurial']
  1273 common_include_dirs = ['mercurial']
       
  1274 
       
  1275 common_cflags = []
       
  1276 
       
  1277 # MSVC 2008 still needs declarations at the top of the scope, but Python 3.9
       
  1278 # makes declarations not at the top of a scope in the headers.
       
  1279 if os.name != 'nt' and sys.version_info[1] < 9:
       
  1280     common_cflags = ['-Werror=declaration-after-statement']
  1244 
  1281 
  1245 osutil_cflags = []
  1282 osutil_cflags = []
  1246 osutil_ldflags = []
  1283 osutil_ldflags = []
  1247 
  1284 
  1248 # platform specific macros
  1285 # platform specific macros
  1354             import pwd
  1391             import pwd
  1355 
  1392 
  1356             env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
  1393             env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
  1357 
  1394 
  1358         cargocmd = ['cargo', 'rustc', '-vv', '--release']
  1395         cargocmd = ['cargo', 'rustc', '-vv', '--release']
       
  1396 
       
  1397         feature_flags = []
       
  1398 
  1359         if sys.version_info[0] == 3 and self.py3_features is not None:
  1399         if sys.version_info[0] == 3 and self.py3_features is not None:
  1360             cargocmd.extend(
  1400             feature_flags.append(self.py3_features)
  1361                 ('--features', self.py3_features, '--no-default-features')
  1401             cargocmd.append('--no-default-features')
  1362             )
  1402 
       
  1403         rust_features = env.get("HG_RUST_FEATURES")
       
  1404         if rust_features:
       
  1405             feature_flags.append(rust_features)
       
  1406 
       
  1407         cargocmd.extend(('--features', " ".join(feature_flags)))
       
  1408 
  1363         cargocmd.append('--')
  1409         cargocmd.append('--')
  1364         if sys.platform == 'darwin':
  1410         if sys.platform == 'darwin':
  1365             cargocmd.extend(
  1411             cargocmd.extend(
  1366                 ("-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup")
  1412                 ("-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup")
  1367             )
  1413             )
  1382                 "command: %r, environment: %r"
  1428                 "command: %r, environment: %r"
  1383                 % (self.rustsrcdir, cargocmd, env)
  1429                 % (self.rustsrcdir, cargocmd, env)
  1384             )
  1430             )
  1385 
  1431 
  1386 
  1432 
  1387 class RustEnhancedExtension(RustExtension):
       
  1388     """A C Extension, conditionally enhanced with Rust code.
       
  1389 
       
  1390     If the HGWITHRUSTEXT environment variable is set to something else
       
  1391     than 'cpython', the Rust sources get compiled and linked within
       
  1392     the C target shared library object.
       
  1393     """
       
  1394 
       
  1395     def __init__(self, mpath, sources, rustlibname, subcrate, **kw):
       
  1396         RustExtension.__init__(
       
  1397             self, mpath, sources, rustlibname, subcrate, **kw
       
  1398         )
       
  1399         if hgrustext != 'direct-ffi':
       
  1400             return
       
  1401         self.extra_compile_args.append('-DWITH_RUST')
       
  1402         self.libraries.append(rustlibname)
       
  1403         self.library_dirs.append(self.rusttargetdir)
       
  1404 
       
  1405     def rustbuild(self):
       
  1406         if hgrustext == 'direct-ffi':
       
  1407             RustExtension.rustbuild(self)
       
  1408 
       
  1409 
       
  1410 class RustStandaloneExtension(RustExtension):
  1433 class RustStandaloneExtension(RustExtension):
  1411     def __init__(self, pydottedname, rustcrate, dylibname, **kw):
  1434     def __init__(self, pydottedname, rustcrate, dylibname, **kw):
  1412         RustExtension.__init__(
  1435         RustExtension.__init__(
  1413             self, pydottedname, [], dylibname, rustcrate, **kw
  1436             self, pydottedname, [], dylibname, rustcrate, **kw
  1414         )
  1437         )
  1430 extmodules = [
  1453 extmodules = [
  1431     Extension(
  1454     Extension(
  1432         'mercurial.cext.base85',
  1455         'mercurial.cext.base85',
  1433         ['mercurial/cext/base85.c'],
  1456         ['mercurial/cext/base85.c'],
  1434         include_dirs=common_include_dirs,
  1457         include_dirs=common_include_dirs,
       
  1458         extra_compile_args=common_cflags,
  1435         depends=common_depends,
  1459         depends=common_depends,
  1436     ),
  1460     ),
  1437     Extension(
  1461     Extension(
  1438         'mercurial.cext.bdiff',
  1462         'mercurial.cext.bdiff',
  1439         ['mercurial/bdiff.c', 'mercurial/cext/bdiff.c'] + xdiff_srcs,
  1463         ['mercurial/bdiff.c', 'mercurial/cext/bdiff.c'] + xdiff_srcs,
  1440         include_dirs=common_include_dirs,
  1464         include_dirs=common_include_dirs,
       
  1465         extra_compile_args=common_cflags,
  1441         depends=common_depends + ['mercurial/bdiff.h'] + xdiff_headers,
  1466         depends=common_depends + ['mercurial/bdiff.h'] + xdiff_headers,
  1442     ),
  1467     ),
  1443     Extension(
  1468     Extension(
  1444         'mercurial.cext.mpatch',
  1469         'mercurial.cext.mpatch',
  1445         ['mercurial/mpatch.c', 'mercurial/cext/mpatch.c'],
  1470         ['mercurial/mpatch.c', 'mercurial/cext/mpatch.c'],
  1446         include_dirs=common_include_dirs,
  1471         include_dirs=common_include_dirs,
       
  1472         extra_compile_args=common_cflags,
  1447         depends=common_depends,
  1473         depends=common_depends,
  1448     ),
  1474     ),
  1449     RustEnhancedExtension(
  1475     Extension(
  1450         'mercurial.cext.parsers',
  1476         'mercurial.cext.parsers',
  1451         [
  1477         [
  1452             'mercurial/cext/charencode.c',
  1478             'mercurial/cext/charencode.c',
  1453             'mercurial/cext/dirs.c',
  1479             'mercurial/cext/dirs.c',
  1454             'mercurial/cext/manifest.c',
  1480             'mercurial/cext/manifest.c',
  1455             'mercurial/cext/parsers.c',
  1481             'mercurial/cext/parsers.c',
  1456             'mercurial/cext/pathencode.c',
  1482             'mercurial/cext/pathencode.c',
  1457             'mercurial/cext/revlog.c',
  1483             'mercurial/cext/revlog.c',
  1458         ],
  1484         ],
  1459         'hgdirectffi',
       
  1460         'hg-direct-ffi',
       
  1461         include_dirs=common_include_dirs,
  1485         include_dirs=common_include_dirs,
       
  1486         extra_compile_args=common_cflags,
  1462         depends=common_depends
  1487         depends=common_depends
  1463         + [
  1488         + ['mercurial/cext/charencode.h', 'mercurial/cext/revlog.h',],
  1464             'mercurial/cext/charencode.h',
       
  1465             'mercurial/cext/revlog.h',
       
  1466             'rust/hg-core/src/ancestors.rs',
       
  1467             'rust/hg-core/src/lib.rs',
       
  1468         ],
       
  1469     ),
  1489     ),
  1470     Extension(
  1490     Extension(
  1471         'mercurial.cext.osutil',
  1491         'mercurial.cext.osutil',
  1472         ['mercurial/cext/osutil.c'],
  1492         ['mercurial/cext/osutil.c'],
  1473         include_dirs=common_include_dirs,
  1493         include_dirs=common_include_dirs,
  1474         extra_compile_args=osutil_cflags,
  1494         extra_compile_args=common_cflags + osutil_cflags,
  1475         extra_link_args=osutil_ldflags,
  1495         extra_link_args=osutil_ldflags,
  1476         depends=common_depends,
  1496         depends=common_depends,
  1477     ),
  1497     ),
  1478     Extension(
  1498     Extension(
  1479         'mercurial.thirdparty.zope.interface._zope_interface_coptimizations',
  1499         'mercurial.thirdparty.zope.interface._zope_interface_coptimizations',
  1480         [
  1500         [
  1481             'mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c',
  1501             'mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c',
  1482         ],
  1502         ],
       
  1503         extra_compile_args=common_cflags,
  1483     ),
  1504     ),
  1484     Extension(
  1505     Extension(
  1485         'mercurial.thirdparty.sha1dc',
  1506         'mercurial.thirdparty.sha1dc',
  1486         [
  1507         [
  1487             'mercurial/thirdparty/sha1dc/cext.c',
  1508             'mercurial/thirdparty/sha1dc/cext.c',
  1488             'mercurial/thirdparty/sha1dc/lib/sha1.c',
  1509             'mercurial/thirdparty/sha1dc/lib/sha1.c',
  1489             'mercurial/thirdparty/sha1dc/lib/ubc_check.c',
  1510             'mercurial/thirdparty/sha1dc/lib/ubc_check.c',
  1490         ],
  1511         ],
       
  1512         extra_compile_args=common_cflags,
  1491     ),
  1513     ),
  1492     Extension(
  1514     Extension(
  1493         'hgext.fsmonitor.pywatchman.bser', ['hgext/fsmonitor/pywatchman/bser.c']
  1515         'hgext.fsmonitor.pywatchman.bser',
       
  1516         ['hgext/fsmonitor/pywatchman/bser.c'],
       
  1517         extra_compile_args=common_cflags,
  1494     ),
  1518     ),
  1495     RustStandaloneExtension(
  1519     RustStandaloneExtension(
  1496         'mercurial.rustext', 'hg-cpython', 'librusthg', py3_features='python3'
  1520         'mercurial.rustext', 'hg-cpython', 'librusthg', py3_features='python3'
  1497     ),
  1521     ),
  1498 ]
  1522 ]
  1499 
  1523 
  1500 
  1524 
  1501 sys.path.insert(0, 'contrib/python-zstandard')
  1525 sys.path.insert(0, 'contrib/python-zstandard')
  1502 import setup_zstd
  1526 import setup_zstd
  1503 
  1527 
  1504 extmodules.append(
  1528 zstd = setup_zstd.get_c_extension(
  1505     setup_zstd.get_c_extension(
  1529     name='mercurial.zstd', root=os.path.abspath(os.path.dirname(__file__))
  1506         name='mercurial.zstd', root=os.path.abspath(os.path.dirname(__file__))
       
  1507     )
       
  1508 )
  1530 )
       
  1531 zstd.extra_compile_args += common_cflags
       
  1532 extmodules.append(zstd)
  1509 
  1533 
  1510 try:
  1534 try:
  1511     from distutils import cygwinccompiler
  1535     from distutils import cygwinccompiler
  1512 
  1536 
  1513     # the -mno-cygwin option has been deprecated for years
  1537     # the -mno-cygwin option has been deprecated for years