dowel

ADR-0017: Features belong to the package that declares them; dep/feature forwards

Status: Accepted

Context

[features] was resolved once, from the root package, into one flat set of names. Every feature.<name> reference in every package’s dowel.build was answered from that single set.

Two things followed, neither intended.

The second is the worse of the two: the manifest reads as though the dependency is being configured, and nothing says otherwise. Validation already treated features as package-scoped — feature.<name> must be declared in that package’s [features] — so the reference side and the activation side disagreed.

Decision

A feature belongs to the package that declares it. Activation is resolved per package, and a value in [features] may name a dependency’s feature:

The active set is carried as <package>/<feature> pairs, and feature.<name> is answered by qualifying with the package whose manifest the value was declared in. Specialization therefore happens per package (Config::for_package), which is where the two sides are reconciled.

Because a forwarded feature can activate an optional dependency inside the dependency — which changes what gets loaded — loading and feature resolution are mutually dependent. The walk is repeated until the requested sets stop growing. Sets only grow, so this terminates; loading, git fetching, and pkg-config resolution are memoized, so later rounds have no external effects.

Consequences