Solana 智能合约编译问题排查与修复总结

本次是学习了这门课程中的实践阶段总结的问题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 工具链:

  1. 卸载 Homebrew 版 Rust:brew uninstall rust
  2. 彻底清理残留配置:rm -rf ~/.cargo ~/.rustup
  3. 重新通过官方脚本安装:curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
  4. 刷新环境变量: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.14block-buffer v0.12toml_datetime 等)。

解决方法

  1. 将项目根目录的 Cargo.toml 中的 edition 降级为 2021
  2. solana-program 的版本要求从 "4.0.0" 降级为 "~1.18.0"(与当前本地的 Solana CLI 工具链版本 1.18.26 匹配),从源头上阻止拉取超前的、不兼容 Solana 底层编译器的 2024 版依赖库。

3. 问题三:深层级联依赖导致的高版本编译器要求

表现

在降低了全局版本并执行了 cargo update 之后,个别间接依赖依然拉取了过高的版本,比如:

  1. 依然出现 indexmap v2.14block-buffer 要求 edition2024
  2. 出现 error: package borsh v1.6.1 cannot be built because it requires rustc 1.77.0 or newer

原因分析

cargo update 默认拉取满足版本约束的"最高版本"。例如,尽管 solana-program 降级了,但诸如 blake3proc-macro-crateborsh 这些库依然更新到了由于底层代码库推进而产生的仅支持 Rust 1.77.0+edition2024 新语法的版本。

解决方法

使用 cargo update -p <包名> --precise <回退版本号> 命令,手动在 Cargo.lock 中"锁死"这些具有新特性的底层库,让它们回退到兼容 Rust 1.75.0 和 edition 2021 的老版本。 本次操作中执行的降级命令包括:

  • cargo update -p blake3 --precise 1.5.5
  • cargo update -p proc-macro-crate@3.5.0 --precise 3.1.0
  • cargo update -p indexmap --precise 2.2.6
  • cargo update -p borsh@1.6.1 --precise 1.5.0

执行完上述锁定后,底层依赖全部通过,cargo build-sbf 最终成功编译出目标合约产物。


总结与避坑建议

  1. 统一本地包管理器 :做 Rust/Solana 开发时,绝对不要 使用 Homebrew 安装 Rust,全程使用官方 rustup 以避免核心套件冲突。
  2. 对齐 Solana 依赖版本 :Solana CLI 拥有一个相对封闭和滞后的编译沙盒。在 Cargo.toml 中声明的 solana-program 等依赖,强烈建议版本号与机器上安装的 solana-cli 版本号保持一致(例如本机是 1.18.26,依赖就写 ~1.18.0)。盲目追求最新版本(如 4.0.0)会导致编译链不匹配的问题。
  3. 慎用 `cargo update` :在旧工具链下如果已经能编译成功,非必要不要执行全局 cargo update,防止依赖被意外推进至要求新版编译器的版本。遇到了依赖包报错,活用 cargo treecardo update --precise 来进行排雷和定点降级。
相关推荐
代码羊羊1 小时前
rust-字符串(切片)、元组、结构体、枚举、数组
开发语言·后端·rust
颜酱2 小时前
从零实现「拍照记单词」小应用(可复刻版)
前端·javascript·人工智能
大猫会长2 小时前
AudioContext给音频提高音量
前端·javascript·音视频
kerli2 小时前
基于 kmp/cmp 的跨平台图片加载方案 - 适配 Android View/Compose/ios
android·前端·ios
RONIN2 小时前
vue组件、组件生命周期、组件分离模块化
前端·vue.js
小强19882 小时前
HTML5语义化标签:从`div`到`article`与`section`的进化之路
前端
RONIN2 小时前
vue开发环境与基础语法、计算属性、侦听属性
前端·vue.js
WayneYang2 小时前
JavaScript ES6+ (ES2015~ES2024) 全特性整理
前端·javascript
逆光如雪2 小时前
移动端border-left 和 width:1px,同样写1px为什么粗细不同?
前端·css