尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
Flipper Zero AppManifests 完全指南:application.fam 清单格式与 fbt 构建系统深度解析
Flipper Zero AppManifests 完全指南application.fam 清单格式与 fbt 构建系统深度解析【免费下载链接】flipperzero-firmwareFlipper Zero firmware source code项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmwareFlipper Zero 固件中的每一个组件——系统服务、主菜单应用、设置项、调试工具乃至 SD 卡上的外部应用——都通过一个名为application.fam的清单文件在构建系统中声明其身份与依赖。本文以 documentation/AppManifests.md 为骨架结合仓库内application.fam实例与 fbt 构建工具、脚本/fbt/appmanifest.py 的源码实现完整讲解 FAM 清单的全部参数、外部应用FAP专属字段、依赖与冲突处理机制帮助你写出可被fbt正确识别、编译与打包的应用清单。FAM 在构建系统中的定位Flipper Zero 固件的所有组件——服务、用户应用与系统设置——均独立开发每个组件对应一份名为application.fam的清单文件用于定义该组件的基本属性及其与系统其他部分的关系。构建固件时fbt会收集所有应用清单并处理其依赖关系随后只构建当前构建配置中实际引用的组件详见 FBT 文档。因此application.fam是fbt理解有哪些应用、各自需要什么的唯一入口——没有清单的应用不会被构建清单中声明的依赖决定了编译时的可用符号与源码集合。从源码结构看清单的实际处理逻辑集中在 scripts/fbt/appmanifest.pyFlipperAppType枚举定义了全部应用类型FlipperApplication数据类声明了所有可用的字段与默认值AppManager负责加载并校验清单重复的appid会直接抛FlipperManifestExceptionAppBuildset则完成依赖解析、冲突检查与目标平台匹配。App 定义与必填参数一个固件组件的属性通过一段 Python 代码片段声明即调用带各种参数的App()函数。清单文件可包含一个或多个App()定义例如 applications/services/bt/application.fam 同时定义了蓝牙服务与蓝牙设置两个组件。只有两个参数是必填的appid字符串构建系统内的应用 ID用于指定构建配置中包含哪个应用以及解析依赖与冲突。fbt强制要求其匹配正则^[a-z0-9_]$见 scripts/fbt/appmanifest.py#L35即只能使用小写字母、数字与下划线且不允许重复声明。apptypeFlipperAppType.*枚举的成员决定组件的固件角色详见下表枚举成员固件组件类型SERVICE系统服务在系统启动早期创建SYSTEM不出现在任何菜单中的应用可由其他应用或 CLI 启动APP主菜单中的常规应用PLUGIN作为固件一部分构建、放置于插件菜单中的应用DEBUG仅在开启调试模式时于调试菜单中可见的应用ARCHIVE唯一且仅有的 Archive 应用SETTINGS放置在系统设置菜单中的应用STARTUP系统启动时运行的回调函数不定义独立应用EXTERNAL构建为.fap插件的外部应用METAPACKAGE不定义任何要运行的代码用于声明依赖与应用捆绑包值得注意的是scripts/fbt/appmanifest.py#L19-L30 中还存在一个文档表格未列出的成员MENUEXTERNAL它属于外部应用类型但按 AppBuildset 定义 仅在显式列入应用集合时才构建always deploy为False。通用参数详解除appid与apptype外其余参数均为可选且只对特定应用类型有意义name菜单中显示的名称。例如蓝牙设置应用在菜单中显示为 Bluetooth见 applications/services/bt/application.fam#L127。entry_point用作应用入口的 C 函数名。C 函数名会被编译器改编mangling如需作为入口点必须用extern C包裹。flags系统应用的内部标志普通开发不应使用。cdefines当当前应用被包含进激活的构建配置时为其他应用全局声明的 C 预处理器定义对外部应用这些定义仅用于构建该应用自身。典型例子如蓝牙服务声明cdefines[SRV_BT]见 applications/services/bt/application.fam#L6。requires应用 ID 列表当当前应用被列入待构建应用清单时这些应用也会被加入构建配置。conflicts应用 ID 列表若构建出的应用列表中出现任一冲突应用fbt将中止固件构建。provides功能上与requires完全一致常用于将若干应用打包声明为提供集合见下文 METAPACKAGE 示例。stack_size应用启动时分配的栈大小字节。栈分配过小会导致栈溢出引发系统崩溃过大则会减少应用可用的堆内存。可用top和freeCLI 命令分析应用内存占用。源码默认值为2048字节见 scripts/fbt/appmanifest.py#L62。icon作为固件一部分构建时从内置资源中选取的动画图标名。order应用在其所属分组内的排序值值越小越靠前用于排序启动钩子与菜单项。蓝牙服务与蓝牙设置的order分别为 20 与 40见 applications/services/bt/application.fam。sdk_headers该应用代码中需要包含进外部应用 API 定义的 C 头文件列表。蓝牙服务声明了bt_service/bt.h与bt_service/bt_keys_storage.h见 applications/services/bt/application.fam#L17。targets应用兼容的目标平台名列表未指定时默认为[all]即所有目标。仓库中硬件相关的调试工具常显式限定目标例如 applications/debug/accessor/application.fam#L5 声明targets[f7]。判断逻辑见 scripts/fbt/appmanifest.py#L97-L98当目标名在targets中或targets含all时视为支持。resources应用源码文件夹内用于打包 SD 卡资源的子文件夹名仅当应用被包含进构建配置时才生效默认值表示不打包资源。METAPACKAGE依赖声明与应用捆绑包METAPACKAGE类型不产生任何可运行代码专门用于声明依赖集合是组织固件应用清单的常用手段。例如 applications/main/application.fam 中的main_apps元包通过provides一次性声明了主菜单全部核心应用gpio、ibutton、infrared、lfrfid、nfc、subghz、bad_usb、u2f、archive 等applications/debug/application.fam 中的debug_apps元包则把 blink_test、vibro_test、keypad_test 等全部调试应用捆绑在一起。这些元包 ID 正是 fbt_options.py 中 FIRMWARE_APPS 引用的集合名如main_apps、system_apps、settings_apps。由于requires与provides都会触发依赖解析见 scripts/fbt/appmanifest.py#L303-L334 的_process_deps循环引用一个元包即可递归带入其提供的全部应用。PLUGIN 与外部应用的构建约束fbt对 PLUGIN 与普通内建应用有不同的参数约束校验逻辑位于 scripts/fbt/appmanifest.py#L144-L173PLUGIN 必须声明requires插件必须通过requires指明宿主应用父应用缺少该字段会直接报错。PLUGIN 不能设置stack_size插件共享宿主应用的进程上下文stack_size会被强制置 0见 scripts/fbt/appmanifest.py#L108-L110若显式传入 stack 值会提示是否本意是 EXTERNAL 类型。fal_embedded仅适用于 PLUGIN普通应用设置该字段会被拒绝。外部分发类应用EXTERNAL、PLUGIN、DEBUG不能使用resources字段资源打包另有fap_file_assets机制内建应用则不能使用fap_extbuild、fap_private_libs、fap_icon_assets等 FAP 专属字段。实际示例可参考 applications/examples/example_plugins/application.famexample_plugins与example_plugins_multi是 EXTERNAL 宿主应用example_plugin1与example_plugin2是 PLUGIN分别通过requires[example_plugins, example_plugins_multi]与requires[example_plugins_multi]挂载到宿主上并通过sources[plugin1.c]、sources[plugin2.c]指定各自的源码文件。插件归属关系由AppBuildset._group_plugins处理见 scripts/fbt/appmanifest.py#L397-L423。外部应用FAP专属参数以下参数仅用于构建 FAPFlipper App Package即.fap文件可独立于固件版本运行详见 AppsOnSDCard.mdsources字符串列表用于在应用文件夹内收集源文件的文件名掩码默认值为[*.c*]同时包含 C 与 C 源码。应用不能使用lib文件夹存放自身源码因为它被保留给fap_private_libs。以!开头的路径从源文件列表中排除掩码可含通配符与目录名。例如[*.c*, !plugins]会收集应用文件夹内除plugins及lib文件夹外的全部 C/C 源码不含通配符*、?的路径则按完整字面路径处理。fap_version字符串应用版本默认0.1也可使用(x, y)形式的二元元组。版本可追加更多点分隔部分如补丁号但只有主版本号与次版本号会被写入构建出的.fap。源码中会将其解析为整数元组并校验至少两个分量见 scripts/fbt/appmanifest.py#L115-L123。fap_icon.png文件名要求 1 位色深、10x10 像素嵌入.fap文件内部。fap_libs额外链接库列表可访问未作为主固件 API 导出的额外函数代价是.fap文件体积与 RAM 消耗增加。fap_category字符串可为空应用子分类同时决定 FAP 在文件系统 apps 文件夹中的存放路径。fap_description字符串可为空应用简介。fap_author字符串可为空应用作者。fap_weburl字符串可为空应用主页。fap_icon_assets字符串定义收集应用图片资源的文件夹名这些图片会被预处理并随应用一起构建使用方式见 AppsOnSDCard.md 的 FAP assets 章节。fap_extbuild支持应用的部分源码由外部工具构建包含一组ExtFile(path文件名, commandshell 命令)定义fbt会为列表中的每个文件执行对应命令。fal_embedded布尔值默认False仅适用于 PLUGIN 类型。若为True插件会作为资源嵌入宿主应用的.fap文件宿主启动时解压到apps_assets/APPID文件夹从而随宿主应用一并分发。fap_extbuild 与 Rust 构建示例外部构建命令在固件根目录执行所有中间文件必须放在应用的临时构建文件夹中。为此可借助fbt的模式展开${FAP_WORK_DIR}替换为应用临时构建文件夹路径${FAP_SRC_DIR}替换为应用源码文件夹路径也可使用fbt内部定义的其他变量。以下示例展示了如何从 Rust 源码构建应用引自 documentation/AppManifests.md#L64-L74sources[target/thumbv7em-none-eabihf/release/libhello_rust.a], fap_extbuild( ExtFile( path${FAP_WORK_DIR}/target/thumbv7em-none-eabihf/release/libhello_rust.a, commandcargo build --release --verbose --target thumbv7em-none-eabihf --target-dir ${FAP_WORK_DIR}/target --manifest-path ${FAP_SRC_DIR}/Cargo.toml, ), ),即先用cargo在临时目录中交叉编译出静态库再将其作为应用源码链接进.fap。fap_private_libs 与私有库示例fap_private_libs随应用以源码形式分发的额外库列表这些库会作为应用构建过程的一部分被编译。库源码必须放在应用源码文件夹内的lib子文件夹中。每个库通过调用Lib()函数定义参数如下name库文件夹名称。必填。fap_include_paths加入父应用 include 路径列表的库相对路径默认[.]即库源码根目录。sources收集库源码的文件名掩码列表路径相对库源码根目录默认[*.c*]。cflags构建该库时附加的编译器标志列表默认[]。cdefines构建该库时附加的预处理器定义列表默认[]。cincludes构建该库时附加的 include 路径列表路径相对应用根目录可用于为库代码提供外部搜索路径如配置头文件默认[]。以下示例引自 documentation/AppManifests.md#L89-L106同时声明了两个私有库fap_private_libs[ Lib( namembedtls, fap_include_paths[include], sources[ library/des.c, library/sha1.c, library/platform_util.c, ], cdefines[MBEDTLS_ERROR_C], ), Lib( nameloclass, cflags[-Wno-error], ), ],对于该片段fbt将构建两个库一个来自lib/mbedtls文件夹的源码另一个来自lib/loclass文件夹。对mbedtls库fbt会把lib/mbedtls/include加入应用 include 路径只编译sources列表指定的文件并为其源码启用MBEDTLS_ERROR_C预处理器定义对loclass库fbt会把lib/loclass加入应用 include 路径并构建该文件夹内全部源码同时禁用将编译警告视为错误这在编译大型第三方代码库时非常实用。两个库最终都会与应用链接。.fam 文件内容与完整实例.fam文件包含一个或多个应用定义。以下为 applications/services/bt/application.fam 的完整内容它同时展示了 STARTUP 与 SETTINGS 两种应用类型文档示例中的order70在仓库当前版本中为 40以仓库实际文件为准App( appidbt, nameBtSrv, apptypeFlipperAppType.SERVICE, entry_pointbt_srv, cdefines[SRV_BT], requires[ cli, dialogs, ], provides[ bt_start, bt_settings, ], stack_size1 * 1024, order20, sdk_headers[bt_service/bt.h, bt_service/bt_keys_storage.h], ) App( appidbt_start, apptypeFlipperAppType.STARTUP, entry_pointbt_on_system_start, order40, )这个实例覆盖了常见参数的典型用法requires声明运行依赖CLI 与对话框服务、provides提供对子组件启动钩子、设置应用的引用、sdk_headers导出供外部应用使用的头文件。仓库内其余.fam文件如 applications/examples/example_plugins/application.fam、applications/examples/example_adc/application.fam可作为编写清单的更多参考。fbt 对清单的处理流程结合 scripts/fbt/appmanifest.py 的源码fbt对清单的处理可归纳为以下流程加载与语法检查AppManager.load_manifest读取application.fam以exec方式执行其 Python 代码App()、ExtFile()、Lib()三个函数在此上下文注册。清单语法错误或未产生任何App()定义都会报错见 scripts/fbt/appmanifest.py#L175-L214。参数校验_validate_app_params按应用类型检查字段合法性PLUGIN 必须requires、禁止stack_size内建应用禁止 FAP 专属字段等__post_init__校验appid正则与fap_version格式。依赖解析AppBuildset._process_deps反复遍历应用集合将requires与provides指向的应用迭代加入集合直至不再新增见 scripts/fbt/appmanifest.py#L325-L334。外部应用归类_process_ext_apps按EXTERNAL_APP_TYPES_MAP收集外部应用并根据硬件目标兼容性分成可构建与不兼容两组。冲突检查_check_conflicts检查conflicts字段发现冲突即以App conflicts for ...中止构建_check_unsatisfied检查requires中缺失的应用。目标平台匹配_check_target_match确保选中应用均支持当前构建目标supports_hardware_target依据targets字段判断。插件分组_group_plugins将 PLUGIN 挂载到其requires指定的宿主应用名下供后续嵌入或菜单组织使用。构建配置层面fbt_options.py 中的FIRMWARE_APPS定义了default与unit_tests两套应用集合分别引用basic_services、main_apps、system_apps、settings_apps等元包 IDFIRMWARE_APP_SET选择实际使用的集合命令行可通过--extra-int-apps、--extra-ext-apps强制追加内建或外部应用详见 fbt.md。常见错误与排查建议Invalid appidappid包含大写字母、连字符等非法字符未匹配^[a-z0-9_]$。统一使用小写蛇形命名。Duplicate app declaration两个清单声明了相同appid全局唯一。Plugin ... cannot have stackPLUGIN 类型误设stack_size若需要独立栈应改用 EXTERNAL 类型。Plugin ... must have requiresPLUGIN 未声明宿主应用。App conflicts for ...构建集合中出现conflicts冲突组合需调整应用集合或移除冲突声明。Unsatisfied dependencies for ...requires引用的appid不存在检查拼写或确认该应用是否已声明清单。App manifest ... is malformed清单文件语法错误或未包含任何App()调用。Skipping ... due to target mismatch应用targets不含当前构建目标属预期跳过行为而非错误。这些校验信息大多直接来自 scripts/fbt/appmanifest.py 中的异常与提示文本遇到构建失败时可按提示逐项核对清单字段。【免费下载链接】flipperzero-firmwareFlipper Zero firmware source code项目地址: https://gitcode.com/GitHub_Trending/fl/flipperzero-firmware创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

从快速上手到三层弹性体系:OmniRoute 仓库 CLAUDE.md(巴西葡语版)技术指南深度解读

从快速上手到三层弹性体系:OmniRoute 仓库 CLAUDE.md(巴西葡语版)技术指南深度解读

从快速上手到三层弹性体系:OmniRoute 仓库 CLAUDE.md(巴西葡语版)技术指南深度解读 【免费下载链接】OmniRoute Never stop coding. Free MIT AI gateway: one endpoint, 352 providers (150 free), 1200 models Kimi, Claude, GPT, Gemini, …

📅 2026/9/14 7:55:46
深入剖析 ScyllaDB Commitlog 段文件格式:从文件头到碎片化条目的逐字节解析

深入剖析 ScyllaDB Commitlog 段文件格式:从文件头到碎片化条目的逐字节解析

深入剖析 ScyllaDB Commitlog 段文件格式:从文件头到碎片化条目的逐字节解析 【免费下载链接】scylladb NoSQL data store using the Seastar framework, compatible with Apache Cassandra and Amazon DynamoDB 项目地址: https://gitcode.com/GitHub_Trending/s…

📅 2026/9/14 7:50:46
数据驱动MPC与机组组合优化:预测、滚动求解与Matlab实现

数据驱动MPC与机组组合优化:预测、滚动求解与Matlab实现

简介:针对电力系统机组组合与模型预测控制交叉方向,这份Matlab项目案例提供了完整可运行的代码框架,适合自动化、电气工程、人工智能等相关专业学生与研究人员用于学习或二次开发。资源共29个文件,核心为16个.mat数据文件与11个.m…

📅 2026/9/14 7:50:46
MORE NEWS

更多资讯

📰

办公智能体Agent Suite落地指南:从架构设计到工作流实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

Edge-TTS 终极指南:5分钟零成本生成微软顶级语音

Edge-TTS 终极指南:5分钟零成本生成微软顶级语音 【免费下载链接】edge-tts Use Microsoft Edges online text-to-speech service from Python WITHOUT needing Microsoft Edge or Windows or an API key 项目地址: https://gitcode.com/GitHub_Trending/ed/edge-…

📰

智能客服系统应答模式与优化技术解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📰

C语言实现SNTP服务器:从报文解析到时间同步的完整实践

简介:SNTP(简单网络时间协议)作为NTP的轻量级简化实现,普遍应用于局域网设备的时间同步服务。这份以C语言编写的SNTP服务器程序源码包,面向需要了解网络时间同步底层原理的开发者,或希望在嵌入式系统及Wind…

📰

基于MATLAB GUI的车道线检测与定位系统设计与实现

简介:MATLAB开发的车道线检测定位系统,带有完整GUI图形界面,面向计算机、通信、人工智能、自动化等相关专业学生、教师及从业者,可支撑课程设计、大作业或毕业设计等场景。系统通过图像处理算法识别道路图像中的车道线&#xff0c…

📰

回溯算法详解:从全排列到子集问题

1. 回溯算法基础与全排列问题回溯算法是一种通过探索所有可能的候选解来找出所有解的算法。如果候选解被确认不是一个解(或者至少不是最后一个解),回溯算法会通过在上一步进行一些变化来丢弃该解,即"回溯"并尝试其他可能…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬