F Prime CMake 构建系统全景指南:`cmake/` 目录公共 API、文件布局与扩展约定
2026/9/15 17:37:25 网站建设 项目流程

F Prime CMake 构建系统全景指南:cmake/目录公共 API、文件布局与扩展约定

【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime

F Prime(F´)是一个面向飞行软件与嵌入式系统的组件化框架,其构建系统的全部核心逻辑集中在仓库根目录的cmake/目录中:它将 FPP 模型自动生成(autocode)为 C++ 源码,并把模块、单元测试与部署(deployment)组装成可执行目标。本文以 cmake/AGENTS.md 为骨架,结合 cmake/API.cmake、cmake/options.cmake、cmake/autocoder/autocoder.cmake 等源码与测试,系统讲解该构建系统的公共接口、目录职责、关键选项与扩展规范。读完本文,你将掌握如何在一个 F Prime 项目中正确注册模块/库/可执行文件/部署/单元测试,理解FPRIME_*选项的语义与默认值,并能在不破坏构建系统的前提下添加平台、工具链、选项与自定义构建阶段。

一、cmake/目录在 F Prime 中的角色

F Prime 的构建体系与普通 CMake 工程的一个关键差异是:它存在一个autocoding(自动代码生成)阶段。开发者在.fpp/.fppi模型文件中声明端口、组件、拓扑,构建系统在编译前把这些模型翻译成 C++ 源码,再连同手写实现一起编译链接。cmake/目录正是这一机制的实现载体——它定义了一套基于 CMake 的 DSL,负责:

  • 把 FPP 模型自动生成(autocoding)为 C++ 代码;
  • 组装模块(components/ports)、单元测试(UT)与部署(deployment);
  • 解析项目settings.ini、平台定义与交叉编译工具链;
  • 提供buildutinstalldictionarysbomversion等构建目标。

AGENTS.md 明确指出:cmake/API.cmake是唯一的外部接口。任何项目或模块的CMakeLists.txt所调用的函数都在该文件中定义,每个函数上方都有内联文档。完整的手册文档位于 docs/user-manual/build-system/,其中 cmake-api.md 讲解公共 API,cmake-implementations.md 讲解内部实现,建议从这两篇开始阅读。

二、公共 API:register_fprime_*函数族

cmake/API.cmake中定义的函数构成 F Prime 构建系统的对外契约。AGENTS.md 给出的速查表如下,它是理解整个构建系统的入口:

函数用途
register_fprime_module注册一个模块(组件/端口库),使其获得 autocoding 能力。
register_fprime_library注册一个不需要 autocoding 的普通库。
register_fprime_executable注册一个可执行文件。
register_fprime_deployment注册一个部署(拓扑加二进制)。
register_fprime_ut注册模块的单元测试。
register_fprime_config注册一个配置模块。
add_fprime_subdirectory向构建添加一个目录(替代add_subdirectory)。
register_fprime_implementationregister_os_implementation为抽象接口提供实现(Os/大量使用)。
register_fprime_targetregister_fprime_ut_targetregister_fprime_build_autocoder添加自定义构建阶段或自动编码器。

register_fprime_module在源码中只是register_fprime_library的向后兼容别名(cmake/API.cmake#L227-L229),历史变量SOURCE_FILESMOD_DEPS等虽然仍受支持,但官方建议改用指令式参数。所有register_fprime_*函数(register_fprime_library/executable/deployment/ut/config)共享同一套调用格式,支持以下指令:

  • SOURCES:源文件列表;
  • AUTOCODER_INPUTS:需要交给自动编码器处理的模型文件(.fpp等);
  • DEPENDS:链接依赖(库、-l参数);
  • HEADERS:头文件列表;
  • LINK_DEPENDS:额外文件(如链接脚本.ld),当其变化时触发重编译。

register_fprime_library为例(cmake/API.cmake#L178-L195):

register_fprime_library( MyFprimeModule SOURCES source1.cpp source2.cpp AUTOCODER_INPUTS model.fpp DEPENDS -lm HEADERS module.h LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/extra_file.ld )

register_fprime_executableregister_fprime_deployment的格式完全相同,区别在于:

  • register_fprime_executable底层委托add_executable,且不再支持EXECUTABLE_NAME变量(传入会触发致命错误,见 cmake/API.cmake#L288-L290);
  • register_fprime_deployment注册的是"拓扑+二进制"整体,支持在依赖树范围内运行 targets(例如对一个部署用到的所有组件跑一遍单元测试),在未设置FPRIME_CURRENT_MODULE时回退到PROJECT_NAME(cmake/API.cmake#L355-L364)。

register_fprime_ut只在启用测试时创建目标:当BUILD_TESTING为 OFF 时函数直接返回、不生成任何目标(cmake/API.cmake#L543-L552),这保证了正式部署构建不会携带测试目标。

2.1 配置模块与覆盖机制

register_fprime_config额外支持CONFIGURATION_OVERRIDES指令,用于覆盖此前配置模块(默认配置、库配置)提供的同名配置文件,例如覆盖FpConfig.fppFpConfig.hpp(cmake/API.cmake#L411-L425):

register_fprime_config( MyFprimeConfig SOURCES config.cpp AUTOCODER_INPUTS config.fpp HEADERS config.hpp CONFIGURATION_OVERRIDES FpConfig.fpp FpConfig.hpp )

其内部实现值得注意(cmake/API.cmake#L450-L507):

  • 配置模块以STATIC 库形式构建(提供SOURCES/AUTOCODER_INPUTS时自动追加STATIC),以便与Fw_Types等基础库之间建立相互依赖而不受库类型限制;
  • 所有配置源(SOURCES/HEADERS/AUTOCODER_INPUTS)会被拷贝进构建缓存再参与编译;
  • 覆盖文件按 CMakeLists.txt 树中的检测顺序生效:platform → fprime config → library → project;
  • 覆盖文件会被拷入被覆盖模块原始构建位置,从而保留原始构建模块的设置;
  • 当标记BASE_CONFIG时,配置模块被链接进全局接口目标,整个构建系统的所有模块都能访问该配置。

仓库 cmake/test/data/TestConfigDeployment 就是针对该机制的完整测试样例:其override/project/下同时放置了FpConfig.fppDpCfg.hpp等覆盖文件与settings.ini

2.2 实现(implementation)机制

register_fprime_implementation用于声明某个实现库实现了某个接口(IMPLEMENTS指令),结果总是 OBJECT 库,以确保在链接期按预期覆盖(cmake/API.cmake#L680-L729):

register_fprime_implementation( MyImplementation IMPLEMENTS SomeImplementationInterface SOURCES source1.cpp source2.cpp AUTOCODER_INPUTS model.fpp HEADERS module.h )

IMPLEMENTS必须且只能传一个接口名,否则触发致命错误;同一模块的实现声明前后不得变更。register_os_implementation则是Os/目录用来注册操作系统层实现的便捷封装(File;Directory;FileSystem这类命名列表 + 后缀如Posix)。

2.3 目录添加与构建图

add_fprime_subdirectory替代原生add_subdirectory,核心价值在于两点(cmake/API.cmake#L92-L150):

  1. 自动化binary_dir参数:F Prime 子目录有特定的二进制根,以避免冲突,并保证标准的#include路径以仓库根为起点;
  2. 构建图构造:所有被add_fprime_subdirectory引入的目录共同构成"超图"(super-graph),CMake 的依赖系统会从该超图中剪裁出每个可执行/模块/库实际需要的子图。因此,把一个暂未使用的子目录加进来并不会导致多余编译,但任何代码都必须出现在这个超图中才能被构建

2.4 自定义目标与自动编码器注册

register_fprime_target允许用户把自定义构建阶段注册进系统:传入一个 CMake 文件路径(或 include 路径),该文件必须定义add_global_targetadd_module_targetadd_deployment_target三个函数(cmake/API.cmake#L578-L593)。register_fprime_ut_target与其行为一致,但仅在BUILD_TESTING=ON时生效。register_fprime_build_autocoder则注册自定义自动编码器,被注册的 CMake 文件必须满足三个条件(cmake/API.cmake#L639-L656):

  1. 在文件作用域调用autocoder_setup_for_individual_sources()autocoder_setup_for_multiple_sources()
  2. 实现<autocoder 名>_is_supported(AC_POSSIBLE_INPUT_FILE),返回该自动编码器是否处理给定输入文件;
  3. 实现<autocoder 名>_setup_autocode(AC_INPUT_FILE)完成实际的代码生成。

cmake/autocoder/下的fpp.cmakefpp_ut.cmake正是以该协议接入的标准 FPP 自动编码器。

三、文件布局:cmake/内部各文件职责

AGENTS.md 给出了一张"哪里放什么"的完整地图,是进入源码前的最佳索引:

路径内容
API.cmake公共 API(见上文)。
FPrime.cmakeFPrime-Code.cmakeFPrimeConfig.cmake项目 include 以搭建构建的入口点。
options.cmake全部FPRIME_*构建选项与路径(FPRIME_ENABLE_*、sanitizers、BUILD_TESTING、框架与库位置)。新增选项前先看这里。
module.cmakeglobal_interface.cmakeflags.cmakeutilities.cmake内部实现:模块、接口与编译标志如何组装。
settings.cmakesettings/解析项目settings.ini
target/构建目标与阶段:buildutinstalldictionarysbomversion,外加sub-build/tools/
autocoder/FPP 自动编码器集成:fpp.cmakefpp_ut.cmakeautocoder.cmake与辅助scripts/
platform/平台定义(Linux.cmakeDarwin.cmakeunix/)及新建平台的platform.cmake.template
toolchain/交叉编译工具链(arm-*-linuxaarch64-*raspberrypi)及toolchain.cmake.template
config_assembler.cmake组装构建所用的配置头文件。
sanitizers.cmake单元测试的 Address/Leak/UB/Thread sanitizer 接线。
sub-build/用于 setup 与工具工作的嵌套 CMake 调用。
test/构建系统自身的测试。
docs/sdd.md构建系统的设计文档。

这些文件在仓库中均可一一对应找到:入口点在 cmake/FPrime.cmake、cmake/FPrime-Code.cmake、cmake/FPrimeConfig.cmake;内部实现在 cmake/module.cmake、cmake/global_interface.cmake、cmake/flags.cmake、cmake/utilities.cmake;配置解析在 cmake/settings.cmake 与 cmake/settings/ini.cmake。

target/目录下实际包含dictionary.cmake(生成命令字典)、ut.cmake(单元测试运行)、install.cmake/fprime_install.cmake(安装)、sbom.cmake(软件物料清单)、version.cmake(版本信息)、refresh_cache.cmaketarget.cmake(目标基础设施),以及tools/下的property_writer.pyarguments-from-file.pyredirector.pycat.py等辅助脚本。构建系统自身的测试位于 cmake/test,其中src/下按功能拆分为test_basic.pytest_config.pytest_autocoder.pytest_implementation.pytest_target_triple.py等 Python 测试,data/下则是一系列可独立配置的测试工程(如TestDeploymentTestConfigDeploymentTestFlagsProject)。

四、FPRIME_*构建选项详解

cmake/options.cmake集中定义了全部构建选项。其文件头明确指出:绝大多数用户无需显式指定任何选项即可构建 F Prime;只有当需要非标准构建行为时才用-D<OPTION>=<VALUE>(通常为ON/OFF)传入。以下选项与默认值均直接取自源码(cmake/options.cmake):

选项默认值作用
CMAKE_DEBUG_OUTPUTOFF输出 F Prime CMake 集成层的调试信息,便于排查构建问题;不影响 CMake 自身。
FPRIME_CMAKE_QUIETOFF关闭模块注册、目标注册、自动编码器注册等状态消息;不影响错误/警告消息。
FPRIME_USE_STUBBED_DRIVERS由平台文件决定ON 时使用Drv包中的桩驱动(serial 与 ipv4 驱动除外);仅接受 ON/OFF/不设置。
FPRIME_USE_BAREMETAL_SCHEDULER由平台文件决定ON 时使用裸机调度器(单上下文,循环调度活动组件),用于无 OS 系统或在 PC 上验证单线程执行。
FPRIME_ENABLE_FRAMEWORK_UTSON是否把框架自身的单元测试加入目标列表;不影响项目自己的 UT。
FPRIME_ENABLE_AUTOCODER_UTSOFF在框架 UT 基础上,是否启用自动编码器工具的 UT(验证工具运行而非产品代码正确性)。
FPRIME_ENABLE_UT_COVERAGEON是否计算单元测试覆盖率;关闭可提升 UT 性能并移除覆盖率目标。
FPRIME_ENABLE_DIRECT_PORT_CALLSOFFON 时拓扑端口连接改用直接函数调用(会禁用 UT,因为 UT 不支持直接端口调用);OFF 时通过函数指针调用。
FPRIME_ENABLE_TEXT_LOGGERSON是否把ActiveTextLogger/PassiveConsoleTextLogger组件纳入构建;关闭后可同时取消FW_ENABLE_TEXT_LOGGING以节省空间(开启时若FW_ENABLE_TEXT_LOGGING=0会构建失败)。
FPRIME_ENABLE_JSON_MODEL_GENERATIONOFFON 时对所有模块运行fpp-to-json生成 JSON 模型,可能需要 Java 及 FPP 的 jar 版本。
FPRIME_SKIP_TOOLS_VERSION_CHECKOFF跳过 F Prime 工具版本检查(高级选项,供维护自定义工具变体时使用;不匹配将不再被报告)。
FPRIME_CHECK_FRAMEWORK_VERSIONOFF仅供内部使用,在打 tag 时校验框架版本已更新。
FPRIME_INSTALL_STATIC_LIBRARIESON是否把静态库安装到 build-artifacts(共享库安装始终开启)。
FPRIME_INSTALL_DEST${PROJECT_SOURCE_DIR}/build-artifactsfprime_install.cmake在环境未设置DESTDIR时使用的默认安装目录。

另有与路径相关的FPRIME_LIBRARY_LOCATIONSFPRIME_FRAMEWORK_LOCATIONS以及标准 CMake 的BUILD_TESTINGCMAKE_TOOLCHAIN_FILE(默认使用本机构建)等。工具链文件放在框架或库的cmake/toolchain/目录,例如-DCMAKE_TOOLCHAIN_FILE=/path/to/cmake/toolchain/arm-hf-linux.cmake

五、扩展约定:平台、工具链、选项与构建阶段

AGENTS.md 明确了四类扩展必须遵循的规范,这是为 F Prime 做贡献或定制时的"红线":

  1. 新增平台或工具链:复制对应的.template文件(cmake/platform/platform.cmake.template、cmake/toolchain/toolchain.cmake.template)作为起点,而不是照抄已有定义,并遵循 cmake-platforms.md 或 cmake-toolchains.md。仓库已有arm-hf-linuxarm-sf-linuxaarch64-linuxaarch64-clang-linuxraspberrypi等工具链定义可作参考。

  2. 新增选项:必须在 cmake/options.cmake 中用option()set(... CACHE ...)声明,并在 settings.md 中与其他FPRIME_*设置一同记录。注意选项校验模式:如FPRIME_USE_STUBBED_DRIVERS仅接受 ON/OFF/不设置,否则message(FATAL_ERROR)

  3. 新增构建阶段:在cmake/target/下实现,并通过register_fprime_target注册,参见 cmake-targets.md。自定义目标文件必须提供add_global_targetadd_module_targetadd_deployment_target三个函数。

  4. 通用守则

    • 在子构建(sub-build)上下文中不适合执行的代码使用skip_on_sub_build()宏提前返回(其通过检查FPRIME_IS_SUB_BUILD实现,见 cmake/API.cmake#L33-L37);
    • 只支持部分平台/工具链/特性的模块使用restrict_platforms()宏,其接受平台名(如LinuxDarwin)、具体工具链名(如aarch64-linux)或特性集(如SOCKETS,会检查FPRIME_HAS_SOCKETSPosix对应旧式FPRIME_USE_POSIX)。当平台不受支持时,模块会被记录进RESTRICTED_TARGETS全局属性并从当前CMakeLists.txt提前返回(cmake/API.cmake#L59-L90);
    • 自动生成的代码永远存放在构建缓存(build-fprime-*/)中,它们是构建产物,不得手工编辑或提交到版本库。

六、Autocoding 的底层运转:从模型到编译源

理解自动编码器如何被驱动,能帮你正确编写AUTOCODER_INPUTS与自定义自动编码器。cmake/autocoder/autocoder.cmake 提供了两层调度:

  • run_ac_set(L28-L80):对一组自动编码器做串行调度,把上一个自动编码器生成的AUTOCODER_GENERATED_AUTOCODER_INPUTS追加为下一个的输入,从而支持"链式"代码生成;
  • run_ac(L92-L120):单个自动编码器的执行单元。它对源文件做规范化与过滤,通过输入哈希string(SHA1 ...))判断输入集是否变化,未变化则复用上次结果、跳过执行;执行后把生成文件、新增依赖写入目标的AC_GENERATEDSOURCESLINK_LIBRARIES等属性。

值得注意的细节:生成文件必须被 CMake 标记为GENERATEDrun_ac_set末尾会断言这一点(L67-L72);同时构建结束时_validate_all_autocoder_inputs_handled会校验每个用户提供的AUTOCODER_INPUT至少被一个自动编码器消费,避免模型文件被静默忽略。

七、修改公共 API 的配套要求

AGENTS.md 强调:修改cmake/API.cmake时,必须同步更新函数上方的内联文档与 cmake-api.md。这是因为该文件既是实现又是文档,二者脱节会直接破坏"面向 Agent/开发者的唯一入口"这一设计前提。同理,新增选项要同步 settings.md,新增平台/工具链要同步对应指南,新增构建阶段要同步 cmake-targets.md。

八、进一步阅读

  • 构建系统入门:01-cmake-intro.md
  • 公共 API 手册:cmake-api.md
  • 内部实现剖析:cmake-implementations.md
  • 平台与工具链:cmake-platforms.md、cmake-toolchains.md
  • 自定义目标:cmake-targets.md
  • 单元测试构建:cmake-uts.md
  • 设置项手册:settings.md
  • 构建系统设计文档:cmake/docs/sdd.md
  • 真实模块的CMakeLists.txt范例可参考 Drv/LinuxGpioDriver/CMakeLists.txt 与 Fw/Buffer/CMakeLists.txt 等框架内模块。

F Prime CMake 文件组织关系

总而言之,cmake/目录是 F Prime 构建体系的"单一事实来源":API.cmake定义了对外契约,options.cmakesettings/定义了配置空间,target/autocoder/platform/toolchain/分别承载构建阶段、代码生成、平台与交叉编译能力。无论你是要为 F Prime 新增一个组件、接入一块新硬件,还是想深入定制构建流程,先读懂 AGENTS.md 这份导航图,再按图索骥进入对应源码与手册,就能快速找到正确的扩展点。

【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址: https://gitcode.com/GitHub_Trending/fpr/fprime

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询