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

基于proc_macro的条件编译:检测crate环境并按需实现代码

可以通过条件编译+可选依赖实现需求

你可以通过Rust的条件编译机制和可选依赖,让token_parser crate在特定环境下编译From<proc_macro::TokenTree>的实现,同时保证普通场景下的可用性。以下是具体实现方式:

1. 配置Cargo.toml

首先将proc-macro设为可选依赖,避免普通场景下引入不必要的依赖:

[dependencies]
# 仅在需要时引入proc-macro依赖
proc-macro = { version = "1.0", optional = true }

如果需要让依赖方主动开启proc-macro支持(推荐,因为无法自动检测依赖方是否为proc-macro crate),可以添加一个feature:

[features]
# 开启proc-macro转换支持
proc-macro-support = ["proc-macro"]

2. 编写条件编译的代码

根据你的需求选择对应的条件编译方式:

场景A:当token_parser自身是proc-macro crate时启用实现

如果你的token_parser本身需要作为proc-macro crate使用(即Cargo.toml中设置了proc-macro = true),直接使用内置的proc_macro cfg:

pub struct Group;
pub struct Ident;
pub struct Punct;
pub struct Literal;

pub enum Token {
    Group(Group),
    Ident(Ident),
    Punct(Punct),
    Literal(Literal)
}

// 仅当当前crate是proc-macro类型时编译该实现
#[cfg(proc_macro)]
impl From<proc_macro::TokenTree> for Token {
    fn from(token: proc_macro::TokenTree) -> Self {
        match token {
            proc_macro::TokenTree::Group(_) => Token::Group(Group),
            proc_macro::TokenTree::Ident(_) => Token::Ident(Ident),
            proc_macro::TokenTree::Punct(_) => Token::Punct(Punct),
            proc_macro::TokenTree::Literal(_) => Token::Literal(Literal),
        }
    }
}

场景B:当其他proc-macro crate依赖token_parser时启用实现

如果token_parser是普通库,需要依赖方主动开启proc-macro支持,使用feature条件编译:

pub struct Group;
pub struct Ident;
pub struct Punct;
pub struct Literal;

pub enum Token {
    Group(Group),
    Ident(Ident),
    Punct(Punct),
    Literal(Literal)
}

// 仅当开启proc-macro-support feature时编译该实现
#[cfg(feature = "proc-macro-support")]
impl From<proc_macro::TokenTree> for Token {
    fn from(token: proc_macro::TokenTree) -> Self {
        match token {
            proc_macro::TokenTree::Group(_) => Token::Group(Group),
            proc_macro::TokenTree::Ident(_) => Token::Ident(Ident),
            proc_macro::TokenTree::Punct(_) => Token::Punct(Punct),
            proc_macro::TokenTree::Literal(_) => Token::Literal(Literal),
        }
    }
}

此时,proc-macro crate依赖token_parser时,只需在其Cargo.toml中开启feature:

[dependencies]
token_parser = { version = "0.1", features = ["proc-macro-support"] }

3. 普通场景的兼容性

因为proc-macro是可选依赖,且转换实现被条件编译包裹,普通crate依赖token_parser时不会引入proc-macro,也不会编译该实现,完全可以正常使用Token枚举。

注意事项

  • Rust内置的#[cfg(proc_macro)]仅针对当前crate的编译环境,无法自动检测依赖自己的crate是否为proc-macro类型。
  • 如果你的token_parser不需要作为proc-macro crate使用,推荐使用feature的方式,让依赖方主动开启功能,灵活性更高。

内容的提问来源于stack exchange,提问作者MaxCross

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:05:36