ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Solana C 语言 BPF 程序开发指南:从 makefile 构建到单元测试的完整实战

Solana C 语言 BPF 程序开发指南:从 makefile 构建到单元测试的完整实战 Solana C 语言 BPF 程序开发指南从 makefile 构建到单元测试的完整实战【免费下载链接】solanaWeb-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.项目地址: https://gitcode.com/GitHub_Trending/so/solana本指南以 Solana 官方 C SDKsdk/bpf/c/README.md为核心系统讲解如何使用 C 语言编写 Solana 链上 BPF 程序包括项目骨架搭建、bpf.mk构建系统用法、Criterion 单元测试框架集成以及 C 语言开发的关键限制与规避方案。读完本文后你将能独立完成一个 C 语言 Solana 程序的编写、编译、测试与部署准备工作。一、背景为什么用 C 写 Solana 程序Solana 链上程序Program运行在 BPFBerkeley Packet Filter虚拟机之上官方主推 Rust 生态但同时也提供了完整的 C/C SDK。C 语言程序编译为bpfel目标 ELF 文件后同样可通过 BPF Loader 部署上链。在 Solana 源码仓库中C 语言的完整开发工具链集中在 sdk/bpf/c 目录包含头文件目录inc/、构建脚本bpf.mk、链接脚本bpf.ld以及配套的 sdk/bpf/scripts工具链下载脚本与 sdk/bpf/env.sh环境配置脚本。仓库自带的 programs/sbf/c/src 下大量 C 示例程序如noop、alloc、move_funds等均采用本指南介绍的这套构建体系。二、快速开始搭建你的第一个 C 程序根据 sdk/bpf/c/README.md 的 Quick start 章节只需两个文件即可起步。1. 编写 makefile在项目根目录创建makefile内容仅需一行include path/to/bpf.mkpath/to/bpf.mk指向仓库中的 sdk/bpf/c/bpf.mk。实际使用中通常写为相对路径例如../../sdk/bpf/c/bpf.mk。该 makefile 接管了后续全部构建逻辑。2. 编写程序源码创建src/program.c内容为#include solana_sdk.h extern uint64_t entrypoint(const uint8_t *input) { SolAccountInfo ka[1]; SolParameters params (SolParameters) { .ka ka }; if (!sol_deserialize(input, params, SOL_ARRAY_SIZE(ka))) { return ERROR_INVALID_ARGUMENT; } return SUCCESS; }这个最小程序完成了三件核心工作entrypoint是程序入口每个 Solana 程序必须导出uint64_t entrypoint(const uint8_t *input)函数接收一个序列化后的输入缓冲区见 entrypoint.h准备SolParameters接收反序列化结果SolParameters结构体包含账户数组指针ka、账户数量ka_num、指令数据指针data/data_len以及当前程序 IDprogram_id调用sol_deserialize解析输入成功返回true失败返回ERROR_INVALID_ARGUMENT该错误码定义于 types.h值为内置错误的高 32 位编码。关于sol_deserialize的实现细节deserialize.h 中的sol_deserialize采用零拷贝反序列化——它不复制数据而是直接在原始缓冲区上填充SolAccountInfo的指针与长度字段因此程序对lamports或账户数据的修改会直接作用到原缓冲区结束时也无需再序列化写回。同时它支持账户去重dup_info字段重复账户直接复制首份账户的指针这是 BPF Loader 输入格式的重要特征。3. 构建与产物执行make即可构建默认输出目录为./out产物为out/program.o。若你的源码目录、测试前缀等需要定制可通过命令行覆盖bpf.mk中的可配置变量详见下文「构建系统深度解析」。三、构建系统深度解析bpf.mk 的工作原理bpf.mk是整个 C 开发体验的基石。理解它的约定与目标规则是高效开发的前提。1. 目录与命名约定make help输出的说明明确了默认约定见 bpf.mk约定项默认值说明源码目录SRC_DIR ? ./src程序位于$(SRC_DIR)/program name程序命名按目录名目录src/foo/即程序名foo测试前缀TEST_PREFIX ? test_测试文件须以test_开头位于程序目录内输出目录OUT_DIR ? ./out所有产物输出到该目录详细模式VV1时回显构建命令默认静默2. 可用的 make 目标目标作用make help显示帮助信息与可用程序/测试列表make all构建全部程序与测试并运行测试make programs构建所有程序make tests构建并运行所有测试make program name按名称构建单个程序make test name构建并运行单个测试make dump_program name用llvm-objdump反汇编输出程序含源码标注make readelf_program name用llvm-readelf显示 ELF 二进制信息make clean删除$(OUT_DIR)例如仓库示例程序 programs/sbf/c/src/noop/noop.c 所在目录名为noop那么make noop会编译出out/noop.somake dump_noop可查看其反汇编。3. 编译与链接参数bpf.mk中实际使用的工具链与参数bpf.mk工具链clang/clang/ld.lld/llvm-objdump/llvm-readelf全部来自bpf-tools由 install.sh 自动下载C 编译标志-Werror -O2 -fno-builtin -stdc17标准为C17BPF 目标标志-target bpf -fPIC -marchbpfelsolanabpfel即 little-endian BPF链接标志-z notext -shared --Bdynamic使用 bpf.ld 链接脚本入口点固定为entrypointSBFv2 支持设置环境变量SOL_SBFV21时追加-DSOL_SBFV21编译宏并启用--pack-dyn-relocsrelr动态重定位打包。链接脚本 bpf.ld 将 ELF 组织为text、rodata、data、dynamic四个段并丢弃.eh_frame、.gnu.hash、.hash等无关段以最小化链上程序体积。依赖自动安装install.sh 会在首次构建时自动下载 Criterion 测试框架与 Rust-BPF 平台工具platform-tools并缓存到~/.cache/solanaenv.sh 则负责导出CC、AR、OBJDUMP、OBJCOPY等环境变量指向 bpf-tools 中的 LLVM 工具。4. 构建产物与部署提示每次成功链接出.so后bpf.mk还会自动生成对应的program-keypair.json密钥对文件若不存在并提示部署命令solana program deploy /absolute/path/to/out/program.so四、单元测试基于 Criterion 的测试体系内置的单元测试支持来自Criterion测试框架详见 sdk/bpf/c/README.md 的 Unit tests 章节以及 install.sh 中自动下载 Criterion 的逻辑。1. 编写测试按约定测试文件放在test/目录命名须以test_开头。创建test/example.c#include criterion/criterion.h #include ../src/program.c Test(test_suite_name, test_case_name) { cr_assert(true); }关键点直接#include程序源码而非链接编译产物使测试能访问程序内部的静态函数与符号使用 Criterion 的Test(suite, case)宏声明用例cr_assert进行断言测试编译时会追加-DSOL_TEST宏与 Criterion 的头文件/库路径见 bpf.mkmacOS 下还会通过install_name_tool修正libcriterion的动态库路径。2. 运行测试make testmake test会依次构建并执行所有测试make test name只运行单个测试。测试可执行文件输出在$(OUT_DIR)/program/test_name通过LD_LIBRARY_PATH指向 Criterion 库目录后运行见 bpf.mk。3. 测试示例仓库中 programs/sbf/c/src/sanity/sanity.c 等示例程序均包含test_sanity.c之类的 Criterion 测试可作为编写更复杂测试用例如构造SolAccountInfo数组、验证指令处理逻辑的直接参考。五、必须知道的限制与应对sdk/bpf/c/README.md 明确列出了 C 开发的两条核心限制理解它们能避免大量踩坑限制 1程序必须完整包含在单个 .c 文件中构建脚本只扫描$(SRC_DIR)/program/下的*.c/*.cc文件并逐一编译、链接见 bpf.mk不支持跨目录多文件项目组织应对方案将业务逻辑拆分为多个头文件.h在唯一的.c文件中#include引入。头文件内容会被编译器内联进单一翻译单元等效于单文件。限制 2没有 libc但solana_sdk.h提供最小原语集BPF 目标下标准 C 库不可用printf、malloc等 libc 函数无法直接使用替代方案solana_sdk.h见 solana_sdk.h聚合了全部可用头文件提供包括头文件提供的原语sol/types.h定长整数类型uint8_t~uint64_t、错误码、SOL_ARRAY_SIZEsol/entrypoint.hSolAccountInfo、SolParameters结构与entrypoint声明sol/deserialize.hsol_deserialize输入反序列化sol/log.hsol_log等链上日志输出原语sol/cpi.h跨程序调用CPI支持sol/sha.h、sol/keccak.h、sol/blake3.h、sol/secp256k1.h、sol/alt_bn128.h、sol/big_mod_exp.h密码学原语sol/pubkey.h、sol/assert.h、sol/return_data.h公钥、断言、return data 等辅助能力内存分配方面链上程序拥有固定虚拟地址的堆区HEAP_START_ADDRESS为0x300000000长度 32KB见 constants.hSDK 通过sol_calloc/sol_free内置函数管理该区域也允许程序自行在该区域实现自定义堆。六、完整实战把示例串起来下面是一个贴合仓库真实结构的完整开发闭环示例my-program/ ├── makefile # 内容include ../../sdk/bpf/c/bpf.mk ├── src/ │ └── counter/ │ ├── counter.c # 程序本体含 entrypoint │ └── test_counter.c # Criterion 测试以 test_ 开头# makefile include ../../sdk/bpf/c/bpf.mk// src/counter/counter.c #include solana_sdk.h extern uint64_t entrypoint(const uint8_t *input) { SolAccountInfo ka[1]; SolParameters params (SolParameters) { .ka ka }; if (!sol_deserialize(input, params, SOL_ARRAY_SIZE(ka))) { return ERROR_INVALID_ARGUMENT; } // ... 业务逻辑读写 ka[0] 的 data 与 lamports ... sol_log(counter program executed); return SUCCESS; }// src/counter/test_counter.c #include criterion/criterion.h #include counter.c Test(counter_suite, returns_success) { // 构造输入、调用 entrypoint、断言返回值 cr_assert(true); }对应的构建与验证命令make # 构建全部生成 out/counter.so make counter # 只构建 counter 程序 make test_counter # 构建并运行单个测试 make dump_counter # 查看反汇编检查 BPF 指令 make readelf_counter # 查看 ELF 段布局 make clean # 清理 out 目录构建成功后make会打印solana program deploy abs path/out/counter.so部署命令配合生成的counter-keypair.json即可上链。七、小结Solana 的 C SDK 提供了一套开箱即用的 BPF 开发体验通过 bpf.mk 一行 include 即可获得完整的编译、链接、反汇编、单元测试流水线solana_sdk.h头文件族覆盖了反序列化、日志、CPI、密码学等链上开发必需原语。遵循「单 .c 文件 头文件拆分」「无 libc、用 SDK 原语」两条铁律你就能用 C 语言写出可测试、可部署的 Solana 链上程序。如需更深入的原语用法可直接查阅 sdk/bpf/c/inc/sol 下的各头文件源码以及 programs/sbf/c/src 中的全部示例实现。【免费下载链接】solanaWeb-Scale Blockchain for fast, secure, scalable, decentralized apps and marketplaces.项目地址: https://gitcode.com/GitHub_Trending/so/solana创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表