Rust in Everything
基于 embassy-executor 0.10.0

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;平台只在二进制里选。

💬 关联讨论

发起讨论
加载中...