diff options
| author | Paolo Bonzini <pbonzini@redhat.com> | 2025-10-29 09:36:33 +0100 |
|---|---|---|
| committer | Paolo Bonzini <pbonzini@redhat.com> | 2025-12-22 12:01:05 +0100 |
| commit | 8c88a12e508161244704efc1685d0ea8ddb8fcd5 (patch) | |
| tree | f007895d8a61f9eddb089743926ceb2fea6731fe | |
| parent | e6c89d7209ccdf1e6e176a1667e0a9ab045703bd (diff) | |
| download | meson-8c88a12e508161244704efc1685d0ea8ddb8fcd5.tar.gz | |
modules: rust: add package.executable
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
| -rw-r--r-- | docs/markdown/Rust-module.md | 27 | ||||
| -rw-r--r-- | mesonbuild/modules/rust.py | 47 |
2 files changed, 66 insertions, 8 deletions
diff --git a/docs/markdown/Rust-module.md b/docs/markdown/Rust-module.md index 7ad9f1cfd..50e4854ca 100644 --- a/docs/markdown/Rust-module.md +++ b/docs/markdown/Rust-module.md @@ -274,12 +274,7 @@ Example usage: rustmod = import('rust') cargo_ws = rustmod.workspace() pkg = cargo_ws.package() - -executable('my_app', 'src/main.rs', - dependencies: pkg.dependencies(), - rust_args: pkg.rust_args(), - rust_dependency_map: pkg.rust_dependency_map(), -) +pkg.executable(install: true) ``` ### workspace.subproject() @@ -411,6 +406,26 @@ Builds a proc-macro crate for a workspace package. Accepts all keyword arguments from [[shared_library]]. +#### package.executable() + +```meson +exe = pkg.executable([target_name], [sources], ...) +``` + +Builds an executable target for a workspace package. The method requires that the +package has at least one `bin` section defined in its `Cargo.toml` file, +or one binary discovered from the contents of the file system. + +Positional arguments: +- `target_name`: (`str`, optional) Name of the binary target to build. If the package + has multiple `bin` sections in `Cargo.toml`, this argument is required and must + match one of the binary names. If omitted and there's only one binary, that binary + will be built automatically. +- `sources`: (`StructuredSources`, optional) Source files for the executable. If omitted, + uses the path specified in the corresponding `bin` section of `Cargo.toml`. + +Accepts all keyword arguments from [[executable]]. + ### Subprojects only #### subproject.dependency() diff --git a/mesonbuild/modules/rust.py b/mesonbuild/modules/rust.py index 137d64099..a30abf8e4 100644 --- a/mesonbuild/modules/rust.py +++ b/mesonbuild/modules/rust.py @@ -20,7 +20,7 @@ from ..dependencies import Dependency 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, - LIBRARY_KWS, _BASE_LANG_KW + EXECUTABLE_KWS, LIBRARY_KWS, _BASE_LANG_KW ) from ..interpreterbase import ContainerTypeInfo, InterpreterException, KwargInfo, typed_kwargs, typed_pos_args, noKwargs, noPosargs, permittedKwargs from ..interpreter.interpreterobjects import Doctest @@ -76,6 +76,11 @@ if T.TYPE_CHECKING: class FuncDependency(TypedDict): rust_abi: T.Optional[RUST_ABI] + class RustPackageExecutable(_kwargs.Executable): + dependencies: T.List[T.Union[Dependency, ExternalLibrary]] + link_with: T.List[LibTypes] + link_whole: T.List[LibTypes] + class RustPackageLibrary(_kwargs.Library): dependencies: T.List[T.Union[Dependency, ExternalLibrary]] link_with: T.List[LibTypes] @@ -242,6 +247,7 @@ class RustPackage(RustCrate): 'dependencies': self.dependencies_method, 'library': self.library_method, 'proc_macro': self.proc_macro_method, + 'executable': self.executable_method, }) @noPosargs @@ -289,7 +295,7 @@ class RustPackage(RustCrate): raise MesonException(f"{name} only accepts one StructuredSources parameter") return None, args[0] - def merge_kw_args(self, state: ModuleState, kwargs: RustPackageLibrary) -> None: + def merge_kw_args(self, state: ModuleState, kwargs: T.Union[RustPackageExecutable, RustPackageLibrary]) -> None: deps = kwargs['dependencies'] kwargs['dependencies'] = self.dependencies_method(state, [], {}) kwargs['dependencies'].extend(deps) @@ -394,6 +400,43 @@ class RustPackage(RustCrate): raise MesonException("not a procedural macro crate") return self._proc_macro_method(state, args, kwargs) + @typed_pos_args('package.executable', optargs=[(str, StructuredSources), StructuredSources]) + @typed_kwargs( + 'package.executable', + *EXECUTABLE_KWS, + DEPENDENCIES_KW, + LINK_WITH_KW, + LINK_WHOLE_KW, + _BASE_LANG_KW.evolve(name='rust_args'), + ) + def executable_method(self, state: 'ModuleState', args: T.Tuple[ + T.Optional[T.Union[str, StructuredSources]], + T.Optional[StructuredSources]], kwargs: RustPackageExecutable) -> Executable: + """Builds executable targets from workspace bins.""" + tgt_args = self.validate_pos_args('package.executable', args) + if not self.package.manifest.bin: + raise MesonException("no [[bin]] section in Cargo package") + + sources: T.Union[StructuredSources, str] + tgt_name, sources = tgt_args + # If there's more than one binary, the first argument must be specified + # and must be one of the keys in pkg.bin + if not tgt_name: + if len(self.package.manifest.bin) > 1: + raise MesonException("Package has multiple binaries, you must specify which one to build as the first argument") + # Single binary, use it + tgt_name = next(iter(self.package.manifest.bin.keys())) + else: + if tgt_name not in self.package.manifest.bin: + raise MesonException(f"Binary '{tgt_name}' not found.") + + if not sources: + sources = self.package.manifest.bin[tgt_name].path + + exe_args: T.Tuple[str, SourcesVarargsType] = (tgt_name, [sources]) + self.merge_kw_args(state, kwargs) + return state._interpreter.build_target(state.current_node, exe_args, kwargs, Executable) + class RustSubproject(RustCrate): """Represents a Cargo subproject.""" |
