summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2025-10-28 16:59:23 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2025-12-22 12:01:05 +0100
commite6c89d7209ccdf1e6e176a1667e0a9ab045703bd (patch)
treefc9a5347c7dd497d5ac21c4166a07ff4d6cb5efa
parent8cd91e1eb4c76e79eba589674af08229b1e02f90 (diff)
downloadmeson-e6c89d7209ccdf1e6e176a1667e0a9ab045703bd.tar.gz
cargo: populate bin table from src/bin/
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--mesonbuild/cargo/manifest.py54
1 files changed, 52 insertions, 2 deletions
diff --git a/mesonbuild/cargo/manifest.py b/mesonbuild/cargo/manifest.py
index 2c3eeb3e0..125319972 100644
--- a/mesonbuild/cargo/manifest.py
+++ b/mesonbuild/cargo/manifest.py
@@ -79,6 +79,28 @@ class ConvertValue(DefaultValue):
return self.func(v if v is not None else ws_v)
+class DictMergeValue(ConvertValue):
+ """Merge the incoming array of tables with a dictionary;
+ a user-provided function maps each table to one of the
+ entries of the dictionary."""
+
+ def __init__(self, func: T.Callable[[T.Any], T.List[object]], key: T.Callable[[T.Any], str], base: T.Mapping[str, object] = None) -> None:
+ super().__init__(func, base)
+ self.key = key
+
+ def convert(self, v: T.Any, ws_v: T.Any) -> object:
+ out = self.func(v if v is not None else ws_v)
+ assert isinstance(out, list) # for mypy
+ assert isinstance(self.default, dict) # for mypy
+
+ d = {self.key(x): x for x in out}
+ # FIXME: check how auto-discovered items are merged with Cargo.toml
+ for k, v in self.default.items():
+ if k not in d:
+ d[k] = v
+ return d
+
+
def _raw_to_dataclass(raw: T.Mapping[str, object], cls: T.Type[_DI], msg: str,
raw_from_workspace: T.Optional[T.Mapping[str, object]] = None,
ignored_fields: T.Optional[T.List[str]] = None,
@@ -490,7 +512,7 @@ class Manifest:
dev_dependencies: T.Dict[str, Dependency] = dataclasses.field(default_factory=dict)
build_dependencies: T.Dict[str, Dependency] = dataclasses.field(default_factory=dict)
lib: T.Optional[Library] = None
- bin: T.List[Binary] = dataclasses.field(default_factory=list)
+ bin: T.Dict[str, Binary] = dataclasses.field(default_factory=dict)
test: T.List[Test] = dataclasses.field(default_factory=list)
bench: T.List[Benchmark] = dataclasses.field(default_factory=list)
example: T.List[Example] = dataclasses.field(default_factory=list)
@@ -515,6 +537,32 @@ class Manifest:
if pkg.autolib and os.path.exists(os.path.join(path, 'src/lib.rs')):
autolib = Library.from_raw({}, pkg)
+ def _discover_targets(subdir: str) -> T.Generator[T.Tuple[str, str], None, None]:
+ """Discover .rs files in a subdirectory and yield (name, path) tuples."""
+ target_dir = os.path.join(path, subdir)
+ if os.path.isdir(target_dir):
+ for entry in os.listdir(target_dir):
+ if entry.endswith('.rs'):
+ target_name = entry[:-3] # Remove .rs extension
+ yield target_name, f'{subdir}/{entry}'
+
+ autobins: T.Dict[str, Binary] = {}
+ if pkg.autobins:
+ # Check for default binary (src/main.rs)
+ if os.path.exists(os.path.join(path, 'src/main.rs')):
+ autobins[pkg.name] = Binary.from_raw({'name': pkg.name, 'path': 'src/main.rs'}, pkg)
+ # Add additional binaries from src/bin/
+ for bin_name, bin_path in _discover_targets('src/bin'):
+ autobins[bin_name] = Binary.from_raw({'name': bin_name, 'path': bin_path}, pkg)
+
+ # Check for additional binaries in src/bin/
+ bin_dir = os.path.join(path, 'src/bin')
+ if os.path.isdir(bin_dir):
+ for entry in os.listdir(bin_dir):
+ if entry.endswith('.rs'):
+ bin_name = entry[:-3] # Remove .rs extension
+ autobins[bin_name] = Binary.from_raw({'name': bin_name, 'path': f'src/bin/{entry}'}, pkg)
+
def dependencies_from_raw(x: T.Dict[str, T.Any]) -> T.Dict[str, Dependency]:
return {k: Dependency.from_raw(k, v, member_path, workspace) for k, v in x.items()}
@@ -527,7 +575,9 @@ class Manifest:
build_dependencies=ConvertValue(dependencies_from_raw),
lints=ConvertValue(Lint.from_raw),
lib=ConvertValue(lambda x: Library.from_raw(x, pkg), default=autolib),
- bin=ConvertValue(lambda x: [Binary.from_raw(b, pkg) for b in x]),
+ bin=DictMergeValue(lambda x: [Binary.from_raw(b, pkg) for b in x],
+ lambda x: x.name,
+ base=autobins),
test=ConvertValue(lambda x: [Test.from_raw(b, pkg) for b in x]),
bench=ConvertValue(lambda x: [Benchmark.from_raw(b, pkg) for b in x]),
example=ConvertValue(lambda x: [Example.from_raw(b, pkg) for b in x]),