mirror of
https://github.com/embassy-rs/embassy.git
synced 2025-09-27 12:20:37 +00:00
Merge pull request #4046 from outfoxxed/main-macro-executor
executor: add executor selection to #[embassy_executor::main]
This commit is contained in:
commit
1eec964637
@ -173,3 +173,27 @@ pub fn main_std(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
pub fn main_wasm(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
main::run(args.into(), item.into(), &main::ARCH_WASM).into()
|
||||
}
|
||||
|
||||
/// Creates a new `executor` instance and declares an application entry point for an unspecified architecture, spawning the corresponding function body as an async task.
|
||||
///
|
||||
/// The following restrictions apply:
|
||||
///
|
||||
/// * The function must accept exactly 1 parameter, an `embassy_executor::Spawner` handle that it can use to spawn additional tasks.
|
||||
/// * The function must be declared `async`.
|
||||
/// * The function must not use generics.
|
||||
/// * Only a single `main` task may be declared.
|
||||
///
|
||||
/// A user-defined entry macro and executor type must be provided via the `entry` and `executor` arguments of the `main` macro.
|
||||
///
|
||||
/// ## Examples
|
||||
/// Spawning a task:
|
||||
/// ``` rust
|
||||
/// #[embassy_executor::main(entry = "your_hal::entry", executor = "your_hal::Executor")]
|
||||
/// async fn main(_s: embassy_executor::Spawner) {
|
||||
/// // Function body
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
pub fn main_unspecified(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
main::run(args.into(), item.into(), &main::ARCH_UNSPECIFIED).into()
|
||||
}
|
||||
|
@ -16,42 +16,57 @@ enum Flavor {
|
||||
pub(crate) struct Arch {
|
||||
default_entry: Option<&'static str>,
|
||||
flavor: Flavor,
|
||||
executor_required: bool,
|
||||
}
|
||||
|
||||
pub static ARCH_AVR: Arch = Arch {
|
||||
default_entry: Some("avr_device::entry"),
|
||||
flavor: Flavor::Standard,
|
||||
executor_required: false,
|
||||
};
|
||||
|
||||
pub static ARCH_RISCV: Arch = Arch {
|
||||
default_entry: Some("riscv_rt::entry"),
|
||||
flavor: Flavor::Standard,
|
||||
executor_required: false,
|
||||
};
|
||||
|
||||
pub static ARCH_CORTEX_M: Arch = Arch {
|
||||
default_entry: Some("cortex_m_rt::entry"),
|
||||
flavor: Flavor::Standard,
|
||||
executor_required: false,
|
||||
};
|
||||
|
||||
pub static ARCH_SPIN: Arch = Arch {
|
||||
default_entry: None,
|
||||
flavor: Flavor::Standard,
|
||||
executor_required: false,
|
||||
};
|
||||
|
||||
pub static ARCH_STD: Arch = Arch {
|
||||
default_entry: None,
|
||||
flavor: Flavor::Standard,
|
||||
executor_required: false,
|
||||
};
|
||||
|
||||
pub static ARCH_WASM: Arch = Arch {
|
||||
default_entry: Some("wasm_bindgen::prelude::wasm_bindgen(start)"),
|
||||
flavor: Flavor::Wasm,
|
||||
executor_required: false,
|
||||
};
|
||||
|
||||
pub static ARCH_UNSPECIFIED: Arch = Arch {
|
||||
default_entry: None,
|
||||
flavor: Flavor::Standard,
|
||||
executor_required: true,
|
||||
};
|
||||
|
||||
#[derive(Debug, FromMeta, Default)]
|
||||
struct Args {
|
||||
#[darling(default)]
|
||||
entry: Option<String>,
|
||||
#[darling(default)]
|
||||
executor: Option<String>,
|
||||
}
|
||||
|
||||
pub fn run(args: TokenStream, item: TokenStream, arch: &Arch) -> TokenStream {
|
||||
@ -112,9 +127,10 @@ pub fn run(args: TokenStream, item: TokenStream, arch: &Arch) -> TokenStream {
|
||||
error(&mut errors, &f.sig, "main function must have 1 argument: the spawner.");
|
||||
}
|
||||
|
||||
let entry = match args.entry.as_deref().or(arch.default_entry) {
|
||||
None => TokenStream::new(),
|
||||
Some(x) => match TokenStream::from_str(x) {
|
||||
let entry = match (args.entry.as_deref(), arch.default_entry.as_deref()) {
|
||||
(None, None) => TokenStream::new(),
|
||||
(Some(x), _) | (None, Some(x)) if x == "" => TokenStream::new(),
|
||||
(Some(x), _) | (None, Some(x)) => match TokenStream::from_str(x) {
|
||||
Ok(x) => quote!(#[#x]),
|
||||
Err(e) => {
|
||||
error(&mut errors, &f.sig, e);
|
||||
@ -123,6 +139,28 @@ pub fn run(args: TokenStream, item: TokenStream, arch: &Arch) -> TokenStream {
|
||||
},
|
||||
};
|
||||
|
||||
let executor = match (args.executor.as_deref(), arch.executor_required) {
|
||||
(None, true) => {
|
||||
error(
|
||||
&mut errors,
|
||||
&f.sig,
|
||||
"\
|
||||
No architecture selected for embassy-executor. Make sure you've enabled one of the `arch-*` features in your Cargo.toml.
|
||||
|
||||
Alternatively, if you would like to use a custom executor implementation, specify it with the `executor` argument.
|
||||
For example: `#[embassy_executor::main(entry = ..., executor = \"some_crate::Executor\")]",
|
||||
);
|
||||
""
|
||||
}
|
||||
(Some(x), _) => x,
|
||||
(None, _) => "::embassy_executor::Executor",
|
||||
};
|
||||
|
||||
let executor = TokenStream::from_str(executor).unwrap_or_else(|e| {
|
||||
error(&mut errors, &f.sig, e);
|
||||
TokenStream::new()
|
||||
});
|
||||
|
||||
let f_body = f.body;
|
||||
let out = &f.sig.output;
|
||||
|
||||
@ -134,7 +172,7 @@ pub fn run(args: TokenStream, item: TokenStream, arch: &Arch) -> TokenStream {
|
||||
::core::mem::transmute(t)
|
||||
}
|
||||
|
||||
let mut executor = ::embassy_executor::Executor::new();
|
||||
let mut executor = #executor::new();
|
||||
let executor = unsafe { __make_static(&mut executor) };
|
||||
executor.run(|spawner| {
|
||||
spawner.must_spawn(__embassy_main(spawner));
|
||||
@ -144,7 +182,7 @@ pub fn run(args: TokenStream, item: TokenStream, arch: &Arch) -> TokenStream {
|
||||
Flavor::Wasm => (
|
||||
quote!(Result<(), wasm_bindgen::JsValue>),
|
||||
quote! {
|
||||
let executor = ::std::boxed::Box::leak(::std::boxed::Box::new(::embassy_executor::Executor::new()));
|
||||
let executor = ::std::boxed::Box::leak(::std::boxed::Box::new(#executor::new()));
|
||||
|
||||
executor.start(|spawner| {
|
||||
spawner.must_spawn(__embassy_main(spawner));
|
||||
|
@ -44,6 +44,8 @@ mod arch;
|
||||
#[cfg(feature = "_arch")]
|
||||
#[allow(unused_imports)] // don't warn if the module is empty.
|
||||
pub use arch::*;
|
||||
#[cfg(not(feature = "_arch"))]
|
||||
pub use embassy_executor_macros::main_unspecified as main;
|
||||
|
||||
pub mod raw;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user