过程宏到底在什么时候运行?它收到什么输入?改了代码之后会不会重新运行?这篇自己写一个最小的 proc-macro crate,在宏里打印和记日志,把三种过程宏的阶段全部量出来。
mac/src/lib.rs(proc-macro crate)与 app/src/main.rs(使用者)已创建;crate 类型 proc-macro
cargo build app 的输出(宏的 eprintln 出现在编译期):
Locking 1 package to latest Rust 1.98.1 compatible version
[编译期] 函数式宏 make_answer! 运行了,输入 tokens = "a b 3"
[编译期] derive(Hello) 运行了,输入 = "struct Point;"
[编译期] #[trace] 运行了,属性参数 = "level = 2",被修饰的条目 = "fn compute(x: i32) -> i32 { x + answer() }"
运行 app 的输出:
[运行期] main 开始
[运行期] 进入 compute
Hello from Point / 43声明宏见声明宏 macro_rules!;derive 展开见Derive 宏如何生成代码。
第一次 build 之后日志共 3 行(3 个宏各运行 1 次) 第二次 cargo build(没改动):日志仍是 3 行 —— 宏没有再运行;但 cargo 输出里仍能看到 [编译期] 行吗? True (cargo 会重放上次缓存的编译器输出) 改了 main.rs 的一个字符串后再 build:日志 6 行(新增 3 行:三个宏全部重新运行,因为使用它们的 crate 整个重新编译)
proc-macro crate 的产物:
['libmac-e31b78be4282dd07.dylib'] (动态库,由 rustc 在编译 app 时加载)
在 proc-macro crate 里 pub fn 一个普通函数:
Compiling mac v0.1.0 (<实验目录>/proj/u79/mac)
error: `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]`
--> <实验目录>/proj/u79/mac/src/lib.rs:28:1
|
28 | pub fn not_a_macro() {}
| ^^^^^^^^^^^^^^^^^^^^