diff options
| author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-11-23 13:21:59 +0000 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-11-23 13:21:59 +0000 |
| commit | a4f9e7cbcc8cb3ff679b4677a85a06d514b0c465 (patch) | |
| tree | acb48252c134b900eca51299995e84a95fbd0cd3 | |
| parent | de95ab264d8ee2bf5ba9c3615ecb1b44e3940694 (diff) | |
| parent | 04a7d976733e021395ff26e26dfa983e67b773a0 (diff) | |
Merge #1071
1071: refactor: autodetect macro variant r=Dirbaio a=lulf
Apply heuristics using target_arch, target_os and target_family to determine which variant of the entry point to use.
Co-authored-by: Ulf Lilleengen <[email protected]>
| -rw-r--r-- | embassy-executor/Cargo.toml | 5 | ||||
| -rw-r--r-- | embassy-executor/src/lib.rs | 10 | ||||
| -rw-r--r-- | embassy-macros/Cargo.toml | 4 | ||||
| -rw-r--r-- | embassy-macros/src/lib.rs | 81 | ||||
| -rw-r--r-- | embassy-macros/src/macros/main.rs | 98 |
5 files changed, 140 insertions, 58 deletions
diff --git a/embassy-executor/Cargo.toml b/embassy-executor/Cargo.toml index 45b0955bf..6fa1dd7fb 100644 --- a/embassy-executor/Cargo.toml +++ b/embassy-executor/Cargo.toml | |||
| @@ -29,9 +29,8 @@ flavors = [ | |||
| 29 | 29 | ||
| 30 | [features] | 30 | [features] |
| 31 | default = [] | 31 | default = [] |
| 32 | std = ["embassy-macros/std", "critical-section/std"] | 32 | std = ["critical-section/std"] |
| 33 | wasm = ["dep:wasm-bindgen", "dep:js-sys", "embassy-macros/wasm"] | 33 | wasm = ["dep:wasm-bindgen", "dep:js-sys"] |
| 34 | riscv = ["embassy-macros/riscv"] | ||
| 35 | 34 | ||
| 36 | # Enable nightly-only features | 35 | # Enable nightly-only features |
| 37 | nightly = [] | 36 | nightly = [] |
diff --git a/embassy-executor/src/lib.rs b/embassy-executor/src/lib.rs index e4cbd04b9..4c7e2f4cd 100644 --- a/embassy-executor/src/lib.rs +++ b/embassy-executor/src/lib.rs | |||
| @@ -8,18 +8,22 @@ | |||
| 8 | pub(crate) mod fmt; | 8 | pub(crate) mod fmt; |
| 9 | 9 | ||
| 10 | #[cfg(feature = "nightly")] | 10 | #[cfg(feature = "nightly")] |
| 11 | pub use embassy_macros::{main, task}; | 11 | pub use embassy_macros::task; |
| 12 | 12 | ||
| 13 | cfg_if::cfg_if! { | 13 | cfg_if::cfg_if! { |
| 14 | if #[cfg(cortex_m)] { | 14 | if #[cfg(cortex_m)] { |
| 15 | #[path="arch/cortex_m.rs"] | 15 | #[path="arch/cortex_m.rs"] |
| 16 | mod arch; | 16 | mod arch; |
| 17 | pub use arch::*; | 17 | pub use arch::*; |
| 18 | #[cfg(feature = "nightly")] | ||
| 19 | pub use embassy_macros::main_cortex_m as main; | ||
| 18 | } | 20 | } |
| 19 | else if #[cfg(target_arch="riscv32")] { | 21 | else if #[cfg(target_arch="riscv32")] { |
| 20 | #[path="arch/riscv32.rs"] | 22 | #[path="arch/riscv32.rs"] |
| 21 | mod arch; | 23 | mod arch; |
| 22 | pub use arch::*; | 24 | pub use arch::*; |
| 25 | #[cfg(feature = "nightly")] | ||
| 26 | pub use embassy_macros::main_riscv as main; | ||
| 23 | } | 27 | } |
| 24 | else if #[cfg(all(target_arch="xtensa", feature = "nightly"))] { | 28 | else if #[cfg(all(target_arch="xtensa", feature = "nightly"))] { |
| 25 | #[path="arch/xtensa.rs"] | 29 | #[path="arch/xtensa.rs"] |
| @@ -30,11 +34,15 @@ cfg_if::cfg_if! { | |||
| 30 | #[path="arch/wasm.rs"] | 34 | #[path="arch/wasm.rs"] |
| 31 | mod arch; | 35 | mod arch; |
| 32 | pub use arch::*; | 36 | pub use arch::*; |
| 37 | #[cfg(feature = "nightly")] | ||
| 38 | pub use embassy_macros::main_wasm as main; | ||
| 33 | } | 39 | } |
| 34 | else if #[cfg(feature="std")] { | 40 | else if #[cfg(feature="std")] { |
| 35 | #[path="arch/std.rs"] | 41 | #[path="arch/std.rs"] |
| 36 | mod arch; | 42 | mod arch; |
| 37 | pub use arch::*; | 43 | pub use arch::*; |
| 44 | #[cfg(feature = "nightly")] | ||
| 45 | pub use embassy_macros::main_std as main; | ||
| 38 | } | 46 | } |
| 39 | } | 47 | } |
| 40 | 48 | ||
diff --git a/embassy-macros/Cargo.toml b/embassy-macros/Cargo.toml index 9b83771c8..5c612c997 100644 --- a/embassy-macros/Cargo.toml +++ b/embassy-macros/Cargo.toml | |||
| @@ -21,9 +21,5 @@ proc-macro2 = "1.0.29" | |||
| 21 | proc-macro = true | 21 | proc-macro = true |
| 22 | 22 | ||
| 23 | [features] | 23 | [features] |
| 24 | std = [] | ||
| 25 | wasm = [] | ||
| 26 | riscv = [] | ||
| 27 | |||
| 28 | # Enabling this cause interrupt::take! to require embassy-executor | 24 | # Enabling this cause interrupt::take! to require embassy-executor |
| 29 | rtos-trace-interrupt = [] | 25 | rtos-trace-interrupt = [] |
diff --git a/embassy-macros/src/lib.rs b/embassy-macros/src/lib.rs index f5df2a269..d2c696c72 100644 --- a/embassy-macros/src/lib.rs +++ b/embassy-macros/src/lib.rs | |||
| @@ -45,7 +45,7 @@ pub fn task(args: TokenStream, item: TokenStream) -> TokenStream { | |||
| 45 | task::run(args, f).unwrap_or_else(|x| x).into() | 45 | task::run(args, f).unwrap_or_else(|x| x).into() |
| 46 | } | 46 | } |
| 47 | 47 | ||
| 48 | /// Creates a new `executor` instance and declares an application entry point spawning the corresponding function body as an async task. | 48 | /// Creates a new `executor` instance and declares an application entry point for Cortex-M spawning the corresponding function body as an async task. |
| 49 | /// | 49 | /// |
| 50 | /// The following restrictions apply: | 50 | /// The following restrictions apply: |
| 51 | /// | 51 | /// |
| @@ -64,10 +64,85 @@ pub fn task(args: TokenStream, item: TokenStream) -> TokenStream { | |||
| 64 | /// } | 64 | /// } |
| 65 | /// ``` | 65 | /// ``` |
| 66 | #[proc_macro_attribute] | 66 | #[proc_macro_attribute] |
| 67 | pub fn main(args: TokenStream, item: TokenStream) -> TokenStream { | 67 | pub fn main_cortex_m(args: TokenStream, item: TokenStream) -> TokenStream { |
| 68 | let args = syn::parse_macro_input!(args as syn::AttributeArgs); | 68 | let args = syn::parse_macro_input!(args as syn::AttributeArgs); |
| 69 | let f = syn::parse_macro_input!(item as syn::ItemFn); | 69 | let f = syn::parse_macro_input!(item as syn::ItemFn); |
| 70 | main::run(args, f).unwrap_or_else(|x| x).into() | 70 | main::run(args, f, main::cortex_m()).unwrap_or_else(|x| x).into() |
| 71 | } | ||
| 72 | |||
| 73 | /// Creates a new `executor` instance and declares an application entry point for RISC-V spawning the corresponding function body as an async task. | ||
| 74 | /// | ||
| 75 | /// The following restrictions apply: | ||
| 76 | /// | ||
| 77 | /// * The function must accept exactly 1 parameter, an `embassy_executor::Spawner` handle that it can use to spawn additional tasks. | ||
| 78 | /// * The function must be declared `async`. | ||
| 79 | /// * The function must not use generics. | ||
| 80 | /// * Only a single `main` task may be declared. | ||
| 81 | /// | ||
| 82 | /// ## Examples | ||
| 83 | /// Spawning a task: | ||
| 84 | /// | ||
| 85 | /// ``` rust | ||
| 86 | /// #[embassy_executor::main] | ||
| 87 | /// async fn main(_s: embassy_executor::Spawner) { | ||
| 88 | /// // Function body | ||
| 89 | /// } | ||
| 90 | /// ``` | ||
| 91 | #[proc_macro_attribute] | ||
| 92 | pub fn main_riscv(args: TokenStream, item: TokenStream) -> TokenStream { | ||
| 93 | let args = syn::parse_macro_input!(args as syn::AttributeArgs); | ||
| 94 | let f = syn::parse_macro_input!(item as syn::ItemFn); | ||
| 95 | main::run(args, f, main::riscv()).unwrap_or_else(|x| x).into() | ||
| 96 | } | ||
| 97 | |||
| 98 | /// Creates a new `executor` instance and declares an application entry point for STD spawning the corresponding function body as an async task. | ||
| 99 | /// | ||
| 100 | /// The following restrictions apply: | ||
| 101 | /// | ||
| 102 | /// * The function must accept exactly 1 parameter, an `embassy_executor::Spawner` handle that it can use to spawn additional tasks. | ||
| 103 | /// * The function must be declared `async`. | ||
| 104 | /// * The function must not use generics. | ||
| 105 | /// * Only a single `main` task may be declared. | ||
| 106 | /// | ||
| 107 | /// ## Examples | ||
| 108 | /// Spawning a task: | ||
| 109 | /// | ||
| 110 | /// ``` rust | ||
| 111 | /// #[embassy_executor::main] | ||
| 112 | /// async fn main(_s: embassy_executor::Spawner) { | ||
| 113 | /// // Function body | ||
| 114 | /// } | ||
| 115 | /// ``` | ||
| 116 | #[proc_macro_attribute] | ||
| 117 | pub fn main_std(args: TokenStream, item: TokenStream) -> TokenStream { | ||
| 118 | let args = syn::parse_macro_input!(args as syn::AttributeArgs); | ||
| 119 | let f = syn::parse_macro_input!(item as syn::ItemFn); | ||
| 120 | main::run(args, f, main::std()).unwrap_or_else(|x| x).into() | ||
| 121 | } | ||
| 122 | |||
| 123 | /// Creates a new `executor` instance and declares an application entry point for WASM spawning the corresponding function body as an async task. | ||
| 124 | /// | ||
| 125 | /// The following restrictions apply: | ||
| 126 | /// | ||
| 127 | /// * The function must accept exactly 1 parameter, an `embassy_executor::Spawner` handle that it can use to spawn additional tasks. | ||
| 128 | /// * The function must be declared `async`. | ||
| 129 | /// * The function must not use generics. | ||
| 130 | /// * Only a single `main` task may be declared. | ||
| 131 | /// | ||
| 132 | /// ## Examples | ||
| 133 | /// Spawning a task: | ||
| 134 | /// | ||
| 135 | /// ``` rust | ||
| 136 | /// #[embassy_executor::main] | ||
| 137 | /// async fn main(_s: embassy_executor::Spawner) { | ||
| 138 | /// // Function body | ||
| 139 | /// } | ||
| 140 | /// ``` | ||
| 141 | #[proc_macro_attribute] | ||
| 142 | pub fn main_wasm(args: TokenStream, item: TokenStream) -> TokenStream { | ||
| 143 | let args = syn::parse_macro_input!(args as syn::AttributeArgs); | ||
| 144 | let f = syn::parse_macro_input!(item as syn::ItemFn); | ||
| 145 | main::run(args, f, main::wasm()).unwrap_or_else(|x| x).into() | ||
| 71 | } | 146 | } |
| 72 | 147 | ||
| 73 | #[proc_macro_attribute] | 148 | #[proc_macro_attribute] |
diff --git a/embassy-macros/src/macros/main.rs b/embassy-macros/src/macros/main.rs index 54806847c..18f7c36c4 100644 --- a/embassy-macros/src/macros/main.rs +++ b/embassy-macros/src/macros/main.rs | |||
| @@ -7,31 +7,34 @@ use crate::util::ctxt::Ctxt; | |||
| 7 | #[derive(Debug, FromMeta)] | 7 | #[derive(Debug, FromMeta)] |
| 8 | struct Args {} | 8 | struct Args {} |
| 9 | 9 | ||
| 10 | pub fn run(args: syn::AttributeArgs, f: syn::ItemFn) -> Result<TokenStream, TokenStream> { | 10 | pub fn riscv() -> TokenStream { |
| 11 | #[allow(unused_variables)] | 11 | quote! { |
| 12 | let args = Args::from_list(&args).map_err(|e| e.write_errors())?; | 12 | #[riscv_rt::entry] |
| 13 | 13 | fn main() -> ! { | |
| 14 | let fargs = f.sig.inputs.clone(); | 14 | let mut executor = ::embassy_executor::Executor::new(); |
| 15 | 15 | let executor = unsafe { __make_static(&mut executor) }; | |
| 16 | let ctxt = Ctxt::new(); | 16 | executor.run(|spawner| { |
| 17 | 17 | spawner.must_spawn(__embassy_main(spawner)); | |
| 18 | if f.sig.asyncness.is_none() { | 18 | }) |
| 19 | ctxt.error_spanned_by(&f.sig, "main function must be async"); | 19 | } |
| 20 | } | ||
| 21 | if !f.sig.generics.params.is_empty() { | ||
| 22 | ctxt.error_spanned_by(&f.sig, "main function must not be generic"); | ||
| 23 | } | 20 | } |
| 21 | } | ||
| 24 | 22 | ||
| 25 | if fargs.len() != 1 { | 23 | pub fn cortex_m() -> TokenStream { |
| 26 | ctxt.error_spanned_by(&f.sig, "main function must have 1 argument: the spawner."); | 24 | quote! { |
| 25 | #[cortex_m_rt::entry] | ||
| 26 | fn main() -> ! { | ||
| 27 | let mut executor = ::embassy_executor::Executor::new(); | ||
| 28 | let executor = unsafe { __make_static(&mut executor) }; | ||
| 29 | executor.run(|spawner| { | ||
| 30 | spawner.must_spawn(__embassy_main(spawner)); | ||
| 31 | }) | ||
| 32 | } | ||
| 27 | } | 33 | } |
| 34 | } | ||
| 28 | 35 | ||
| 29 | ctxt.check()?; | 36 | pub fn wasm() -> TokenStream { |
| 30 | 37 | quote! { | |
| 31 | let f_body = f.block; | ||
| 32 | |||
| 33 | #[cfg(feature = "wasm")] | ||
| 34 | let main = quote! { | ||
| 35 | #[wasm_bindgen::prelude::wasm_bindgen(start)] | 38 | #[wasm_bindgen::prelude::wasm_bindgen(start)] |
| 36 | pub fn main() -> Result<(), wasm_bindgen::JsValue> { | 39 | pub fn main() -> Result<(), wasm_bindgen::JsValue> { |
| 37 | static EXECUTOR: ::embassy_executor::_export::StaticCell<::embassy_executor::Executor> = ::embassy_executor::_export::StaticCell::new(); | 40 | static EXECUTOR: ::embassy_executor::_export::StaticCell<::embassy_executor::Executor> = ::embassy_executor::_export::StaticCell::new(); |
| @@ -43,10 +46,11 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn) -> Result<TokenStream, Toke | |||
| 43 | 46 | ||
| 44 | Ok(()) | 47 | Ok(()) |
| 45 | } | 48 | } |
| 46 | }; | 49 | } |
| 50 | } | ||
| 47 | 51 | ||
| 48 | #[cfg(all(feature = "std", not(feature = "wasm"), not(feature = "riscv")))] | 52 | pub fn std() -> TokenStream { |
| 49 | let main = quote! { | 53 | quote! { |
| 50 | fn main() -> ! { | 54 | fn main() -> ! { |
| 51 | let mut executor = ::embassy_executor::Executor::new(); | 55 | let mut executor = ::embassy_executor::Executor::new(); |
| 52 | let executor = unsafe { __make_static(&mut executor) }; | 56 | let executor = unsafe { __make_static(&mut executor) }; |
| @@ -55,31 +59,31 @@ pub fn run(args: syn::AttributeArgs, f: syn::ItemFn) -> Result<TokenStream, Toke | |||
| 55 | spawner.must_spawn(__embassy_main(spawner)); | 59 | spawner.must_spawn(__embassy_main(spawner)); |
| 56 | }) | 60 | }) |
| 57 | } | 61 | } |
| 58 | }; | 62 | } |
| 63 | } | ||
| 59 | 64 | ||
| 60 | #[cfg(all(not(feature = "std"), not(feature = "wasm"), not(feature = "riscv")))] | 65 | pub fn run(args: syn::AttributeArgs, f: syn::ItemFn, main: TokenStream) -> Result<TokenStream, TokenStream> { |
| 61 | let main = quote! { | 66 | #[allow(unused_variables)] |
| 62 | #[cortex_m_rt::entry] | 67 | let args = Args::from_list(&args).map_err(|e| e.write_errors())?; |
| 63 | fn main() -> ! { | ||
| 64 | let mut executor = ::embassy_executor::Executor::new(); | ||
| 65 | let executor = unsafe { __make_static(&mut executor) }; | ||
| 66 | executor.run(|spawner| { | ||
| 67 | spawner.must_spawn(__embassy_main(spawner)); | ||
| 68 | }) | ||
| 69 | } | ||
| 70 | }; | ||
| 71 | 68 | ||
| 72 | #[cfg(all(not(feature = "std"), not(feature = "wasm"), feature = "riscv"))] | 69 | let fargs = f.sig.inputs.clone(); |
| 73 | let main = quote! { | 70 | |
| 74 | #[riscv_rt::entry] | 71 | let ctxt = Ctxt::new(); |
| 75 | fn main() -> ! { | 72 | |
| 76 | let mut executor = ::embassy_executor::Executor::new(); | 73 | if f.sig.asyncness.is_none() { |
| 77 | let executor = unsafe { __make_static(&mut executor) }; | 74 | ctxt.error_spanned_by(&f.sig, "main function must be async"); |
| 78 | executor.run(|spawner| { | 75 | } |
| 79 | spawner.must_spawn(__embassy_main(spawner)); | 76 | if !f.sig.generics.params.is_empty() { |
| 80 | }) | 77 | ctxt.error_spanned_by(&f.sig, "main function must not be generic"); |
| 81 | } | 78 | } |
| 82 | }; | 79 | |
| 80 | if fargs.len() != 1 { | ||
| 81 | ctxt.error_spanned_by(&f.sig, "main function must have 1 argument: the spawner."); | ||
| 82 | } | ||
| 83 | |||
| 84 | ctxt.check()?; | ||
| 85 | |||
| 86 | let f_body = f.block; | ||
| 83 | 87 | ||
| 84 | let result = quote! { | 88 | let result = quote! { |
| 85 | #[::embassy_executor::task()] | 89 | #[::embassy_executor::task()] |
