Skip to content

Commit db4dc19

Browse files
committed
cargo: populate bin table from src/bin/
Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 97ed037 commit db4dc19

File tree

1 file changed

+52
-2
lines changed

1 file changed

+52
-2
lines changed

mesonbuild/cargo/manifest.py

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,28 @@ def convert(self, v: T.Any, ws_v: T.Any) -> object:
8080
return self.func(v if v is not None else ws_v)
8181

8282

83+
class DictMergeValue(ConvertValue):
84+
"""Merge the incoming array of tables with a dictionary;
85+
a user-provided function maps each table to one of the
86+
entries of the dictionary."""
87+
88+
def __init__(self, func: T.Callable[[T.Any], T.List[object]], key: T.Callable[[T.Any], str], base: T.Mapping[str, object] = None) -> None:
89+
super().__init__(func, base)
90+
self.key = key
91+
92+
def convert(self, v: T.Any, ws_v: T.Any) -> object:
93+
out = self.func(v if v is not None else ws_v)
94+
assert isinstance(out, list) # for mypy
95+
assert isinstance(self.default, dict) # for mypy
96+
97+
d = {self.key(x): x for x in out}
98+
# FIXME: check how auto-discovered items are merged with Cargo.toml
99+
for k, v in self.default.items():
100+
if k not in d:
101+
d[k] = v
102+
return d
103+
104+
83105
def _raw_to_dataclass(raw: T.Mapping[str, object], cls: T.Type[_DI], msg: str,
84106
raw_from_workspace: T.Optional[T.Mapping[str, object]] = None,
85107
ignored_fields: T.Optional[T.List[str]] = None,
@@ -491,7 +513,7 @@ class Manifest:
491513
dev_dependencies: T.Dict[str, Dependency] = dataclasses.field(default_factory=dict)
492514
build_dependencies: T.Dict[str, Dependency] = dataclasses.field(default_factory=dict)
493515
lib: T.Optional[Library] = None
494-
bin: T.List[Binary] = dataclasses.field(default_factory=list)
516+
bin: T.Dict[str, Binary] = dataclasses.field(default_factory=dict)
495517
test: T.List[Test] = dataclasses.field(default_factory=list)
496518
bench: T.List[Benchmark] = dataclasses.field(default_factory=list)
497519
example: T.List[Example] = dataclasses.field(default_factory=list)
@@ -516,6 +538,32 @@ def from_raw(cls, raw: raw.Manifest, path: str, workspace: T.Optional[Workspace]
516538
if pkg.autolib and os.path.exists(os.path.join(path, 'src/lib.rs')):
517539
autolib = Library.from_raw({}, pkg)
518540

541+
def _discover_targets(subdir: str) -> T.Generator[T.Tuple[str, str], None, None]:
542+
"""Discover .rs files in a subdirectory and yield (name, path) tuples."""
543+
target_dir = os.path.join(path, subdir)
544+
if os.path.isdir(target_dir):
545+
for entry in os.listdir(target_dir):
546+
if entry.endswith('.rs'):
547+
target_name = entry[:-3] # Remove .rs extension
548+
yield target_name, f'{subdir}/{entry}'
549+
550+
autobins: T.Dict[str, Binary] = {}
551+
if pkg.autobins:
552+
# Check for default binary (src/main.rs)
553+
if os.path.exists(os.path.join(path, 'src/main.rs')):
554+
autobins[pkg.name] = Binary.from_raw({'name': pkg.name, 'path': 'src/main.rs'}, pkg)
555+
# Add additional binaries from src/bin/
556+
for bin_name, bin_path in _discover_targets('src/bin'):
557+
autobins[bin_name] = Binary.from_raw({'name': bin_name, 'path': bin_path}, pkg)
558+
559+
# Check for additional binaries in src/bin/
560+
bin_dir = os.path.join(path, 'src/bin')
561+
if os.path.isdir(bin_dir):
562+
for entry in os.listdir(bin_dir):
563+
if entry.endswith('.rs'):
564+
bin_name = entry[:-3] # Remove .rs extension
565+
autobins[bin_name] = Binary.from_raw({'name': bin_name, 'path': f'src/bin/{entry}'}, pkg)
566+
519567
def dependencies_from_raw(x: T.Dict[str, T.Any]) -> T.Dict[str, Dependency]:
520568
return {k: Dependency.from_raw(k, v, member_path, workspace) for k, v in x.items()}
521569

@@ -528,7 +576,9 @@ def dependencies_from_raw(x: T.Dict[str, T.Any]) -> T.Dict[str, Dependency]:
528576
build_dependencies=ConvertValue(dependencies_from_raw),
529577
lints=ConvertValue(Lint.from_raw),
530578
lib=ConvertValue(lambda x: Library.from_raw(x, pkg), default=autolib),
531-
bin=ConvertValue(lambda x: [Binary.from_raw(b, pkg) for b in x]),
579+
bin=DictMergeValue(lambda x: [Binary.from_raw(b, pkg) for b in x],
580+
lambda x: x.name,
581+
base=autobins),
532582
test=ConvertValue(lambda x: [Test.from_raw(b, pkg) for b in x]),
533583
bench=ConvertValue(lambda x: [Benchmark.from_raw(b, pkg) for b in x]),
534584
example=ConvertValue(lambda x: [Example.from_raw(b, pkg) for b in x]),

0 commit comments

Comments
 (0)