From d8e872a8d3bffb01b617b84bb2a285437146fd36 Mon Sep 17 00:00:00 2001 From: Daniele Nicolodi Date: Sat, 9 Dec 2023 20:33:44 +0100 Subject: [PATCH] ENH: support shared libraries on Windows when explicitly enabled Fixes #525. --- mesonpy/__init__.py | 14 ++++++++++++-- mesonpy/_rpath.py | 2 +- tests/test_tags.py | 2 +- tests/test_wheel.py | 3 ++- 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/mesonpy/__init__.py b/mesonpy/__init__.py index 05016a1c..b3db7799 100644 --- a/mesonpy/__init__.py +++ b/mesonpy/__init__.py @@ -311,10 +311,12 @@ def __init__( metadata: Metadata, manifest: Dict[str, List[Tuple[pathlib.Path, str]]], limited_api: bool, + shared_libs_win32: bool, ) -> None: self._metadata = metadata self._manifest = manifest self._limited_api = limited_api + self._shared_libs_win32 = shared_libs_win32 @property def _has_internal_libs(self) -> bool: @@ -430,6 +432,9 @@ def _install_path(self, wheel_file: mesonpy._wheelfile.WheelFile, origin: Path, if self._has_internal_libs: if _is_native(origin): + if sys.platform == 'win32' and not self._shared_libs_win32: + raise NotImplementedError(f'Bundling libraries in wheel is not supported on {sys.platform}') + # When an executable, libray, or Python extension module is # dynamically linked to a library built as part of the project, # Meson adds a library load path to it pointing to the build @@ -566,6 +571,7 @@ def _string_or_path(value: Any, name: str) -> str: scheme = _table({ 'meson': _string_or_path, 'limited-api': _bool, + 'shared-libs-win32': _bool, 'args': _table({ name: _strings for name in _MESON_ARGS_KEYS }), @@ -757,6 +763,10 @@ def __init__( if not value: self._limited_api = False + # Shared library support on Windows requires collaboration + # from the package, make sure the developpers aknowledge this. + self._shared_libs_win32 = pyproject_config.get('shared-libs-win32', False) + def _run(self, cmd: Sequence[str]) -> None: """Invoke a subprocess.""" # Flush the line to ensure that the log line with the executed @@ -920,13 +930,13 @@ def sdist(self, directory: Path) -> pathlib.Path: def wheel(self, directory: Path) -> pathlib.Path: """Generates a wheel in the specified directory.""" self.build() - builder = _WheelBuilder(self._metadata, self._manifest, self._limited_api) + builder = _WheelBuilder(self._metadata, self._manifest, self._limited_api, self._shared_libs_win32) return builder.build(directory) def editable(self, directory: Path) -> pathlib.Path: """Generates an editable wheel in the specified directory.""" self.build() - builder = _EditableWheelBuilder(self._metadata, self._manifest, self._limited_api) + builder = _EditableWheelBuilder(self._metadata, self._manifest, self._limited_api, self._shared_libs_win32) return builder.build(directory, self._source_dir, self._build_dir, self._build_command, self._editable_verbose) diff --git a/mesonpy/_rpath.py b/mesonpy/_rpath.py index 6c0016b3..e618fbb7 100644 --- a/mesonpy/_rpath.py +++ b/mesonpy/_rpath.py @@ -19,7 +19,7 @@ if sys.platform == 'win32' or sys.platform == 'cygwin': def fix_rpath(filepath: Path, libs_relative_path: str) -> None: - raise NotImplementedError(f'Bundling libraries in wheel is not supported on {sys.platform}') + pass elif sys.platform == 'darwin': diff --git a/tests/test_tags.py b/tests/test_tags.py index c55d6973..73d1187f 100644 --- a/tests/test_tags.py +++ b/tests/test_tags.py @@ -77,7 +77,7 @@ def test_python_host_platform(monkeypatch): def wheel_builder_test_factory(content, pure=True, limited_api=False): manifest = defaultdict(list) manifest.update({key: [(pathlib.Path(x), os.path.join('build', x)) for x in value] for key, value in content.items()}) - return mesonpy._WheelBuilder(None, manifest, limited_api) + return mesonpy._WheelBuilder(None, manifest, limited_api, False) def test_tag_empty_wheel(): diff --git a/tests/test_wheel.py b/tests/test_wheel.py index 33a974c4..e8ece686 100644 --- a/tests/test_wheel.py +++ b/tests/test_wheel.py @@ -231,7 +231,8 @@ def test_entrypoints(wheel_full_metadata): def test_top_level_modules(package_module_types): with mesonpy._project() as project: - builder = mesonpy._EditableWheelBuilder(project._metadata, project._manifest, project._limited_api) + builder = mesonpy._EditableWheelBuilder( + project._metadata, project._manifest, project._limited_api, project._shared_libs_win32) assert set(builder._top_level_modules) == { 'file', 'package',