Skip to content

Commit d9eb84a

Browse files
committed
cargo: add configurable features to Interpreter
Add features property to cargo.Interpreter to make default features configurable; customization of which features are enabled by default is triggered by rust.workspace().
1 parent e6cbcbe commit d9eb84a

File tree

3 files changed

+55
-4
lines changed

3 files changed

+55
-4
lines changed

docs/markdown/Rust-module.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -180,9 +180,21 @@ rustmod.workspace(...)
180180
Create and return a `workspace` object for managing the project's Cargo
181181
workspace.
182182

183+
Keyword arguments:
184+
- `default_features`: (`bool`, optional) Whether to enable default features.
185+
If not specified and `features` is provided, defaults to true.
186+
- `features`: (`list[str]`, optional) List of additional features to enable globally
187+
183188
The function must be called in a project with `Cargo.lock` and `Cargo.toml`
184189
files in the root source directory. While the object currently has
185190
no methods, upon its creation Meson analyzes the `Cargo.toml` file and
186191
computes the full set of dependencies and features needed to build the
187192
package in `Cargo.toml`. Therefore, this function should be invoked before
188193
using Cargo subprojects. Methods will be added in future versions of Meson.
194+
195+
If either argument is provided, the build will use a custom set of features.
196+
Features can only be set once - subsequent calls will fail if different features
197+
are specified.
198+
199+
When `features` is provided without `default_features`, the 'default' feature is
200+
automatically included.

mesonbuild/cargo/interpreter.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from . import builder, version, cfg
2121
from .toml import load_toml
2222
from .manifest import Manifest, CargoLock, fixup_meson_varname
23-
from ..mesonlib import MesonException, MachineChoice, version_compare
23+
from ..mesonlib import MesonException, MachineChoice, unique_list, version_compare
2424
from .. import coredata, mlog
2525
from ..wrap.wrap import PackageDefinition
2626

@@ -65,6 +65,8 @@ class PackageKey:
6565

6666

6767
class Interpreter:
68+
_features: T.Optional[T.List[str]] = None
69+
6870
def __init__(self, env: Environment, subdir: str, subprojects_dir: str) -> None:
6971
self.environment = env
7072
# Map Cargo.toml's subdir to loaded manifest.
@@ -80,6 +82,21 @@ def __init__(self, env: Environment, subdir: str, subprojects_dir: str) -> None:
8082
self.subdir = subdir
8183
self.environment.wrap_resolver.merge_wraps(self.cargolock.wraps)
8284

85+
@property
86+
def features(self) -> T.List[str]:
87+
"""Get the features list. Once read, it cannot be modified."""
88+
if self._features is None:
89+
self._features = ['default']
90+
return self._features
91+
92+
@features.setter
93+
def features(self, value: T.List[str]) -> None:
94+
"""Set the features list. Can only be set before first read."""
95+
value_unique = sorted(unique_list(value))
96+
if self._features is not None and value_unique != self._features:
97+
raise MesonException("Cannot modify features after they have been selected or used")
98+
self._features = value_unique
99+
83100
def get_build_def_files(self) -> T.List[str]:
84101
build_def_files = [os.path.join(subdir, 'Cargo.toml') for subdir in self.manifests]
85102
if self.cargolock:
@@ -94,7 +111,8 @@ def load_root_package(self) -> PackageState:
94111
key = PackageKey(manifest.package.name, manifest.package.api)
95112
self.packages[key] = pkg
96113
self._prepare_package(pkg)
97-
self._enable_feature(pkg, 'default')
114+
for feature in self.features:
115+
self._enable_feature(pkg, feature)
98116
return pkg
99117

100118
def interpret(self, subdir: str) -> mparser.CodeBlockNode:

mesonbuild/modules/rust.py

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
DEPENDENCIES_KW, LINK_WITH_KW, LINK_WHOLE_KW, SHARED_LIB_KWS, TEST_KWS, TEST_KWS_NO_ARGS,
1919
OUTPUT_KW, INCLUDE_DIRECTORIES, SOURCES_VARARGS, NoneType, in_set_validator
2020
)
21-
from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noKwargs, noPosargs, permittedKwargs
21+
from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs, permittedKwargs
2222
from ..interpreter.interpreterobjects import Doctest
2323
from ..mesonlib import File, MesonException, PerMachine
2424
from ..programs import ExternalProgram, NonExistingExternalProgram
@@ -495,13 +495,34 @@ def proc_macro(self, state: ModuleState, args: T.Tuple[str, SourcesVarargsType],
495495
return target
496496

497497
@noPosargs
498-
@noKwargs
498+
@typed_kwargs(
499+
'rust.workspace',
500+
KwargInfo('default_features', (bool, NoneType), default=None),
501+
KwargInfo(
502+
'features',
503+
(ContainerTypeInfo(list, str), NoneType),
504+
default=None,
505+
listify=True,
506+
),
507+
)
499508
def workspace(self, state: ModuleState, args: T.List, kwargs: T.Dict[str, T.Any]) -> RustWorkspace:
500509
"""Creates a Rust workspace object, controlling the build of
501510
all the packages in a Cargo.lock file."""
502511
if self.interpreter.cargo is None:
503512
raise MesonException("rust.workspace() requires a Cargo project (Cargo.toml and Cargo.lock)")
504513

514+
default_features = kwargs['default_features']
515+
features = kwargs['features']
516+
if default_features is not None or features is not None:
517+
# If custom features are provided, default_features = None should be treated as True
518+
if default_features is None:
519+
default_features = True
520+
521+
cargo_features = ['default'] if default_features else []
522+
if features is not None:
523+
cargo_features.extend(features)
524+
self.interpreter.cargo.features = cargo_features
525+
505526
# Check if we already have a cached workspace for this cargo interpreter
506527
ws_obj = self._workspace_cache.get(self.interpreter.cargo)
507528
if ws_obj is None:

0 commit comments

Comments
 (0)