comparison setup.py @ 41290:593718ff5844 stable 4.9rc0

merge default into stable for 4.9 release
author Augie Fackler <augie@google.com>
date Fri, 18 Jan 2019 13:28:22 -0500
parents 98ce494e104d
children 8427fea04017
comparison
equal deleted inserted replaced
40482:fbd168455b26 41290:593718ff5844
130 raise SystemExit( 130 raise SystemExit(
131 "Couldn't import standard bz2 (incomplete Python install).") 131 "Couldn't import standard bz2 (incomplete Python install).")
132 132
133 ispypy = "PyPy" in sys.version 133 ispypy = "PyPy" in sys.version
134 134
135 iswithrustextensions = 'HGWITHRUSTEXT' in os.environ 135 hgrustext = os.environ.get('HGWITHRUSTEXT')
136 # TODO record it for proper rebuild upon changes
137 # (see mercurial/__modulepolicy__.py)
138 if hgrustext != 'cpython' and hgrustext is not None:
139 hgrustext = 'direct-ffi'
136 140
137 import ctypes 141 import ctypes
142 import errno
138 import stat, subprocess, time 143 import stat, subprocess, time
139 import re 144 import re
140 import shutil 145 import shutil
141 import tempfile 146 import tempfile
142 from distutils import log 147 from distutils import log
287 # and disable localization for the same reasons. 292 # and disable localization for the same reasons.
288 hgenv['HGPLAIN'] = '1' 293 hgenv['HGPLAIN'] = '1'
289 hgenv['LANGUAGE'] = 'C' 294 hgenv['LANGUAGE'] = 'C'
290 hgcmd = ['hg'] 295 hgcmd = ['hg']
291 # Run a simple "hg log" command just to see if using hg from the user's 296 # Run a simple "hg log" command just to see if using hg from the user's
292 # path works and can successfully interact with this repository. 297 # path works and can successfully interact with this repository. Windows
298 # gives precedence to hg.exe in the current directory, so fall back to the
299 # python invocation of local hg, where pythonXY.dll can always be found.
293 check_cmd = ['log', '-r.', '-Ttest'] 300 check_cmd = ['log', '-r.', '-Ttest']
294 try: 301 if os.name != 'nt':
295 retcode, out, err = runcmd(hgcmd + check_cmd, hgenv) 302 try:
296 except EnvironmentError: 303 retcode, out, err = runcmd(hgcmd + check_cmd, hgenv)
297 retcode = -1 304 except EnvironmentError:
298 if retcode == 0 and not filterhgerr(err): 305 retcode = -1
299 return hgcommand(hgcmd, hgenv) 306 if retcode == 0 and not filterhgerr(err):
307 return hgcommand(hgcmd, hgenv)
300 308
301 # Fall back to trying the local hg installation. 309 # Fall back to trying the local hg installation.
302 hgenv = localhgenv() 310 hgenv = localhgenv()
303 hgcmd = [sys.executable, 'hg'] 311 hgcmd = [sys.executable, 'hg']
304 try: 312 try:
455 def initialize_options(self): 463 def initialize_options(self):
456 self.zstd = True 464 self.zstd = True
457 return build_ext.initialize_options(self) 465 return build_ext.initialize_options(self)
458 466
459 def build_extensions(self): 467 def build_extensions(self):
468 ruststandalones = [e for e in self.extensions
469 if isinstance(e, RustStandaloneExtension)]
470 self.extensions = [e for e in self.extensions
471 if e not in ruststandalones]
460 # Filter out zstd if disabled via argument. 472 # Filter out zstd if disabled via argument.
461 if not self.zstd: 473 if not self.zstd:
462 self.extensions = [e for e in self.extensions 474 self.extensions = [e for e in self.extensions
463 if e.name != 'mercurial.zstd'] 475 if e.name != 'mercurial.zstd']
476
477 for rustext in ruststandalones:
478 rustext.build('' if self.inplace else self.build_lib)
464 479
465 return build_ext.build_extensions(self) 480 return build_ext.build_extensions(self)
466 481
467 def build_extension(self, ext): 482 def build_extension(self, ext):
468 if isinstance(ext, RustExtension): 483 if isinstance(ext, RustExtension):
829 'mercurial.cffi', 844 'mercurial.cffi',
830 'mercurial.hgweb', 845 'mercurial.hgweb',
831 'mercurial.pure', 846 'mercurial.pure',
832 'mercurial.thirdparty', 847 'mercurial.thirdparty',
833 'mercurial.thirdparty.attr', 848 'mercurial.thirdparty.attr',
834 'mercurial.thirdparty.cbor',
835 'mercurial.thirdparty.cbor.cbor2',
836 'mercurial.thirdparty.zope', 849 'mercurial.thirdparty.zope',
837 'mercurial.thirdparty.zope.interface', 850 'mercurial.thirdparty.zope.interface',
838 'mercurial.utils', 851 'mercurial.utils',
839 'mercurial.revlogutils', 852 'mercurial.revlogutils',
840 'mercurial.testing', 853 'mercurial.testing',
842 'hgext.fastannotate', 855 'hgext.fastannotate',
843 'hgext.fsmonitor.pywatchman', 856 'hgext.fsmonitor.pywatchman',
844 'hgext.infinitepush', 857 'hgext.infinitepush',
845 'hgext.highlight', 858 'hgext.highlight',
846 'hgext.largefiles', 'hgext.lfs', 'hgext.narrow', 859 'hgext.largefiles', 'hgext.lfs', 'hgext.narrow',
860 'hgext.remotefilelog',
847 'hgext.zeroconf', 'hgext3rd', 861 'hgext.zeroconf', 'hgext3rd',
848 'hgdemandimport'] 862 'hgdemandimport']
849 if sys.version_info[0] == 2: 863 if sys.version_info[0] == 2:
850 packages.extend(['mercurial.thirdparty.concurrent', 864 packages.extend(['mercurial.thirdparty.concurrent',
851 'mercurial.thirdparty.concurrent.futures']) 865 'mercurial.thirdparty.concurrent.futures'])
895 'mercurial/thirdparty/xdiff/xprepare.h', 909 'mercurial/thirdparty/xdiff/xprepare.h',
896 'mercurial/thirdparty/xdiff/xtypes.h', 910 'mercurial/thirdparty/xdiff/xtypes.h',
897 'mercurial/thirdparty/xdiff/xutils.h', 911 'mercurial/thirdparty/xdiff/xutils.h',
898 ] 912 ]
899 913
914 class RustCompilationError(CCompilerError):
915 """Exception class for Rust compilation errors."""
916
900 class RustExtension(Extension): 917 class RustExtension(Extension):
901 """A C Extension, conditionnally enhanced with Rust code. 918 """Base classes for concrete Rust Extension classes.
902
903 if iswithrustextensions is False, does nothing else than plain Extension
904 """ 919 """
905 920
906 rusttargetdir = os.path.join('rust', 'target', 'release') 921 rusttargetdir = os.path.join('rust', 'target', 'release')
907 922
908 def __init__(self, mpath, sources, rustlibname, subcrate, **kw): 923 def __init__(self, mpath, sources, rustlibname, subcrate,
924 py3_features=None, **kw):
909 Extension.__init__(self, mpath, sources, **kw) 925 Extension.__init__(self, mpath, sources, **kw)
910 if not iswithrustextensions: 926 if hgrustext is None:
911 return 927 return
912 srcdir = self.rustsrcdir = os.path.join('rust', subcrate) 928 srcdir = self.rustsrcdir = os.path.join('rust', subcrate)
913 self.libraries.append(rustlibname) 929 self.py3_features = py3_features
914 self.extra_compile_args.append('-DWITH_RUST')
915 930
916 # adding Rust source and control files to depends so that the extension 931 # adding Rust source and control files to depends so that the extension
917 # gets rebuilt if they've changed 932 # gets rebuilt if they've changed
918 self.depends.append(os.path.join(srcdir, 'Cargo.toml')) 933 self.depends.append(os.path.join(srcdir, 'Cargo.toml'))
919 cargo_lock = os.path.join(srcdir, 'Cargo.lock') 934 cargo_lock = os.path.join(srcdir, 'Cargo.lock')
923 self.depends.extend(os.path.join(dirpath, fname) 938 self.depends.extend(os.path.join(dirpath, fname)
924 for fname in fnames 939 for fname in fnames
925 if os.path.splitext(fname)[1] == '.rs') 940 if os.path.splitext(fname)[1] == '.rs')
926 941
927 def rustbuild(self): 942 def rustbuild(self):
928 if not iswithrustextensions: 943 if hgrustext is None:
929 return 944 return
930 env = os.environ.copy() 945 env = os.environ.copy()
931 if 'HGTEST_RESTOREENV' in env: 946 if 'HGTEST_RESTOREENV' in env:
932 # Mercurial tests change HOME to a temporary directory, 947 # Mercurial tests change HOME to a temporary directory,
933 # but, if installed with rustup, the Rust toolchain needs 948 # but, if installed with rustup, the Rust toolchain needs
939 # Unix only fix (os.path.expanduser not really reliable if 954 # Unix only fix (os.path.expanduser not really reliable if
940 # HOME is shadowed like this) 955 # HOME is shadowed like this)
941 import pwd 956 import pwd
942 env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir 957 env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir
943 958
944 subprocess.check_call(['cargo', 'build', '-vv', '--release'], 959 cargocmd = ['cargo', 'build', '-vv', '--release']
945 env=env, cwd=self.rustsrcdir) 960 if sys.version_info[0] == 3 and self.py3_features is not None:
961 cargocmd.extend(('--features', self.py3_features,
962 '--no-default-features'))
963 try:
964 subprocess.check_call(cargocmd, env=env, cwd=self.rustsrcdir)
965 except OSError as exc:
966 if exc.errno == errno.ENOENT:
967 raise RustCompilationError("Cargo not found")
968 elif exc.errno == errno.EACCES:
969 raise RustCompilationError(
970 "Cargo found, but permisssion to execute it is denied")
971 else:
972 raise
973 except subprocess.CalledProcessError:
974 raise RustCompilationError(
975 "Cargo failed. Working directory: %r, "
976 "command: %r, environment: %r" % (self.rustsrcdir, cmd, env))
977
978 class RustEnhancedExtension(RustExtension):
979 """A C Extension, conditionally enhanced with Rust code.
980
981 If the HGRUSTEXT environment variable is set to something else
982 than 'cpython', the Rust sources get compiled and linked within the
983 C target shared library object.
984 """
985
986 def __init__(self, mpath, sources, rustlibname, subcrate, **kw):
987 RustExtension.__init__(self, mpath, sources, rustlibname, subcrate,
988 **kw)
989 if hgrustext != 'direct-ffi':
990 return
991 self.extra_compile_args.append('-DWITH_RUST')
992 self.libraries.append(rustlibname)
946 self.library_dirs.append(self.rusttargetdir) 993 self.library_dirs.append(self.rusttargetdir)
994
995 class RustStandaloneExtension(RustExtension):
996
997 def __init__(self, pydottedname, rustcrate, dylibname, **kw):
998 RustExtension.__init__(self, pydottedname, [], dylibname, rustcrate,
999 **kw)
1000 self.dylibname = dylibname
1001
1002 def build(self, target_dir):
1003 self.rustbuild()
1004 target = [target_dir]
1005 target.extend(self.name.split('.'))
1006 ext = '.so' # TODO Unix only
1007 target[-1] += ext
1008 shutil.copy2(os.path.join(self.rusttargetdir, self.dylibname + ext),
1009 os.path.join(*target))
1010
947 1011
948 extmodules = [ 1012 extmodules = [
949 Extension('mercurial.cext.base85', ['mercurial/cext/base85.c'], 1013 Extension('mercurial.cext.base85', ['mercurial/cext/base85.c'],
950 include_dirs=common_include_dirs, 1014 include_dirs=common_include_dirs,
951 depends=common_depends), 1015 depends=common_depends),
955 depends=common_depends + ['mercurial/bdiff.h'] + xdiff_headers), 1019 depends=common_depends + ['mercurial/bdiff.h'] + xdiff_headers),
956 Extension('mercurial.cext.mpatch', ['mercurial/mpatch.c', 1020 Extension('mercurial.cext.mpatch', ['mercurial/mpatch.c',
957 'mercurial/cext/mpatch.c'], 1021 'mercurial/cext/mpatch.c'],
958 include_dirs=common_include_dirs, 1022 include_dirs=common_include_dirs,
959 depends=common_depends), 1023 depends=common_depends),
960 RustExtension('mercurial.cext.parsers', ['mercurial/cext/charencode.c', 1024 RustEnhancedExtension(
961 'mercurial/cext/dirs.c', 1025 'mercurial.cext.parsers', ['mercurial/cext/charencode.c',
962 'mercurial/cext/manifest.c', 1026 'mercurial/cext/dirs.c',
963 'mercurial/cext/parsers.c', 1027 'mercurial/cext/manifest.c',
964 'mercurial/cext/pathencode.c', 1028 'mercurial/cext/parsers.c',
965 'mercurial/cext/revlog.c'], 1029 'mercurial/cext/pathencode.c',
966 'hgdirectffi', 1030 'mercurial/cext/revlog.c'],
967 'hg-direct-ffi', 1031 'hgdirectffi',
968 include_dirs=common_include_dirs, 1032 'hg-direct-ffi',
969 depends=common_depends + ['mercurial/cext/charencode.h', 1033 include_dirs=common_include_dirs,
970 'mercurial/rust/src/lib.rs', 1034 depends=common_depends + ['mercurial/cext/charencode.h',
971 'mercurial/rust/src/ancestors.rs', 1035 'mercurial/cext/revlog.h',
972 'mercurial/rust/src/cpython.rs']), 1036 'rust/hg-core/src/ancestors.rs',
1037 'rust/hg-core/src/lib.rs']),
973 Extension('mercurial.cext.osutil', ['mercurial/cext/osutil.c'], 1038 Extension('mercurial.cext.osutil', ['mercurial/cext/osutil.c'],
974 include_dirs=common_include_dirs, 1039 include_dirs=common_include_dirs,
975 extra_compile_args=osutil_cflags, 1040 extra_compile_args=osutil_cflags,
976 extra_link_args=osutil_ldflags, 1041 extra_link_args=osutil_ldflags,
977 depends=common_depends), 1042 depends=common_depends),
980 'mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c', 1045 'mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c',
981 ]), 1046 ]),
982 Extension('hgext.fsmonitor.pywatchman.bser', 1047 Extension('hgext.fsmonitor.pywatchman.bser',
983 ['hgext/fsmonitor/pywatchman/bser.c']), 1048 ['hgext/fsmonitor/pywatchman/bser.c']),
984 ] 1049 ]
1050
1051 if hgrustext == 'cpython':
1052 extmodules.append(
1053 RustStandaloneExtension('mercurial.rustext', 'hg-cpython', 'librusthg',
1054 py3_features='python3')
1055 )
1056
985 1057
986 sys.path.insert(0, 'contrib/python-zstandard') 1058 sys.path.insert(0, 'contrib/python-zstandard')
987 import setup_zstd 1059 import setup_zstd
988 extmodules.append(setup_zstd.get_c_extension( 1060 extmodules.append(setup_zstd.get_c_extension(
989 name='mercurial.zstd', 1061 name='mercurial.zstd',