Rust in Everything
基于 tauri 2.12.5

编译期

一个 tauri 应用在运行之前,已经有三段代码在 cargo build 里跑过了:应用的 build.rs(tauri-build)、generate_context!(tauri-macros 调 tauri-codegen)、#[command] 和 generate_handler!(tauri-macros)。源码在 crates/tauri-build/src(约 2 500 行)、crates/tauri-codegen/src(约 1 800 行)、crates/tauri-macros/src(约 1 600 行),以及它们共用的 tauri-utils 里的 config、acl/build.rs、assets.rs、html2.rs。

这三段代码之间靠文件和环境变量交接,不靠函数调用:build script 把权限清单和能力写进 OUT_DIR、用 cargo:rustc-env 留下目标三元组;generate_context! 展开时再按 OUT_DIR 环境变量找到这些文件。命令宏这一边和前两者无关,只在开了 build > removeUnusedCommands 时读一份 build script 写的允许列表。

  1. tauri-build:try_build 的每一步:读配置并合并 TAURI_CONFIG、发 desktop / mobile / dev 三个 cfg、核对 Cargo feature 和配置(「does not match the allowlist」就从这里来)、通过 links 元数据收集 tauri 和插件的权限文件、读 capabilities/ 并校验、把 acl-manifests.json 和 capabilities.json 写进 OUT_DIR;项目里没有 capabilities 目录时,每次 cargo build 都会重跑。
  2. generate_context!:配置变成 Rust 字面量;frontendDist 逐个文件 brotli 压缩(debug 质量 2、release 质量 9),以内容哈希命名写进 OUT_DIR 再 include_bytes!;配置了 CSP 时为内联脚本和 .js 文件算 sha256;ACL 在这里解析;整个 Context 在一个 8 MiB 栈的线程里构造。
  3. #[command] 与 generate_handler!:命令宏保留原函数,另生成一个 __cmd__ 包装宏,每个参数一次 CommandArg::from_command;同步和 async 两种生成;async 命令借用参数为什么必须返回 Result;rename_all 和 rename;generate_handler! 展开成按命令名 match 的闭包。
flowchart TB
  tauribs["tauri 的 build.rs"] -->|"DEP_TAURI_*"| appbs["应用的 build.rs"]
  conf["tauri.conf.json"] --> appbs
  caps["capabilities 目录"] --> appbs
  appbs --> outdir["OUT_DIR 里的 JSON"]
  conf --> ctxmacro["generate_context!"]
  dist["frontendDist"] --> ctxmacro
  outdir --> ctxmacro
  ctxmacro --> ctx["Context"]
  cmd["#[command] fn"] --> wrapper["__cmd__ 包装宏"]
  wrapper --> handler["generate_handler! 闭包"]
  ctx --> run["Builder::run"]
  handler --> run

Context 交给 Builder 之后的事属于启动主线的运行时部分,见 Builder 与 App;generate_handler! 生成的闭包在运行时怎么被调用,见 on_message 与分发。ACL 的数据结构和解析规则属于 07 安全(权限、能力、作用域、编译期解析),这一部分只讲它们在编译期从哪里收集、写到哪里。

💬 关联讨论

发起讨论
加载中...