diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py index 25a1b70dbf01..6acd998cdecd 100644 --- a/mesonbuild/cargo/interpreter.py +++ b/mesonbuild/cargo/interpreter.py @@ -12,6 +12,7 @@ from __future__ import annotations import dataclasses import functools +import itertools import os import pathlib import collections @@ -144,6 +145,8 @@ def get_lint_args(self, rustc: RustCompiler) -> T.List[str]: args.extend(lint.to_arguments(has_check_cfg)) if has_check_cfg: + args.append('--check-cfg') + args.append('cfg(test)') for feature in self.manifest.features: if feature != 'default': args.append('--check-cfg') @@ -426,6 +429,20 @@ def _prepare_package(self, pkg: PackageState) -> None: for condition, dependencies in pkg.manifest.target.items(): if eval_cfg(condition, cfgs): pkg.manifest.dependencies.update(dependencies) + + # If you specify the optional dependency with the dep: prefix anywhere in the [features] + # table, that disables the implicit feature. + deps = set(feature[4:] + for feature in itertools.chain.from_iterable(pkg.manifest.features.values()) + if feature.startswith('dep:')) + for name, dep in itertools.chain(pkg.manifest.dependencies.items(), + pkg.manifest.dev_dependencies.items(), + pkg.manifest.build_dependencies.items()): + if dep.optional and name not in deps: + pkg.manifest.features.setdefault(name, []) + pkg.manifest.features[name].append(f'dep:{name}') + deps.add(name) + # Fetch required dependencies recursively. for depname, dep in pkg.manifest.dependencies.items(): if not dep.optional: @@ -497,9 +514,6 @@ def _enable_feature(self, pkg: PackageState, feature: str) -> None: if feature in cfg.features: return cfg.features.add(feature) - # A feature can also be a dependency. - if feature in pkg.manifest.dependencies: - self._add_dependency(pkg, feature) # Recurse on extra features and dependencies this feature pulls. # https://doc.rust-lang.org/cargo/reference/features.html#the-features-section for f in pkg.manifest.features.get(feature, []): diff --git a/mesonbuild/cargo/manifest.py b/mesonbuild/cargo/manifest.py index ec84e4b16cf2..2c3eeb3e0cf4 100644 --- a/mesonbuild/cargo/manifest.py +++ b/mesonbuild/cargo/manifest.py @@ -442,8 +442,7 @@ def from_raw(cls, r: T.Union[raw.FromWorkspace, T.Dict[str, T.Dict[str, raw.Lint settings = T.cast('raw.Lint', {'level': settings}) check_cfg = None if name == 'unexpected_cfgs': - # 'cfg(test)' is added automatically by cargo - check_cfg = ['cfg(test)'] + settings.get('check-cfg', []) + check_cfg = settings.get('check-cfg', []) lints[name] = Lint(name=name, level=settings['level'], priority=settings.get('priority', 0), diff --git a/unittests/cargotests.py b/unittests/cargotests.py index 643ceceb49a6..e8eace74fa2e 100644 --- a/unittests/cargotests.py +++ b/unittests/cargotests.py @@ -428,7 +428,7 @@ def test_cargo_toml_lints(self) -> None: self.assertEqual(manifest.lints[2].name, 'unexpected_cfgs') self.assertEqual(manifest.lints[2].level, 'deny') self.assertEqual(manifest.lints[2].priority, 0) - self.assertEqual(manifest.lints[2].check_cfg, ['cfg(test)', 'cfg(MESON)']) + self.assertEqual(manifest.lints[2].check_cfg, ['cfg(MESON)']) def test_cargo_toml_lints_to_args(self) -> None: with tempfile.TemporaryDirectory() as tmpdir: @@ -444,8 +444,7 @@ def test_cargo_toml_lints_to_args(self) -> None: self.assertEqual(manifest.lints[1].to_arguments(True), ['-A', 'unknown_lints']) self.assertEqual(manifest.lints[2].to_arguments(False), ['-D', 'unexpected_cfgs']) self.assertEqual(manifest.lints[2].to_arguments(True), - ['-D', 'unexpected_cfgs', '--check-cfg', 'cfg(test)', - '--check-cfg', 'cfg(MESON)']) + ['-D', 'unexpected_cfgs', '--check-cfg', 'cfg(MESON)']) def test_cargo_toml_dependencies(self) -> None: with tempfile.TemporaryDirectory() as tmpdir: