Mercurial > public > mercurial-scm > hg-stable
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', |