summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2025-10-29 09:36:33 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2025-12-22 12:01:05 +0100
commit8c88a12e508161244704efc1685d0ea8ddb8fcd5 (patch)
treef007895d8a61f9eddb089743926ceb2fea6731fe
parente6c89d7209ccdf1e6e176a1667e0a9ab045703bd (diff)
downloadmeson-8c88a12e508161244704efc1685d0ea8ddb8fcd5.tar.gz
modules: rust: add package.executable
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--docs/markdown/Rust-module.md27
-rw-r--r--mesonbuild/modules/rust.py47
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."""