No architecture selected for embassy-executor
主线位置:定时器主线的第一步,
#[embassy_executor::main]展开成平台的入口函数和Executor::run。平台模块提供什么、WFE/SEV在哪,见各平台的执行器;宏展开见宏。
flowchart TB
m["embassy_executor::main"] --> p{"platform-* 几个"}
p -->|0| u["main_unspecified"]
u --> e1["No architecture selected"]
p -->|2 个以上| e3["At most one ..."]
p -->|1| t{"executor-thread"}
t -->|没开| e2["E0433 找不到 main"]
t -->|开了| ok["main_std 等"]
实验 crate exp-embassy/pita-noplat(embassy-executor 不开默认之外的 feature,靠本 crate 的 thread / std 两个 feature 转发)和 pita-noplat-arch;std,debug;M2 Max、macOS 27、rustc 1.99.0。程序就是一个 #[embassy_executor::main] async fn main(_spawner: Spawner),打印一行后退出。
现象
只开 executor-thread(--features thread):
error: 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")]
--> src/main.rs:4:1
|
4 | async fn main(_spawner: Spawner) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
照着提示去开 arch-std(pita-noplat-arch),cargo 在解析依赖时就拒绝,同时列出真正的名字:
package `pita-noplat-arch` depends on `embassy-executor` with feature `arch-std` but `embassy-executor` does not have that feature.
help: available features: _any_trace, _platform, defmt, embassy-time-driver, executor-interrupt, executor-thread, log, metadata-name, nightly, platform-avr, platform-cortex-ar, platform-cortex-m, platform-riscv32, platform-spin, platform-std, platform-wasm, rtos-trace, scheduler-deadline, scheduler-priority, trace, turbowakers
只开 platform-std(--features std):
error[E0433]: cannot find `main` in `embassy_executor`
--> src/main.rs:3:21
|
3 | #[embassy_executor::main]
| ^^^^ could not find `main` in `embassy_executor`
|
note: found an item that was configured out
--> ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/embassy-executor-0.10.0/src/lib.rs:48:54
|
47 | #[cfg(not(feature = "_platform"))]
| ----------------------- the item is gated here
48 | pub use embassy_executor_macros::main_unspecified as main;
| ^^^^
error[E0752]: `main` function is not allowed to be `async`
这次的 note 更容易把人带偏:它指向的 main_unspecified 是「没选平台」时的那个宏,被关掉恰恰因为平台已经选了。缺的是 executor-thread。第二条 E0752 是连带的:宏没展开,async fn main 原样留给了 rustc。
两个平台(--features "thread std embassy-executor/platform-spin",模拟某个依赖为了自己的测试开了另一个平台):
error: At most one of these features can be enabled at the same time: `platform-avr` `platform-cortex-m` `platform-cortex-ar` `platform-riscv32` `platform-std` `platform-wasm` `platform-spin`
--> ~/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/embassy-executor-0.10.0/src/lib.rs:18:9
...
error: could not compile `embassy-executor` (lib) due to 1 previous error
出处
lib.rs 里 main 有两个来源,按 _platform 二选一:
#[cfg(not(feature = "_platform"))]
pub use embassy_executor_macros::main_unspecified as main;
#[cfg(feature = "_platform")]
#[allow(unused_imports)] // don't warn if the module is empty.
pub use platform::*;
每个 platform-* 都打开 _platform。选了平台以后,main 只能从 platform::* 来,而平台文件把 Executor 和 main 都放在 executor-thread 后面,platform/std.rs 开头:
#[cfg(feature = "executor-thread")]
pub use thread::*;
#[cfg(feature = "executor-thread")]
mod thread {
// ...
pub use embassy_executor_macros::main_std as main;
所以「选了平台、没开 executor-thread」时 main 根本不存在,于是 E0433。
没选平台时,main_unspecified 用的 ARCH_UNSPECIFIED 要求调用方用 executor = "..." 指定执行器,没指定时 run 报上面那句话。arch-* 在 0.10.0 改名为 platform-*(来历见各平台的执行器),宏里的字符串没跟着改;CHANGELOG 0.10.0 也还写着「The feature name arch-cortex-ar remains the same」。main 分支在 #6631 的提交 c4a30fd66(「replaced some legacy arch-* wording with platform-*」,2026-07-27)里把它改成了「No platform selected for embassy-executor. Make sure you've enabled one of the platform-* features in your Cargo.toml.」,还没有发版。
平台互斥的检查是 lib.rs 开头的 check_at_most_one!,展开成对每一对 feature 的 all(...) 判断加一个 compile_error!。
修法
两个 feature 一起开,平台按目标选一个:
# std
embassy-executor = { version = "=0.10.0", features = ["platform-std", "executor-thread"] }
# Cortex-M
embassy-executor = { version = "=0.10.0", features = ["platform-cortex-m", "executor-thread"] }
pita-noplat --features "thread std":
main ran
只用 InterruptExecutor、不要线程模式执行器的 Cortex-M 程序,开 executor-interrupt、不开 executor-thread,入口用 cortex_m_rt::entry 自己写,不能用 #[embassy_executor::main]。
库 crate 不该开任何 platform-*:平台和 executor-* 是二进制的决定,库只依赖 embassy-executor 本身(拿 Spawner、写 #[task])。两个平台的错误几乎总是某个库违反了这一条,用 cargo tree -e features -i embassy-executor 找出是谁。
怎么确认没中招
- 二进制的
Cargo.toml里embassy-executor那一行同时有一个platform-和executor-thread(或executor-interrupt)。 - 照着 0.9 及以前的文档、博客或报错写
arch-*时,换成同名的platform-*;cargo 的available features列表就是 0.10.0 的全集。 cargo tree -e features -i embassy-executor里platform-开头的分支只能有一条。
小结
- 只开
executor-thread:No architecture selected,提示里的arch-*是 0.10.0 之前的名字,照做会被 cargo 拒绝;main 已改,未发版。 - 只开
platform-*:E0433 cannot find main,note指向的main_unspecified是误导,缺的是executor-thread。 - 两个平台:
At most one of these features;平台只在二进制里选。