diff options
| author | Paolo Bonzini <pbonzini@redhat.com> | 2025-09-24 17:23:20 +0200 |
|---|---|---|
| committer | Dylan Baker <dylan@pnwbakers.com> | 2025-10-14 09:35:56 -0700 |
| commit | 16c5080a184f095dd721b719b5406128aee5e890 (patch) | |
| tree | 31539a29d0f3df2fb8daa2875587554cca37c57f | |
| parent | f864690f3a74ed4f751e9b6d9a8855ec16030c65 (diff) | |
| download | meson-16c5080a184f095dd721b719b5406128aee5e890.tar.gz | |
cargo: improve error message for dependency version conflicts
While developing I often got a confusing 'Neither a subproject directory nor
a None.wrap file was found'. Replace it with a clear message that explains:
1. Which dependency couldn't be found
2. What versions are available in the root Cargo.lock
3. That this is likely a version conflict
4. How to fix it (update dependencies to match root Cargo.lock)
Example:
ERROR: Dependency 'socket2-0.4-rs' not found. Root Cargo.lock provides:
socket2-0.5-rs, socket2-0.6-rs. This could be a Meson bug, please report it.
I am actually not sure if this is really always a Meson bug. But to be
safe, suggest reporting it until more experience is gained.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
| -rw-r--r-- | mesonbuild/cargo/interpreter.py | 11 | ||||
| -rw-r--r-- | mesonbuild/cargo/manifest.py | 23 |
2 files changed, 33 insertions, 1 deletions
diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index be3d29337..74d7ae09f 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -124,6 +124,17 @@ class Interpreter: def _fetch_package_from_subproject(self, package_name: str, meson_depname: str) -> T.Tuple[PackageState, bool]: subp_name, _ = self.environment.wrap_resolver.find_dep_provider(meson_depname) + if subp_name is None: + # If Cargo.lock has a different version, this could be a resolution + # bug, but maybe also a version mismatch? I am not sure yet... + similar_deps = [pkg.subproject + for pkg in self.cargolock.named(package_name)] + if similar_deps: + similar_msg = f'Cargo.lock provides: {", ".join(similar_deps)}.' + else: + similar_msg = 'Cargo.lock does not contain this crate name.' + raise MesonException(f'Dependency {meson_depname!r} not found in any wrap files or Cargo.lock; {similar_msg} This could be a Meson bug, please report it.') + subdir, _ = self.environment.wrap_resolver.resolve(subp_name) subprojects_dir = os.path.join(subdir, 'subprojects') self.environment.wrap_resolver.load_and_merge(subprojects_dir, T.cast('SubProject', meson_depname)) diff --git a/mesonbuild/cargo/manifest.py b/mesonbuild/cargo/manifest.py index 698bb98a5..01e7c697b 100644 --- a/mesonbuild/cargo/manifest.py +++ b/mesonbuild/cargo/manifest.py @@ -5,12 +5,13 @@ from __future__ import annotations +import collections import dataclasses import os import typing as T from . import version -from ..mesonlib import MesonException, lazy_property +from ..mesonlib import MesonException, lazy_property, Version from .. import mlog if T.TYPE_CHECKING: @@ -489,6 +490,14 @@ class CargoLockPackage: checksum: T.Optional[str] = None dependencies: T.List[str] = dataclasses.field(default_factory=list) + @lazy_property + def api(self) -> str: + return version.api(self.version) + + @lazy_property + def subproject(self) -> str: + return f'{self.name}-{self.api}-rs' + @classmethod def from_raw(cls, raw: raw.CargoLockPackage) -> CargoLockPackage: return _raw_to_dataclass(raw, cls, 'Cargo.lock package') @@ -508,3 +517,15 @@ class CargoLock: def from_raw(cls, raw: raw.CargoLock) -> CargoLock: return _raw_to_dataclass(raw, cls, 'Cargo.lock', package=lambda x: [CargoLockPackage.from_raw(p) for p in x]) + + def named(self, name: str) -> T.Sequence[CargoLockPackage]: + return self._versions[name] + + @lazy_property + def _versions(self) -> T.Dict[str, T.List[CargoLockPackage]]: + versions = collections.defaultdict(list) + for pkg in self.package: + versions[pkg.name].append(pkg) + for pkg_versions in versions.values(): + pkg_versions.sort(reverse=True, key=lambda pkg: Version(pkg.version)) + return versions |
