一个现代、生产就绪的模板,用于使用 Zig 编程语言开发 Flipper Zero 应用程序。该项目提供了一个流线化的构建系统,将 Zig 与 Flipper Zero SDK 相结合,使开发者能够为 Flipper Zero 平台编写类型安全、内存安全的应用程序。
该模板将 Zig 强大的构建系统及语言特性与 Flipper Zero 固件开发套件相连接。它处理了 Zig 的 ARM Cortex-M4 交叉编译与 Flipper SDK 之间的复杂集成,为自定义应用程序提供了一个干净的起点。
ufbt(非官方构建工具)无缝集成,用于打包 FAP 文件该模板使用两阶段构建过程:
Zig 构建阶段:将 Zig 源码编译为 ARM Cortex-M4 目标文件(app.o)
thumb 架构,cortex-m4 CPU 模型eabihf(嵌入式应用二进制接口,硬浮点)ReleaseSmall 以最小化二进制体积UFBT 打包阶段:将目标文件与 SDK 链接,并打包为 .fap 格式
ufbt 命令所需ufbt 自动管理(安装到 ~/.ufbt)该模板预配置为 ARM64 macOS,使用 ARM 工具链路径:
~/.ufbt/toolchain/arm64-darwin/arm-none-eabi/include
如果你使用其他平台,可能需要调整 build.zig:31 中的 arm_libc_include 路径,以匹配你的工具链位置。
安装 UFBT:
python3 -m pip install --upgrade ufbt
ufbt update
克隆或下载此模板:
git clone https://github.com/yourusername/flipper-template.git
cd flipper-template
初始化你的项目:
zig build init
这个交互式脚本会提示你输入:
my_custom_app)将 Zig 源码编译为目标文件:
zig build
这将在 zig-out/bin/app.o 生成包含所有编译的应用代码的目标文件。
构建并打包完整的应用程序:
zig build fap
这会运行完整的流程:
ufbt 与 SDK 链接dist/ 目录生成 .fap 文件在连接的 Flipper Zero 上直接启动应用程序:
zig build launch
这会构建、打包并通过 USB 传输应用,然后自动启动它。
flipper-template/
├── application.fam # Flipper 应用清单(元数据、入口点)
├── build.zig # Zig 构建系统配置
├── build.zig.zon # Zig 包清单
├── icon.png # 应用图标(建议 10x10px)
├── setup.sh # 交互式项目初始化脚本
├── src/
│ └── root.zig # 主要应用源码
└── zig-out/ # 构建产物(生成)
└── bin/
└── app.o # 编译的目标文件
src/root.zig:包含 start() 函数和应用逻辑的入口点application.fam:Flipper 特定的配置(应用 ID、类别、依赖、栈大小)build.zig:定义编译目标、SDK 路径和构建命令该模板包含一个演示核心 Flipper API 的“Hello World”示例:
// 导入 Flipper SDK 函数
const flipper = @cImport({
@cInclude("furi.h");
@cInclude("gui/gui.h");
@cInclude("gui/canvas.h");
@cInclude("gui/view_port.h");
});
// 应用入口点(必须命名为 "start")
export fn start(_: ?*anyopaque) callconv(.{ .arm_aapcs = .{} }) i32 {
// 初始化 GUI 视口
const gui = flipper.furi_record_open("gui");
const view_port = flipper.view_port_alloc();
// 设置回调和 UI
// ...(完整实现见 src/root.zig)
// 事件循环
_ = flipper.furi_thread_flags_wait(1, flipper.FuriFlagWaitAny, flipper.FuriWaitForever);
return 0;
}
构建系统自动配置以下部分的包含路径:
所有头文件均可通过 Zig 代码中的 @cImport() 使用。
Flipper SDK 使用 ARM AAPCS 调用约定:
start() 入口点)确保导出的函数与预期的调用约定匹配:
export fn start(_: ?*anyopaque) callconv(.{ .arm_aapcs = .{} }) i32
export fn draw_callback(canvas: ?*Canvas, ctx: ?*anyopaque) callconv(.{ .arm_aapcs_vfp = .{} }) void
某些 SDK 头文件包含 Zig 的 C 翻译器无法处理的结构(例如 input/input.h 中的联合体与不透明类型)。对于这些情况,手动声明外部函数:
extern fn view_port_input_callback_set(
view_port: ?*flipper.ViewPort,
callback: ?*const fn (?*anyopaque, ?*anyopaque) callconv(.{ .arm_aapcs_vfp = .{} }) void,
context: ?*anyopaque
) callconv(.{ .arm_aapcs = .{} }) void;
问题:unable to find header 'furi.h'
~/.ufbt 路径不正确ufbt update 安装 SDK 头文件问题:undefined reference to 'view_port_alloc'
zig build fap 而非 zig build 来完成链接问题:No Flipper device found
问题:启动时应用崩溃
application.fam 中增加 stack_size,或验证函数签名修改 build.zig 中的 addFlipperDefines() 以调整预处理器宏:
obj.root_module.addCMacro("FAP_VERSION", "\\\"1.0\\\"");
obj.root_module.addCMacro("CUSTOM_DEFINE", "value");
更改 build.zig:11 中的优化级别:
const optimize = b.standardOptimizeOption(.{
.preferred_optimize_mode = .ReleaseFast, // 或 .ReleaseSmall、.Debug
});
该模板针对 Flipper Zero 的 STM32WB55(ARM Cortex-M4F)。要移植到其他 ARM 设备,请调整 build.zig:4-9:
const target = b.resolveTargetQuery(.{
.cpu_arch = .thumb,
.cpu_model = .{ .explicit = &std.Target.arm.cpu.cortex_m4 },
.os_tag = .freestanding,
.abi = .eabihf,
});
欢迎贡献!该模板旨在简化 Flipper Zero 的 Zig 开发。如果你遇到 SDK 兼容性问题或有改进构建过程的建议,请提交 Issue 或 Pull Request。
本项目采用 MIT 许可证——详见 LICENSE 文件。
注意:这是一个非官方模板,与 Flipper Devices Inc. 无关。在部署到生产设备之前,请务必彻底测试应用程序。