DEBUG.WIKI
搬瓦工;先看线路,再选 VPS;CN2 GIA · 对应线路套餐;查看线路 →
野草云;香港 200Mbps 峰值;不限月流量 · BGP VPS;查看套餐 →
RackNerd;$21.99/年 · 1GB KVM

Rust 1.99.0 编译 UEFI release 报 undefined symbol: wcslen,1.99.1 已修复

UEFI 项目仅在 release 下报 undefined symbol: wcslen,检查 Rust 1.99.0 工具链。1.99.1 已修复;无法更新的 no_std 构建可按限定条件临时禁用对应 LLVM 优化。

UEFI 项目在 debug 下能构建,换成 --release 后却链接失败:

rust-lld: error: undefined symbol: wcslen

报错可能引用 uefi 库里的 ComponentName、ComponentName2 等函数,即使应用入口只返回成功状态也能碰到。若实际工具链是 Rust 1.99.0,先检查这条已知回归:1.99.1 已正式修复 UEFI 与部分嵌入式目标缺失 wcslen 的问题。

这里的 wcslen 是链接产物需要的符号,不是某个 Rust 源文件、crate 或主机上的动态库文件。它与 macOS 上 rust-lld 找不到 libLLVM.dylib 的启动错误不同,不能通过调整主机动态库路径解决。

记录 release、目标和实际工具链

在原构建入口核对版本及完整链接错误。已有对应工具链时,可以查看:

rustc +1.99.0 --version --verbose

问题对应的 1.99.0 分发使用 LLVM 23.1.1,示例目标为 x86_64-unknown-uefi。确认 CI、IDE 或打包脚本是否固定到这一工具链;终端默认版本已经更新,不等于原构建也更新。

同时比较构建参数:目标、release profile、LTO、既有 RUSTFLAGS 和依赖锁定都应记录。优化后的代码可能引用宽字符长度函数,而该版本对应目标的支撑实现未提供所需符号,所以 debug 成功不能排除工具链问题。

如果目标实际上是 Windows、Linux 或自定义裸机平台,应先保留完整目标定义和符号引用位置。这条 UEFI 处理路径不能覆盖所有 wcslen 未定义,更不能替代外部 C 库的正常链接配置。

优先采用 1.99.1 的正式修正

保留项目原有目标和 Cargo.lock,用已安装且已添加 UEFI 目标的 1.99.1 工具链重新构建:

cargo +1.99.1 build --release --target x86_64-unknown-uefi

这是针对已有 UEFI Cargo 工程的构建命令,不是部署到固件的命令。若尚未安装相应工具链或目标,应先按项目的工具链管理流程准备,不能把缺 target 的新错误误认成原回归还在。

仓库若通过 rust-toolchain.toml 固定版本,同步修改该处及 CI 的版本来源,避免临时命令成功后下一次常规构建又回到 1.99.0。更新后要回到原来失败的完整构建流程验证,而不只编译一个空入口。

不要给 UEFI 目标直接链接主机 libc,也不要写一个总是返回 0 的同名函数充当桩。即使链接成功,错误的宽字符串长度仍可能破坏运行时行为。

暂时保留 1.99.0 的 no_std 构建

确实暂时无法更新、而且属于这里的 no_std 构建时,可以在该次构建中禁用产生 wcslen 调用的 LLVM 优化:

RUSTFLAGS="-C llvm-args=-disable-loop-idiom-wcslen" cargo +1.99.0 build --release --target x86_64-unknown-uefi

这条 Unix 类 shell 示例假定没有其他必须保留的 RUSTFLAGS;已有参数时需按工程原方式合并,不能整项覆盖。它针对本次编译的优化行为,不能修补已经分发的预编译标准库。因此不能把它当成所有使用 std 场景的通用修复。

该开关是临时的 LLVM 参数,升级正式修正版本后应评估移除,避免未来工具链不再接受它。验收先确认原 release 产物完成链接,再在受控 UEFI 测试环境检查启动和实际使用的协议路径;构建成功本身不代表已经验证了固件运行。