You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 18:31:09