summaryrefslogtreecommitdiff
path: root/mesonbuild
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2025-10-17 18:50:15 +0200
committerPaolo Bonzini <pbonzini@redhat.com>2025-12-22 11:58:30 +0100
commit5de9723535506f625e093cbf9549b3ce0bf5940f (patch)
tree49dedb66344ec9fad644c03a21fff43990302ec2 /mesonbuild
parent646593856800c55f44fe2b15991570737709a36e (diff)
downloadmeson-5de9723535506f625e093cbf9549b3ce0bf5940f.tar.gz
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(). Fixes: #14290 Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'mesonbuild')
-rw-r--r--mesonbuild/cargo/interpreter.py22
-rw-r--r--mesonbuild/modules/rust.py31
2 files changed, 47 insertions, 6 deletions
diff --git a/mesonbuild/cargo/interpreter.py b/mesonbuild/cargo/interpreter.py
index cc7e2a65b..2a14fc096 100644
--- a/mesonbuild/cargo/interpreter.py
+++ b/mesonbuild/cargo/interpreter.py
@@ -24,7 +24,7 @@ from . import builder, version
from .cfg import eval_cfg
from .toml import load_toml
from .manifest import Manifest, CargoLock, CargoLockPackage, Workspace, fixup_meson_varname
-from ..mesonlib import is_parent_path, MesonException, MachineChoice, version_compare
+from ..mesonlib import is_parent_path, MesonException, MachineChoice, unique_list, version_compare
from .. import coredata, mlog
from ..wrap.wrap import PackageDefinition
@@ -205,6 +205,8 @@ class WorkspaceState:
class Interpreter:
+ _features: T.Optional[T.List[str]] = None
+
def __init__(self, env: Environment, subdir: str, subprojects_dir: str) -> None:
self.environment = env
self.subprojects_dir = subprojects_dir
@@ -224,6 +226,21 @@ class Interpreter:
self.environment.wrap_resolver.merge_wraps(self.cargolock.wraps)
self.build_def_files.append(filename)
+ @property
+ def features(self) -> T.List[str]:
+ """Get the features list. Once read, it cannot be modified."""
+ if self._features is None:
+ self._features = ['default']
+ return self._features
+
+ @features.setter
+ def features(self, value: T.List[str]) -> None:
+ """Set the features list. Can only be set before first read."""
+ value_unique = sorted(unique_list(value))
+ if self._features is not None and value_unique != self._features:
+ raise MesonException("Cannot modify features after they have been selected or used")
+ self._features = value_unique
+
def get_build_def_files(self) -> T.List[str]:
return self.build_def_files
@@ -240,7 +257,8 @@ class Interpreter:
pkgs = [self._require_workspace_member(ws, m) for m in ws.workspace.default_members]
for pkg in pkgs:
self._prepare_package(pkg)
- self._enable_feature(pkg, 'default')
+ for feature in self.features:
+ self._enable_feature(pkg, feature)
def interpret(self, subdir: str, project_root: T.Optional[str] = None) -> mparser.CodeBlockNode:
filename = os.path.join(self.environment.source_dir, subdir, 'Cargo.toml')
diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py
index 84ea70fce..39e1d9ce1 100644
--- a/mesonbuild/modules/rust.py
+++ b/mesonbuild/modules/rust.py
@@ -19,8 +19,7 @@ from ..interpreter.type_checking import (
DEPENDENCIES_KW, LINK_WITH_KW, LINK_WHOLE_KW, SHARED_LIB_KWS, TEST_KWS, TEST_KWS_NO_ARGS,
OUTPUT_KW, INCLUDE_DIRECTORIES, SOURCES_VARARGS, NoneType, in_set_validator
)
-from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noKwargs, noPosargs, permittedKwargs
-from ..interpreterbase.baseobjects import TYPE_kwargs
+from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noPosargs, permittedKwargs
from ..interpreter.interpreterobjects import Doctest
from ..mesonlib import File, MachineChoice, MesonException, PerMachine
from ..programs import ExternalProgram, NonExistingExternalProgram
@@ -65,6 +64,9 @@ if T.TYPE_CHECKING:
language: T.Optional[Literal['c', 'cpp']]
bindgen_version: T.List[str]
+ class FuncWorkspace(TypedDict):
+ default_features: T.Optional[bool]
+ features: T.List[str]
RUST_TEST_KWS: T.List[KwargInfo] = [
KwargInfo(
@@ -515,8 +517,17 @@ class RustModule(ExtensionModule):
@FeatureNew('rust.workspace', '1.11.0')
@noPosargs
- @noKwargs
- def workspace(self, state: ModuleState, args: T.List, kwargs: TYPE_kwargs) -> RustWorkspace:
+ @typed_kwargs(
+ 'rust.workspace',
+ KwargInfo('default_features', (bool, NoneType), default=None),
+ KwargInfo(
+ 'features',
+ (ContainerTypeInfo(list, str), NoneType),
+ default=None,
+ listify=True,
+ ),
+ )
+ def workspace(self, state: ModuleState, args: T.List, kwargs: FuncWorkspace) -> RustWorkspace:
"""Creates a Rust workspace object, controlling the build of
all the packages in a Cargo.lock file."""
if self.interpreter.cargo is None:
@@ -525,6 +536,18 @@ class RustModule(ExtensionModule):
self.interpreter.add_languages(['rust'], True, MachineChoice.HOST)
self.interpreter.add_languages(['rust'], True, MachineChoice.BUILD)
+ default_features = kwargs['default_features']
+ features = kwargs['features']
+ if default_features is not None or features is not None:
+ # If custom features are provided, default_features = None should be treated as True
+ if default_features is None:
+ default_features = True
+
+ cargo_features = ['default'] if default_features else []
+ if features is not None:
+ cargo_features.extend(features)
+ self.interpreter.cargo.features = cargo_features
+
ws = self.interpreter.cargo.load_workspace(state.root_subdir)
return RustWorkspace(self.interpreter, ws)