如何编译出可调试的 rustc:rust.debug 配置、panic 时获取 backtrace 与 -Z 标志
【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust
当你需要修改 rustc 编译器本身,或者在本地复现一次 Internal Compiler Error(ICE,编译器内部错误)时,默认构建的 rustc 几乎没有调试信息:backtrace 里没有行号,用 GDB 单步调试也没有符号。这篇文章给出 rust 仓库文档中记录的操作路径:在bootstrap.toml中配置rust.debug,重新编译出一个带调试信息的 rustc,并在 panic 时通过RUST_BACKTRACE=1获取带行号的栈回溯,以及使用-Z不稳定标志辅助诊断。
适用前提:你要构建的是 rust 仓库自身的编译器(通过 bootstrap 构建系统),而不是普通的 Rust 程序。构建入口是仓库根目录下的./x脚本,运行它需要本机已安装 Python。
准备:clone 仓库并创建 bootstrap.toml
按 构建指南 的步骤获取源码并初始化配置:
git clone https://github.com/rust-lang/rust.git cd rust ./x setup./x setup会创建一份带合理默认值的bootstrap.toml。所有可调项的完整清单和说明在 bootstrap.example.toml 中,rust.debug相关选项的默认值以该文件中的注释为准。
磁盘空间要求(均来自构建指南与调试指南):
- 构建 stage1 编译器大约需要 10~15GB 可用空间;
- 若后面把
rust.debuginfo-level设为 2,会用到"35GB 以上"磁盘,且编译时间明显变长(文档原文提示 "upwards of 35GB")。
配置 rust.debug:修改 bootstrap.toml
默认情况下 rustc 不带大部分调试信息(见 compiler-debugging.md)。在bootstrap.toml中加入:
rust.debug = true根据 bootstrap.example.toml 的注释,rust.debug = true会同时影响若干未显式配置的选项,包括rust.debug-assertions(调试断言,代价是少量运行时变慢)、rust.debug-logging(保留debug!/trace!调用)、rust.overflow-checks,而rust.debuginfo-level的默认值会变为 1(rust.debug = true时)。也就是说rust.debug = true一次开启了debug-assertions、debug-logging等一组选项;如果你想单独微调,可以显式配置这些子项。
用 GDB 调试 rustc 时的额外配置
如果你要用 GDB 调试 rustc,需要完整符号信息,此时把 debuginfo 级别设为 2:
rust.debug = true rust.debuginfo-level = 2文档对这两级有明确区分:
debuginfo-level = 1(debug = true时的默认值):可以跟踪执行路径,但丢失符号信息;debuginfo-level = 2:符号信息完整,但会生成数 GB 的 debuginfo,显著拖慢链接过程,并占用 35GB 以上磁盘。
另外两个与调试相关的边界条件(来自 compiler-debugging.md):
默认配置会启用
symbol-mangling-versionv0,这要求 GDB 至少是 v10.2。GDB 版本更低时,需要在bootstrap.toml中禁用新符号方案:rust.new-symbol-mangling = false修改任何配置项之后必须重新构建编译器,配置才会生效:
./x build验证构建出的 rustc
构建完成后,把 stage1 工具链链接到 rustup(quickstart 中的做法):
rustup toolchain link stage1 build/host/stage1 rustc +stage1 -vV文档给出的rustc +stage1 -vV示例输出中,版本号以-dev结尾(如rustc 1.48.0-dev),说明工具链指向你本地构建的编译器。注意该自建工具链不包含cargo,rustup 会回退使用已安装的nightly/beta/stable工具链中的cargo。
panic(ICE)时获取 backtrace
rustc 发生 ICE 时,设置环境变量RUST_BACKTRACE=1即可获得panic!的栈回溯,和普通 Rust 程序一样:
RUST_BACKTRACE=1 rustc +stage1 error.rsbacktrace 的信息量取决于编译 rustc 时是否配置了debug = true:
默认配置(未设
rust.debug = true)下,backtrace 没有行号,只到函数级别。文档示例(节选):stack backtrace: 0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace ... 32: rustc_typeck::check_crate ... 37: rustc_driver::run_compiler设置
debug = true后,每帧会附带文件:行号位置信息。文档示例(节选):stack backtrace: 7: rustc_typeck::check::cast::CastCheck::check at /home/user/rust/compiler/rustc_typeck/src/check/cast.rs:572 ... 34: rustc_driver::run_compiler at /home/user/rust/compiler/rustc_driver/src/lib.rs:253(以上两段均为文档示例,具体帧数、路径和行号会随你的代码版本变化。)
两个相关的环境变量与已知限制:
RUSTC_ICE=0可以禁止 rustc 在 ICE 时向当前工作目录写rustc-ice-<timestamp>-<pid>.txt文件;默认是会产生这个文件的。- 文档明确说明 backtrace 在 MinGW 上不可用("backtraces don't work on MinGW")。如果 backtrace 全是
unknown,文档建议改用 Linux、macOS 或 Windows 上的 MSVC 工具链环境。 - 想要更详细的回溯可用
RUST_BACKTRACE=full(文档示例输出中的 note 提到该取值)。
用 -Z 标志辅助诊断
编译器自带一批-Z不稳定标志,它们只在 nightly 上生效,其中许多对调试很有用。查看完整列表:
rustc +stage1 -Z help文档重点介绍了下面几个:
定位错误消息的产生点:-Z treat-err-as-bug
-Z treat-err-as-bug=n让编译器在第n个错误处直接 panic,从而拿到错误发生点的 backtrace;省略=n时默认按 1 处理,即遇到第一个错误就 panic。文档中的完整流程(示例):
fn main() { 1 + (); }先正常编译,确认能复现错误:
rustc +stage1 error.rs加上-Z treat-err-as-bug后,编译器在处理该错误时 panic,输出中会包含internal compiler error: unexpected panic以及指向编译器源码位置的栈回溯(文档示例中回溯指向rustc::traits::error_reporting::...::report_selection_error等帧)。
查看错误创建位置:-Z track-diagnostics
-Z track-diagnostics利用#[track_caller]在每条错误消息旁打印它的创建位置,文档示例输出:
error[E0277]: cannot add `()` to `{integer}` -Ztrack-diagnostics: created at compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs:638:39文档指出它与-Z treat-err-as-bug的差异:它会对所有错误打印位置、不需要带调试符号编译的编译器、也不必阅读长栈回溯。
其他有用标志
-Z verbose-internals:打印更多对调试有用的内部信息(文档原话是 "generally enables printing more info that could be useful for debugging");-Z eagerly-emit-delayed-bugs:把 delayed bugs 变成正常错误直接暴露出来,可与-Z treat-err-as-bug组合使用,停在特定的 delayed bug 处并获取 backtrace。
限制与后续
- 任何
bootstrap.toml配置改动后都要重新./x build才生效; rust.debug = true的编译器因调试断言等检查会"稍慢但仍可用"(bootstrap.example.toml 原文注释);debuginfo-level = 2只建议在你确实用 GDB 等调试器单步调试时开启,平时用默认的 level 1 即可跟踪执行路径;- 需要更深入调试时,文档还分别提供了查询调试(incrcomp-debugging)、后端调试(backend/debugging)、借用检查器调试(borrow-check/debugging)以及 tracing 日志输出的专门章节,均可从 compiler-debugging.md 内链接进入。
【免费下载链接】rustEmpowering everyone to build reliable and efficient software.项目地址: https://gitcode.com/GitHub_Trending/ru/rust
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考