--- a/setup.py Thu Dec 06 16:23:20 2018 +0100
+++ b/setup.py Thu Dec 06 16:34:22 2018 +0100
@@ -132,7 +132,11 @@
ispypy = "PyPy" in sys.version
-iswithrustextensions = 'HGWITHRUSTEXT' in os.environ
+hgrustext = os.environ.get('HGWITHRUSTEXT')
+# TODO record it for proper rebuild upon changes
+# (see mercurial/__modulepolicy__.py)
+if hgrustext != 'cpython' and hgrustext is not None:
+ hgrustext = 'direct-ffi'
import ctypes
import errno
@@ -458,11 +462,18 @@
return build_ext.initialize_options(self)
def build_extensions(self):
+ ruststandalones = [e for e in self.extensions
+ if isinstance(e, RustStandaloneExtension)]
+ self.extensions = [e for e in self.extensions
+ if e not in ruststandalones]
# Filter out zstd if disabled via argument.
if not self.zstd:
self.extensions = [e for e in self.extensions
if e.name != 'mercurial.zstd']
+ for rustext in ruststandalones:
+ rustext.build('' if self.inplace else self.build_lib)
+
return build_ext.build_extensions(self)
def build_extension(self, ext):
@@ -903,20 +914,16 @@
"""Exception class for Rust compilation errors."""
class RustExtension(Extension):
- """A C Extension, conditionnally enhanced with Rust code.
-
- if iswithrustextensions is False, does nothing else than plain Extension
+ """Base classes for concrete Rust Extension classes.
"""
rusttargetdir = os.path.join('rust', 'target', 'release')
def __init__(self, mpath, sources, rustlibname, subcrate, **kw):
Extension.__init__(self, mpath, sources, **kw)
- if not iswithrustextensions:
+ if hgrustext is None:
return
srcdir = self.rustsrcdir = os.path.join('rust', subcrate)
- self.libraries.append(rustlibname)
- self.extra_compile_args.append('-DWITH_RUST')
# adding Rust source and control files to depends so that the extension
# gets rebuilt if they've changed
@@ -930,7 +937,7 @@
if os.path.splitext(fname)[1] == '.rs')
def rustbuild(self):
- if not iswithrustextensions:
+ if hgrustext is None:
return
env = os.environ.copy()
if 'HGTEST_RESTOREENV' in env:
@@ -962,6 +969,40 @@
"Cargo failed. Working directory: %r, "
"command: %r, environment: %r" % (self.rustsrcdir, cmd, env))
+class RustEnhancedExtension(RustExtension):
+ """A C Extension, conditionally enhanced with Rust code.
+
+ If the HGRUSTEXT environment variable is set to something else
+ than 'cpython', the Rust sources get compiled and linked within the
+ C target shared library object.
+ """
+
+ def __init__(self, mpath, sources, rustlibname, subcrate, **kw):
+ RustExtension.__init__(self, mpath, sources, rustlibname, subcrate,
+ **kw)
+ if hgrustext != 'direct-ffi':
+ return
+ self.extra_compile_args.append('-DWITH_RUST')
+ self.libraries.append(rustlibname)
+ self.library_dirs.append(self.rusttargetdir)
+
+class RustStandaloneExtension(RustExtension):
+
+ def __init__(self, pydottedname, rustcrate, dylibname, **kw):
+ RustExtension.__init__(self, pydottedname, [], dylibname, rustcrate,
+ **kw)
+ self.dylibname = dylibname
+
+ def build(self, target_dir):
+ self.rustbuild()
+ target = [target_dir]
+ target.extend(self.name.split('.'))
+ ext = '.so' # TODO Unix only
+ target[-1] += ext
+ shutil.copy2(os.path.join(self.rusttargetdir, self.dylibname + ext),
+ os.path.join(*target))
+
+
extmodules = [
Extension('mercurial.cext.base85', ['mercurial/cext/base85.c'],
include_dirs=common_include_dirs,
@@ -974,19 +1015,20 @@
'mercurial/cext/mpatch.c'],
include_dirs=common_include_dirs,
depends=common_depends),
- RustExtension('mercurial.cext.parsers', ['mercurial/cext/charencode.c',
- 'mercurial/cext/dirs.c',
- 'mercurial/cext/manifest.c',
- 'mercurial/cext/parsers.c',
- 'mercurial/cext/pathencode.c',
- 'mercurial/cext/revlog.c'],
- 'hgdirectffi',
- 'hg-direct-ffi',
- include_dirs=common_include_dirs,
- depends=common_depends + ['mercurial/cext/charencode.h',
- 'mercurial/cext/revlog.h',
- 'rust/hg-core/src/ancestors.rs',
- 'rust/hg-core/src/lib.rs']),
+ RustEnhancedExtension(
+ 'mercurial.cext.parsers', ['mercurial/cext/charencode.c',
+ 'mercurial/cext/dirs.c',
+ 'mercurial/cext/manifest.c',
+ 'mercurial/cext/parsers.c',
+ 'mercurial/cext/pathencode.c',
+ 'mercurial/cext/revlog.c'],
+ 'hgdirectffi',
+ 'hg-direct-ffi',
+ include_dirs=common_include_dirs,
+ depends=common_depends + ['mercurial/cext/charencode.h',
+ 'mercurial/cext/revlog.h',
+ 'rust/hg-core/src/ancestors.rs',
+ 'rust/hg-core/src/lib.rs']),
Extension('mercurial.cext.osutil', ['mercurial/cext/osutil.c'],
include_dirs=common_include_dirs,
extra_compile_args=osutil_cflags,
@@ -1000,6 +1042,12 @@
['hgext/fsmonitor/pywatchman/bser.c']),
]
+if hgrustext == 'cpython':
+ extmodules.append(
+ RustStandaloneExtension('mercurial.rustext', 'hg-cpython', 'librusthg')
+ )
+
+
sys.path.insert(0, 'contrib/python-zstandard')
import setup_zstd
extmodules.append(setup_zstd.get_c_extension(