Defined Cargo features for Python3, making them overall simpler to
use, hooked them in build and made mercurial.rustext importable.
This is tested with Python 3.6.7.
| hg-reviewers |
Defined Cargo features for Python3, making them overall simpler to
use, hooked them in build and made mercurial.rustext importable.
This is tested with Python 3.6.7.
| Lint Skipped |
| Unit Tests Skipped |
Queued, thanks.
We'll probably need to add suffix to the filename to disambiguate py2/3
modules. It's $PYTHON-config --extension-suffix on my Linux machine, but
I don't know if it can be obtained directly in setup.py.
@yuja great, thanks. Didn't know about this suffix, apparently it can be obtained through the sysconfig module (thats what $PYTHON-config does)
~ $ python2 -c "import sysconfig; print(sysconfig.get_config_var('SO'))"
.so
~ $ python3 -c "import sysconfig; print(sysconfig.get_config_var('SO'))"
-c:1: DeprecationWarning: SO is deprecated, use EXT_SUFFIX
.cpython-37m-x86_64-linux-gnu.so
~ $ python3 -c "import sysconfig; print(sysconfig.get_config_var('EXT_SUFFIX'))"
.cpython-37m-x86_64-linux-gnu.soI suppose that's also the thing to use to build for Windows or other operating systems.
| Path | Packages | |||
|---|---|---|---|---|
| M | mercurial/__init__.py (4 lines) | |||
| M | rust/Cargo.lock (1 line) | |||
| M | rust/hg-cpython/Cargo.toml (9 lines) | |||
| M | setup.py (10 lines) |
| Commit | Parents | Author | Summary | Date |
|---|---|---|---|---|
| Georges Racinet | Dec 17 2018, 9:05 AM |
| if fullname.startswith('mercurial.cext.'): | if fullname.startswith('mercurial.cext.'): | ||||
| return None | return None | ||||
| # third-party packages are expected to be dual-version clean | # third-party packages are expected to be dual-version clean | ||||
| if fullname.startswith('mercurial.thirdparty'): | if fullname.startswith('mercurial.thirdparty'): | ||||
| return None | return None | ||||
| # zstd is already dual-version clean, don't try and mangle it | # zstd is already dual-version clean, don't try and mangle it | ||||
| if fullname.startswith('mercurial.zstd'): | if fullname.startswith('mercurial.zstd'): | ||||
| return None | return None | ||||
| # rustext is built for the right python version, | |||||
| # don't try and mangle it | |||||
| if fullname.startswith('mercurial.rustext'): | |||||
| return None | |||||
| # pywatchman is already dual-version clean, don't try and mangle it | # pywatchman is already dual-version clean, don't try and mangle it | ||||
| if fullname.startswith('hgext.fsmonitor.pywatchman'): | if fullname.startswith('hgext.fsmonitor.pywatchman'): | ||||
| return None | return None | ||||
| # Try to find the module using other registered finders. | # Try to find the module using other registered finders. | ||||
| spec = None | spec = None | ||||
| for finder in sys.meta_path: | for finder in sys.meta_path: | ||||
| if finder == self: | if finder == self: | ||||
| [[package]] | [[package]] | ||||
| name = "cpython" | name = "cpython" | ||||
| version = "0.2.1" | version = "0.2.1" | ||||
| source = "registry+https://github.com/rust-lang/crates.io-index" | source = "registry+https://github.com/rust-lang/crates.io-index" | ||||
| dependencies = [ | dependencies = [ | ||||
| "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", | "libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", | "num-traits 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| "python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | "python27-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | ||||
| "python3-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", | |||||
| ] | ] | ||||
| [[package]] | [[package]] | ||||
| name = "hg-core" | name = "hg-core" | ||||
| version = "0.1.0" | version = "0.1.0" | ||||
| [[package]] | [[package]] | ||||
| name = "hg-cpython" | name = "hg-cpython" | ||||
| [package] | [package] | ||||
| name = "hg-cpython" | name = "hg-cpython" | ||||
| version = "0.1.0" | version = "0.1.0" | ||||
| authors = ["Georges Racinet <gracinet@anybox.fr>"] | authors = ["Georges Racinet <gracinet@anybox.fr>"] | ||||
| [lib] | [lib] | ||||
| name='rusthg' | name='rusthg' | ||||
| crate-type = ["cdylib"] | crate-type = ["cdylib"] | ||||
| [features] | [features] | ||||
| default = ["python27", "python27-sys"] | default = ["python27"] | ||||
| python27 = ["cpython/python27-sys", "cpython/extension-module-2-7"] | python27 = ["cpython/python27-sys", | ||||
| "cpython/extension-module-2-7", | |||||
| "python27-sys", | |||||
| ] | |||||
| python3 = ["python3-sys", "cpython/python3-sys", "cpython/extension-module"] | |||||
| [dependencies] | [dependencies] | ||||
| hg-core = { path = "../hg-core" } | hg-core = { path = "../hg-core" } | ||||
| libc = '*' | libc = '*' | ||||
| [dependencies.cpython] | [dependencies.cpython] | ||||
| version = "*" | version = "*" | ||||
| default-features = false | default-features = false | ||||
| [dependencies.python27-sys] | [dependencies.python27-sys] | ||||
| version = "0.2.1" | version = "0.2.1" | ||||
| optional = true | optional = true | ||||
| [dependencies.python3-sys] | [dependencies.python3-sys] | ||||
| version = "0.2.1" | version = "0.2.1" | ||||
| optional = true | optional = true | ||||
| """Exception class for Rust compilation errors.""" | """Exception class for Rust compilation errors.""" | ||||
| class RustExtension(Extension): | class RustExtension(Extension): | ||||
| """Base classes for concrete Rust Extension classes. | """Base classes for concrete Rust Extension classes. | ||||
| """ | """ | ||||
| rusttargetdir = os.path.join('rust', 'target', 'release') | rusttargetdir = os.path.join('rust', 'target', 'release') | ||||
| def __init__(self, mpath, sources, rustlibname, subcrate, **kw): | def __init__(self, mpath, sources, rustlibname, subcrate, | ||||
| py3_features=None, **kw): | |||||
| Extension.__init__(self, mpath, sources, **kw) | Extension.__init__(self, mpath, sources, **kw) | ||||
| if hgrustext is None: | if hgrustext is None: | ||||
| return | return | ||||
| srcdir = self.rustsrcdir = os.path.join('rust', subcrate) | srcdir = self.rustsrcdir = os.path.join('rust', subcrate) | ||||
| self.py3_features = py3_features | |||||
| # adding Rust source and control files to depends so that the extension | # adding Rust source and control files to depends so that the extension | ||||
| # gets rebuilt if they've changed | # gets rebuilt if they've changed | ||||
| self.depends.append(os.path.join(srcdir, 'Cargo.toml')) | self.depends.append(os.path.join(srcdir, 'Cargo.toml')) | ||||
| cargo_lock = os.path.join(srcdir, 'Cargo.lock') | cargo_lock = os.path.join(srcdir, 'Cargo.lock') | ||||
| if os.path.exists(cargo_lock): | if os.path.exists(cargo_lock): | ||||
| self.depends.append(cargo_lock) | self.depends.append(cargo_lock) | ||||
| for dirpath, subdir, fnames in os.walk(os.path.join(srcdir, 'src')): | for dirpath, subdir, fnames in os.walk(os.path.join(srcdir, 'src')): | ||||
| # invoke this build. | # invoke this build. | ||||
| # Unix only fix (os.path.expanduser not really reliable if | # Unix only fix (os.path.expanduser not really reliable if | ||||
| # HOME is shadowed like this) | # HOME is shadowed like this) | ||||
| import pwd | import pwd | ||||
| env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir | env['HOME'] = pwd.getpwuid(os.getuid()).pw_dir | ||||
| cargocmd = ['cargo', 'build', '-vv', '--release'] | cargocmd = ['cargo', 'build', '-vv', '--release'] | ||||
| if sys.version_info[0] == 3 and self.py3_features is not None: | |||||
| cargocmd.extend(('--features', self.py3_features, | |||||
| '--no-default-features')) | |||||
| try: | try: | ||||
| subprocess.check_call(cargocmd, env=env, cwd=self.rustsrcdir) | subprocess.check_call(cargocmd, env=env, cwd=self.rustsrcdir) | ||||
| except OSError as exc: | except OSError as exc: | ||||
| if exc.errno == errno.ENOENT: | if exc.errno == errno.ENOENT: | ||||
| raise RustCompilationError("Cargo not found") | raise RustCompilationError("Cargo not found") | ||||
| elif exc.errno == errno.EACCES: | elif exc.errno == errno.EACCES: | ||||
| raise RustCompilationError( | raise RustCompilationError( | ||||
| "Cargo found, but permisssion to execute it is denied") | "Cargo found, but permisssion to execute it is denied") | ||||
| 'mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c', | 'mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c', | ||||
| ]), | ]), | ||||
| Extension('hgext.fsmonitor.pywatchman.bser', | Extension('hgext.fsmonitor.pywatchman.bser', | ||||
| ['hgext/fsmonitor/pywatchman/bser.c']), | ['hgext/fsmonitor/pywatchman/bser.c']), | ||||
| ] | ] | ||||
| if hgrustext == 'cpython': | if hgrustext == 'cpython': | ||||
| extmodules.append( | extmodules.append( | ||||
| RustStandaloneExtension('mercurial.rustext', 'hg-cpython', 'librusthg') | RustStandaloneExtension('mercurial.rustext', 'hg-cpython', 'librusthg', | ||||
| py3_features='python3') | |||||
| ) | ) | ||||
| sys.path.insert(0, 'contrib/python-zstandard') | sys.path.insert(0, 'contrib/python-zstandard') | ||||
| import setup_zstd | import setup_zstd | ||||
| extmodules.append(setup_zstd.get_c_extension( | extmodules.append(setup_zstd.get_c_extension( | ||||
| name='mercurial.zstd', | name='mercurial.zstd', | ||||
| root=os.path.abspath(os.path.dirname(__file__)))) | root=os.path.abspath(os.path.dirname(__file__)))) | ||||