Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 38 additions & 6 deletions mesonbuild/cargo/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -316,11 +316,11 @@ def features(self, value: T.List[str]) -> None:
def get_build_def_files(self) -> T.List[str]:
return self.build_def_files

def load_workspace(self, subdir: str) -> WorkspaceState:
def load_workspace(self, subdir: str, extra_members: T.Optional[T.List[str]]) -> WorkspaceState:
"""Load the root Cargo.toml package and prepare it with features and dependencies."""
subdir = os.path.normpath(subdir)
manifest, cached = self._load_manifest(subdir)
ws = self._get_workspace(manifest, subdir, False)
ws = self._get_workspace(manifest, subdir, extra_members, False)
if not cached:
self._prepare_entry_point(ws)
return ws
Expand Down Expand Up @@ -356,7 +356,7 @@ def interpret(self, subdir: str, project_root: T.Optional[str] = None) -> mparse
assert isinstance(manifest, Manifest)
return self.interpret_package(manifest, build, subdir, project_root)
else:
ws = self.load_workspace(subdir)
ws = self.load_workspace(subdir, None)
return self.interpret_workspace(ws, build, subdir)

def interpret_package(self, manifest: Manifest, build: builder.Builder, subdir: str, project_root: str) -> mparser.CodeBlockNode:
Expand Down Expand Up @@ -447,7 +447,28 @@ def _add_workspace_member(self, manifest_: Manifest, ws: WorkspaceState, m: str)
else:
ws.packages[m] = PackageState(manifest_, ws_subdir=ws.subdir, ws_member=m, downloaded=ws.downloaded)

def _get_workspace(self, manifest: T.Union[Workspace, Manifest], subdir: str, downloaded: bool) -> WorkspaceState:
# Returns the expansion of a glob expression with a single
# cannonical result, otherwise (multiple results) returns None.
@staticmethod
def _unglobify(pat: str) -> T.Optional[str]:
ret = ''
iterator = iter(pat)
for char in iterator:
if char in {'?', '*'}:
return None
elif char == '[':
try:
ret += next(iterator)
if next(iterator) != ']':
return None
except StopIteration:
mlog.warning(f'Encountered invalid glob pattern "{pat}"')
return None
else:
ret += char
return ret

def _get_workspace(self, manifest: T.Union[Workspace, Manifest], subdir: str, extra_members: T.Optional[T.List[str]], downloaded: bool) -> WorkspaceState:
ws = self.workspaces.get(subdir)
if ws:
return ws
Expand All @@ -456,7 +477,18 @@ def _get_workspace(self, manifest: T.Union[Workspace, Manifest], subdir: str, do
ws = WorkspaceState(workspace, subdir, downloaded=downloaded)
if workspace.root_package:
self._add_workspace_member(workspace.root_package, ws, '.')
for m in workspace.members:

members = [self._unglobify(entry) for entry in workspace.members]
if None in members:
if extra_members is None:
mlog.warning('Cargo workspace contains glob members. Please specify them manually using the \'extra_members\' kwarg')
members = [member for member in members if member is not None]
if extra_members is not None:
members += extra_members
# set ws default members if not set
if workspace.default_members is None:
workspace.default_members = members
for m in members:
self._load_workspace_member(ws, m)
self.workspaces[subdir] = ws
return ws
Expand Down Expand Up @@ -530,7 +562,7 @@ def _fetch_package_from_subproject(self, package_name: str, subp_name: str) -> P
subp_name in self.environment.wrap_resolver.wraps and \
self.environment.wrap_resolver.wraps[subp_name].type is not None

ws = self._get_workspace(manifest, subdir, downloaded=downloaded)
ws = self._get_workspace(manifest, subdir, None, downloaded=downloaded)
member = ws.packages_to_member[package_name]
pkg = self._require_workspace_member(ws, member)
pkg.subproject_name = subp_name
Expand Down
2 changes: 1 addition & 1 deletion mesonbuild/cargo/manifest.py
Original file line number Diff line number Diff line change
Expand Up @@ -618,7 +618,7 @@ def from_raw(cls, raw: raw.Manifest, path: str) -> Self:
if 'package' in raw:
ws.root_package = Manifest.from_raw(raw, path, ws, '.')
if not ws.default_members:
ws.default_members = ['.'] if ws.root_package else ws.members
ws.default_members = ['.'] if ws.root_package else None
return ws


Expand Down
9 changes: 8 additions & 1 deletion mesonbuild/modules/rust.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ class FuncBindgen(TypedDict):
class FuncWorkspace(TypedDict):
default_features: T.Optional[bool]
features: T.List[str]
extra_members: T.List[str]

class FuncDependency(TypedDict):
rust_abi: T.Optional[RUST_ABI]
Expand Down Expand Up @@ -996,6 +997,12 @@ def to_system_dependency(self, state: ModuleState, args: T.Tuple[Dependency, T.O
default=None,
listify=True,
),
KwargInfo(
'extra_members',
(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
Expand All @@ -1018,7 +1025,7 @@ def workspace(self, state: ModuleState, args: T.List, kwargs: FuncWorkspace) ->
cargo_features.extend(features)
self.interpreter.cargo.features = cargo_features

ws = self.interpreter.cargo.load_workspace(state.root_subdir)
ws = self.interpreter.cargo.load_workspace(state.root_subdir, kwargs['extra_members'])

# Cargo projects may not have a subprojects directory, because
# dependencies are declared in Cargo.toml rather than .wrap files.
Expand Down
15 changes: 15 additions & 0 deletions test cases/rust/43 extra_members/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions test cases/rust/43 extra_members/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[workspace]
resolver = "3"
members = [
"subdir/*",
"g[*]mma"
]
4 changes: 4 additions & 0 deletions test cases/rust/43 extra_members/g*mma/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[package]
name = "gamma"
version = "0.0.0"
edition = "2021"
1 change: 1 addition & 0 deletions test cases/rust/43 extra_members/g*mma/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main() {}
12 changes: 12 additions & 0 deletions test cases/rust/43 extra_members/meson.build
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
project('rust ws extra_members', 'rust',
meson_version: '>= 1.11'
)

cargo = import('rust').workspace(extra_members: ['subdir/alpha'])

if 'beta' in cargo.packages()
error('Unexpectedly resolved glob member')
endif

cargo.package('alpha').executable()
cargo.package('gamma').executable()
4 changes: 4 additions & 0 deletions test cases/rust/43 extra_members/subdir/alpha/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[package]
name = "alpha"
version = "0.0.0"
edition = "2021"
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
fn main() {}
4 changes: 4 additions & 0 deletions test cases/rust/43 extra_members/subdir/beta/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[package]
name = "beta"
version = "0.0.0"
edition = "2021"
3 changes: 3 additions & 0 deletions test cases/rust/43 extra_members/subdir/beta/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
#error "Intentionally not building"
}
Loading