Windows编译Wasm遇Mio依赖报错,如何仅保留宏生成函数?
问题分析
核心问题有两个:一是需要通过wasm特性实现跨平台编译隔离(Wasm目标编译宏生成的API函数,原生目标忽略宏代码);二是Windows下Wasm编译时触发Mio库错误——本质是Mio为原生IO设计,完全不支持Wasm目标,而你的宏依赖的HTTP客户端(如reqwest)默认引入了Mio,导致Wasm编译时拉取了不兼容的依赖。
解决方案
1. 特性化隔离依赖(修改Cargo.toml)
将所有平台相关依赖通过特性开关控制,避免Wasm环境引入原生IO依赖:
[features] default = [] # Wasm环境专属特性,启用reqwest的Wasm绑定 wasm = ["reqwest/wasm-bindgen", "js-sys"] # 原生环境专属特性,启用reqwest的原生TLS支持 native = ["reqwest/native-tls", "tokio/rt-multi-thread"] [dependencies] # 禁用reqwest默认特性,避免自动引入Mio reqwest = { version = "0.11", default-features = false } js-sys = { version = "0.3", optional = true } tokio = { version = "1.0", default-features = false, optional = true } # 宏相关依赖(无平台限制) proc-macro2 = "1.0" quote = "1.0" syn = { version = "2.0", features = ["full"] }
2. 宏代码的条件化生成
在宏定义中通过#[cfg(feature = "...")]控制不同环境下的代码输出,实现Wasm编译生成有效API函数、原生编译忽略宏代码的目标:
use proc_macro::TokenStream; use quote::quote; use syn::parse_macro_input; // 自定义宏输入解析结构(示例) struct ApiRequestInput { fn_name: syn::Ident, method: syn::Ident, url: syn::LitStr, args: Vec<syn::FnArg>, return_type: syn::Type, } #[proc_macro] pub fn define_api_request(input: TokenStream) -> TokenStream { let input = parse_macro_input!(input as ApiRequestInput); // Wasm环境:生成兼容Wasm的API请求函数 #[cfg(feature = "wasm")] let impl_block = quote! { pub async fn #input.fn_name(#(#input.args),*) -> Result<#input.return_type, reqwest::Error> { reqwest::Client::new() .#input.method(#input.url) .send() .await? .json() .await } }; // 非Wasm环境:要么生成空实现,要么直接不生成有效代码(实现"忽略宏代码"的需求) #[cfg(not(feature = "wasm"))] let impl_block = quote! { // 原生编译时若未启用native特性,直接不生成函数(或编译报错提示) #[cfg(not(feature = "native"))] compile_error!("Native builds require the `native` feature to enable API functions"); // 启用native特性时生成原生环境的API函数 #[cfg(feature = "native")] pub async fn #input.fn_name(#(#input.args),*) -> Result<#input.return_type, reqwest::Error> { reqwest::Client::new() .#input.method(#input.url) .send() .await? .json() .await } }; TokenStream::from(quote! { #impl_block }) }
3. 验证编译命令
- Wasm编译(仅生成宏定义的API函数,无Mio依赖):
cargo build --target wasm32-unknown-unknown --features wasm --release - 原生编译(默认忽略宏代码,若需启用则加
--features native):# 忽略宏代码(无API函数生成) cargo build --release # 启用原生环境API函数 cargo build --release --features native
额外注意事项
- 确保已安装Wasm目标:
rustup target add wasm32-unknown-unknown - 检查所有间接依赖,避免默认引入原生IO相关特性(如tokio的
net特性会依赖Mio,需通过native特性按需启用)
内容的提问来源于stack exchange,提问作者Fuji
相关产品推荐
相关产品推荐

