本次是学习了这门课程中的实践阶段总结的问题Solana/Learn Me A Solana 写的真好,推荐~~~
在本次 Solana 智能合约的开发和打包(
cargo build-sbf)过程中,遇到了一系列由于环境冲突 、Rust 版本过旧 与依赖包版本过新导致的问题。本文档记录了项目代码的简要介绍,以及这些编译问题的表现、根本原因和最终的解决步骤,以便后续参考。
项目代码简介
当前项目(pxsol-ss)是一个非常基础的 Solana 智能合约(Program)模板。
核心逻辑位于 src/lib.rs:
rust
solana_program::entrypoint!(process_instruction);
use solana_program::{
account_info::AccountInfo,
entrypoint,
entrypoint::ProgramResult,
pubkey::Pubkey,
};
pub fn process_instruction(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> ProgramResult {
solana_program::msg!("Hello, Solana!");
Ok(())
}
项目暴露了一个标准的 Solana 指令处理入口 process_instruction。
- 参数 : 接收三个标准参数:
program_id(当前执行的合约地址)、accounts(相关的账户数组)、instruction_data(被序列化的指令数据)。 - 功能 : 目前没有执行复杂的链上状态变更,当它被调用时,只通过
solana_program::msg!("Hello, Solana!");向链上日志输出一行 "Hello, Solana!",随后返回Ok(())以示执行成功。 - 作用: 这是所有 Solana 原生智能合约(Non-Anchor,不使用 Anchor 框架)的"Hello World"基座,非常适合用来验证编译工具链和早期环境搭建的连通性。
1. 问题一:Rust 环境冲突(error: no such command: +solana)
表现
在执行 cargo build-sbf 时,终端报错:
go
error: no such command: `+solana`
原因分析
Solana 在编译智能合约时,会通过 rustup 调用其特定绑定的工具链(即 cargo +solana)。但是,你的 macOS 系统中不仅通过 rustup 安装了 Rust,还通过 Homebrew 安装了全局的 Rust(路径位于 /opt/homebrew/bin/cargo)。 Homebrew 安装的 Cargo 不支持 +toolchain 这种语法特性,导致其将 +solana 误认为是一个名为 cargo-+solana 的子命令,从而引发报错。
解决方法
彻底清理并统一 Rust 环境,确保系统唯一使用官方的 rustup 工具链:
- 卸载 Homebrew 版 Rust:
brew uninstall rust - 彻底清理残留配置:
rm -rf ~/.cargo ~/.rustup - 重新通过官方脚本安装:
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh - 刷新环境变量:
source "$HOME/.cargo/env"
2. 问题二:版本特性不支持(feature edition2024 is required)
表现
解决了环境问题后,编译时再次报错,指出 Cargo.toml 或某个依赖库要求 edition2024:
java
The package requires the Cargo feature called `edition2024`, but that feature is not stabilized in this version of Cargo (1.75.0-dev).
原因分析
Solana 官方 build-sbf 编译工具目前内置绑定的 rustc 版本为 1.75.0 (最高支持 edition 2021)。而项目初始化的 Cargo.toml 默认填写了 edition = "2024",且 solana-program 依赖版本写得过高(4.0.0),导致 Cargo 在背后自动拉取了大量仅支持 edition2024 的最新依赖包(如 indexmap v2.14、block-buffer v0.12、toml_datetime 等)。
解决方法
- 将项目根目录的
Cargo.toml中的edition降级为2021。 - 将
solana-program的版本要求从"4.0.0"降级为"~1.18.0"(与当前本地的 Solana CLI 工具链版本1.18.26匹配),从源头上阻止拉取超前的、不兼容 Solana 底层编译器的 2024 版依赖库。
3. 问题三:深层级联依赖导致的高版本编译器要求
表现
在降低了全局版本并执行了 cargo update 之后,个别间接依赖依然拉取了过高的版本,比如:
- 依然出现
indexmap v2.14或block-buffer要求edition2024。 - 出现
error: package borsh v1.6.1 cannot be built because it requires rustc 1.77.0 or newer。
原因分析
cargo update 默认拉取满足版本约束的"最高版本"。例如,尽管 solana-program 降级了,但诸如 blake3、proc-macro-crate 或 borsh 这些库依然更新到了由于底层代码库推进而产生的仅支持 Rust 1.77.0+ 或 edition2024 新语法的版本。
解决方法
使用 cargo update -p <包名> --precise <回退版本号> 命令,手动在 Cargo.lock 中"锁死"这些具有新特性的底层库,让它们回退到兼容 Rust 1.75.0 和 edition 2021 的老版本。 本次操作中执行的降级命令包括:
cargo update -p blake3 --precise 1.5.5cargo update -p proc-macro-crate@3.5.0 --precise 3.1.0cargo update -p indexmap --precise 2.2.6cargo update -p borsh@1.6.1 --precise 1.5.0
执行完上述锁定后,底层依赖全部通过,cargo build-sbf 最终成功编译出目标合约产物。
总结与避坑建议
- 统一本地包管理器 :做 Rust/Solana 开发时,绝对不要 使用 Homebrew 安装 Rust,全程使用官方
rustup以避免核心套件冲突。 - 对齐 Solana 依赖版本 :Solana CLI 拥有一个相对封闭和滞后的编译沙盒。在
Cargo.toml中声明的solana-program等依赖,强烈建议版本号与机器上安装的solana-cli版本号保持一致(例如本机是1.18.26,依赖就写~1.18.0)。盲目追求最新版本(如4.0.0)会导致编译链不匹配的问题。 - 慎用 `cargo update` :在旧工具链下如果已经能编译成功,非必要不要执行全局
cargo update,防止依赖被意外推进至要求新版编译器的版本。遇到了依赖包报错,活用cargo tree和cardo update --precise来进行排雷和定点降级。