Skip to content

Commit 6096481

Browse files
committed
cargo: include the implicit feature for dependencies in the manifest
Make the implicit `xyz = ["dep:xyz"]` declaration explicit in the Manifest. This also makes it possible to implement correctly the part of the spec where "If you specify the optional dependency with the dep: prefix anywhere in the [features] table, that disables the implicit feature." Unfortunately, this can only be done after target-specific configurations are resolved, which makes it hard to write a unit test for this. Rustix requires it, though; without this patch, something like [package] name = "rustix" edition = "2021" rust-version = "1.63" version = "0.38.34" [dependencies] alloc = { version = "1.0.0", optional = true, package = "rustc-std-workspace-alloc" } libc = { version = "0.2.0", optional = true, package = "libc" } libc_errno = { version = "0.3.8", optional = true, package = "errno" } [features] alloc = [] default = ["std"] rustc-dep-of-std = ["dep:alloc"] std = ["alloc"] use-libc = ["libc_errno", "libc"] would incorrectly request the rustc-std-workspace-alloc crate via the chain default->std->alloc. The patch blocks it because it finds the "dep:alloc" dependency of feature rustc-dep-of-std. Signed-off-by: Paolo Bonzini <[email protected]>
1 parent a90592a commit 6096481

File tree

1 file changed

+15
-3
lines changed

1 file changed

+15
-3
lines changed

mesonbuild/cargo/interpreter.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
from __future__ import annotations
1313
import dataclasses
1414
import functools
15+
import itertools
1516
import os
1617
import pathlib
1718
import collections
@@ -428,6 +429,20 @@ def _prepare_package(self, pkg: PackageState) -> None:
428429
for condition, dependencies in pkg.manifest.target.items():
429430
if eval_cfg(condition, cfgs):
430431
pkg.manifest.dependencies.update(dependencies)
432+
433+
# If you specify the optional dependency with the dep: prefix anywhere in the [features]
434+
# table, that disables the implicit feature.
435+
deps = set(feature[4:]
436+
for feature in itertools.chain.from_iterable(pkg.manifest.features.values())
437+
if feature.startswith('dep:'))
438+
for name, dep in itertools.chain(pkg.manifest.dependencies.items(),
439+
pkg.manifest.dev_dependencies.items(),
440+
pkg.manifest.build_dependencies.items()):
441+
if dep.optional and name not in deps:
442+
pkg.manifest.features.setdefault(name, [])
443+
pkg.manifest.features[name].append(f'dep:{name}')
444+
deps.add(name)
445+
431446
# Fetch required dependencies recursively.
432447
for depname, dep in pkg.manifest.dependencies.items():
433448
if not dep.optional:
@@ -499,9 +514,6 @@ def _enable_feature(self, pkg: PackageState, feature: str) -> None:
499514
if feature in cfg.features:
500515
return
501516
cfg.features.add(feature)
502-
# A feature can also be a dependency.
503-
if feature in pkg.manifest.dependencies:
504-
self._add_dependency(pkg, feature)
505517
# Recurse on extra features and dependencies this feature pulls.
506518
# https://doc.rust-lang.org/cargo/reference/features.html#the-features-section
507519
for f in pkg.manifest.features.get(feature, []):

0 commit comments

Comments
 (0)