嵌入式系统编程【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址https://gitcode.com/gh_mirrors/fpri/fprime点击查看免费下载F´F Prime是一个面向飞行软件与嵌入式系统的开源框架其 CMake 构建系统在标准 CMake 之上提供了模块注册、自动编码autocoding、单元测试与部署构建等一整套机制。然而任何构建系统都无法覆盖所有项目的全部需求——当你需要为部署追加一个依赖 F´ 代码的辅助工具、注册一个类似make dict的自定义构建目标或者把使用其他构建系统的外部库纳入构建流程时就需要对 F´ 的 CMake 系统进行定制。本文以 docs/UsersGuide/cmake/Customization.md 为骨架结合仓库内 cmake/API.cmake、cmake/target/target.cmake 等源码实现完整讲解这三类自定义场景的标准做法、hook 函数规范与实际可运行的示例帮助你掌握在 F´ 构建系统中安全、可维护地开洞的能力。一、自定义的基本思路CMake 即底层能力在动手之前需要明确一个前提F´ 的构建系统归根结底是 CMake。Customization.md 开篇就强调这套系统赋予了用户很强的能力——只要是标准 CMake 模式能实现的事情在 F´ 中几乎都能实现如果本文的示例没有覆盖到你的需求建议先去系统学习 CMake 本身。结合源码可以更清楚地看到标准 CMake 之上的 F´ 封装是如何落地的F´ 通过add_fprime_subdirectory替代原生add_subdirectory来组织目录见 cmake/API.cmake 中该函数的实现它会自动计算 binary 目录并保持 F´ 的 include 路径结构模块、可执行文件、部署、单元测试分别通过register_fprime_module、register_fprime_executable、register_fprime_deployment、register_fprime_ut注册底层最终都会调用add_library/add_executable等原生 CMake 命令见 cmake/module.cmake 的generate_base_module_properties自定义目标与自定义自动编码器则通过register_fprime_target、register_fprime_build_autocoder注入见 cmake/API.cmake。因此所有自定义工作本质上都是在这些注册点与原生 CMake 命令之间插入自己的代码。自定义代码应该放在哪里部署的顶层CMakeLists.txt是一个关键插入点。从 cmake/deployment-CMakeLists.txt.template 可以看到部署文件的经典三段式结构# Section 1: 基础项目设置 project(Ref C CXX) cmake_minimum_required(VERSION 3.15) # Section 2: 引入 F prime 核心构建系统 include(PATH-TO/cmake/FPrime.cmake) # NOTE: 自定义 target 在此处注册两条 include 之间 include(PATH-TO/cmake/FPrime-Code.cmake) # Section 3: 引入部署相关的组件与拓扑 add_fprime_subdirectory(PATH-TO-MODULE) ... add_fprime_subdirectory(PATH-TO-TOP)模板中明确注释自定义 target 应注册在FPrime.cmake与FPrime-Code.cmake两条 include 之间。真实部署 Ref/CMakeLists.txt 正是这样做的include(${CMAKE_CURRENT_LIST_DIR}/../cmake/FPrime.cmake) # NOTE: register custom targets between these two lines include(${CMAKE_CURRENT_LIST_DIR}/../cmake/FPrime-Code.cmake)原因也很直接FPrime.cmake负责导入整个构建系统 API 与选项FPrime-Code.cmake见 cmake/FPrime-Code.cmake负责把 Fw、Svc、Os、Drv、CFDP、Utils 等框架核心目录加入构建。目标文件必须先于模块被注册才能让后续每个模块在定义时被挂上对应的模块级目标——如果注册晚了cmake/target/target.cmake 中的register_fprime_list_helper会直接抛出FATAL_ERRORCannot register fprime target after including subdirectories or FPrime-Code.cmake。二、构建依赖 F´ 代码的工具可执行文件Utilities如果你要写一个需要链接 F´ 模块、使用 F´ 端口或类型的辅助工具例如自定义的字典生成器、代码检查工具、日志分析器等最直接的方式是调用register_fprime_executable注册一个工具可执行文件。2.1 基本用法register_fprime_executable的定义与完整参数说明在 cmake/API.cmake 中其要求或可选的变量包括变量必填说明EXECUTABLE_NAME可选可执行文件的名称若不设置也未传参则使用PROJECT_NAME或由模块名推导SOURCE_FILES是与MOD_DEPS至少其一源文件与自动编码输入*Ai.xml、*.fpp、*.c、*.cpp等的列表会被自动拆分为自动编码输入与手写源码两类MOD_DEPS可选无法从 include 图自动推断的非标准链接依赖例如其他模块名或-lpthread这类链接标志Customization.md 特别提醒调用该函数前必须先把EXECUTABLE_NAME设置好以指定工具的名称。一个最小示例set(EXECUTABLE_NAME my_tool) set(SOURCE_FILES ${CMAKE_CURRENT_LIST_DIR}/my_tool.cpp ${FPRIME_FRAMEWORK_PATH}/Svc/CmdDispatcher/CmdDispatcherComponentAi.xml ) set(MOD_DEPS Fw_Types -lpthread ) register_fprime_executable()从实现看register_fprime_executable在 cmake/API.cmake 中首先检查SOURCE_FILES或MOD_DEPS是否已定义否则报错随后按EXECUTABLE_NAME→ 位置参数 → 模块名的优先级确定可执行文件名最后交给generate_executable→generate_base_module_properties创建add_executable目标见 cmake/module.cmake。2.2 与部署可执行文件的区别register_fprime_executable不用于注册部署二进制如整个 flight software 镜像部署应使用register_fprime_deployment见 cmake/API.cmake。两者的核心区别register_fprime_deployment会以PROJECT_NAME作为可执行文件名并且会自动运行部署级目标例如生成字典dict从而保证标准部署产物齐备register_fprime_executable只生成一个命名的工具二进制不触发部署级目标工具目标构建后会自动安装到由FPRIME_INSTALL_DEST变量指定的构建产物目录可执行文件进入${TOOLCHAIN_NAME}/bin库进入lib与lib/static参见 cmake/target/install.cmake。2.3 依赖工具时的注意事项cmake/API.cmake 的 Caveats 一节还给出了一条重要约束不要把可执行目标放进MOD_DEPS例如传给register_fprime_deployment否则多个可执行文件在最终链接时可能因为各自的main定义冲突而失败而且这类错误与 CMake 定义顺序相关、时隐时现。正确做法是只建立 CMake 层面的依赖set(SOURCE_FILES tool.c) register_fprime_executable(TOOL) ... register_fprime_deployment(MY_DEPLOYMENT) add_dependencies(MY_DEPLOYMENT TOOL) # 仅 CMake 依赖不参与链接2.4 用独立的 tools 部署只构建工具Customization.md 建议如果工具较多、又不希望每次都被部署构建连带编译可以单独建立一个 tools 部署在其中只注册工具可执行文件从而仅构建这些工具。这正好利用了 F´ 模块按需构建的特性——每个工具目标的依赖子图会被单独解析未被依赖的模块不会真正编译cmake/API.cmake 中add_fprime_subdirectory的注释说明CMake 依赖系统会阻止多余的构建。三、自定义构建目标Make Targetshook 模式这是 Customization.md 的篇幅核心为构建系统添加自定义的全局/模块级构建目标在 GNU Make 生成器下体现为make target与make MODULE_target。例如你需要一个统计源码行数的目标、一个汇总各模块文件的sloc目标或者一个在所有模块上运行自定义脚本的lint目标。3.1 hook 模式的三步流程按照 Customization.md 与 cmake/target/target.cmake 的规范注册自定义目标需要三步创建目标定义文件.cmake在其中定义两个函数add_global_target向顶层添加全局目标对应make dict这样的全局命令add_module_target为每个模块添加模块级子目标对应make MODULE_dict这样的按模块命令。目标文件还必须定义add_deployment_target可以为空实现用于响应register_fprime_deployment的部署级回调——setup_single_target会对每个模块按FP_TYPE属性决定调用add_module_target还是add_deployment_target两者必须都存在。用register_fprime_target注册该文件宏定义见 cmake/API.cmakeregister_fprime_target(${CMAKE_CURRENT_LIST_DIR}/cmake/my_target.cmake)Customization.md 同时指出如果你的目标不需要每个模块一份 全局一份的双层结构也可以直接在目标文件里调用add_custom_target添加单个目标。3.2 两个 add 函数的签名与职责cmake/target/target.cmake 对这两个函数给出了严格的参数规范add_global_target(TARGET_NAME)添加全局目标。TARGET_NAME必须被传递给一次add_custom_target调用如果希望该目标随makeall默认构建就给add_custom_target传入ALL参数。add_module_target(MODULE_NAME TARGET_NAME AC_INPUTS SOURCE_FILES AC_OUTPUTS MOD_DEPS)为每个模块添加子目标。参数含义为MODULE_NAME正在构建的模块名TARGET_NAME目标名模块级目标一般命名为${MODULE_NAME}_${TARGET_NAME}AC_INPUTS自动编码输入Ai.xml文件列表SOURCE_FILES手写源码*.cpp、*.hppAC_OUTPUTS自动编码输出Ac.cpp、Ac.hppMOD_DEPS模块声明的依赖列表。若你的目标命令依赖自动编码产物应通过DEPENDS依赖AC_OUTPUTS确保自定义命令在自动编码步骤之后执行。命名辅助函数get_target_name会把目标文件名去.cmake后缀作为全局目标名并在传入模块名时生成${MODULE}_${TARGET}的模块级名字。也就是说若目标文件名为dict.cmake则全局目标叫dict各模块的子目标叫MODULE_dict。3.3 原文档示例裸全局目标Customization.md 给出的完整示例是注册一个直接复制字典产物到源码目录的全局目标add_custom_target( dict COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_BINARY_DIR}/dict/serializable ${CMAKE_SOURCE_DIR}/py_dict/serializable COMMAND ${CMAKE_COMMAND} -E touch ${CMAKE_SOURCE_DIR}/py_dict/serializable/__init__.py )注意这里用CMAKE_COMMAND -E执行文件系统操作copy_directory、touch而不是硬编码 shell 命令这保证了跨平台可移植性——这也是 F´ 内置目标的一贯风格例如 cmake/target/check.cmake 中删除.gcda覆盖率数据文件也是用${CMAKE_COMMAND} -E chdir ... find ...实现的。运行方式原文示例仓库内存在可验证的 Ref 部署cmake ../Ref make dict即先对Ref部署执行 CMake 配置再通过make dict触发该自定义目标。3.4 源码级示例F´ 内置目标是怎么写的仓库cmake/target/目录下自带一套按同一 hook 模式实现的内置目标是最好的学习范本dictcmake/target/dict.cmake——字典目标。它把全局与部署级函数留空只实现add_module_targetfunction(dict_add_global_target) endfunction() function(dict_add_deployment_target) endfunction() function(dict_add_module_target MODULE TARGET SOURCES DEPENDENCIES) get_target_name(${TARGET} ${MODULE}) run_ac_set(${SOURCES} autocoder/fpp autocoder/ai_xml) set(DICTIONARY ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}TopologyAppDictionary.xml) foreach(FILE IN LISTS AC_GENERATED) if (FILE STREQUAL DICTIONARY) set_property(GLOBAL PROPERTY DICTIONARY_FILE ${DICTIONARY}) break() endif() endforeach() endfunction(dict_add_module_target)其注释解释了关键设计字典按部署per-deployment生成全局变体没有意义实际生成工作由拓扑模块承担模块级函数只需要确认字典文件出现在自动编码输出中并把其路径记录到全局属性DICTIONARY_FILE供后续install目标把字典安装到${TOOLCHAIN_NAME}/dict目录见 cmake/target/install.cmake。implcmake/target/impl.cmake——实现模板生成目标展示了只做模块级、不做全局的模式function(impl_add_module_target MODULE TARGET SOURCE_FILES DEPENDENCIES) get_target_name(${TARGET} ${MODULE}) run_ac_set(${SOURCE_FILES} autocoder/fpp autocoder/ai_impl) add_custom_target(${TARGET_MOD_NAME} DEPENDS ${AC_GENERATED}) endfunction(impl_add_module_target)它运行 fpp 与 ai_impl 自动编码器产出模板文件并以DEPENDS ${AC_GENERATED}建立对自动编码输出的依赖——正是 3.2 节规范的直接体现。versioncmake/target/version.cmake——演示了带ALL的全局目标随默认构建执行并利用add_custom_target的BYPRODUCTS、copy_if_different来生成version.hpp可视为自定义目标生成头文件的参考模板。check与utcmake/target/check.cmake、cmake/target/ut.cmake——分别演示了全局目标用${CMAKE_CTEST_COMMAND}跑测试、以及模块级目标按FPRIME_UTS属性聚合单元测试依赖的做法。fpp_locscmake/target/fpp_locs.cmake——一个特殊目标它不生成普通的 per-module 命令而是在add_global_target中一次性完成 FPP 位置索引locs.fpp与依赖缓存的预生成用于解决 FPP 依赖分析的性能问题。这些内置目标的完整清单与说明可参考 docs/UsersGuide/cmake/Targets.md 与 docs/UsersGuide/cmake/cmake-api.md。3.5 仅测试可用的目标register_fprime_ut_target与register_fprime_target配套cmake/API.cmake 还提供了register_fprime_ut_target注册的 UT 目标只在BUILD_TESTINGON时创建。其内部逻辑是UT 目标是唯一会在单元测试模块上运行的目标见 cmake/target/target.cmake 中setup_module_targets对FPRIME_UT_TARGET_LIST的处理——单元测试模块只挂 UT 目标部署模块则额外追加 UT 目标。覆盖率MODULE_coverage这类依赖 gcov 与CMAKE_BUILD_TYPETESTING的目标即属此类见 docs/UsersGuide/cmake/Targets.md。四、外部库与其他构建系统的集成当项目需要引入一个使用独立构建系统如 autotools、自定义 Makefile的外部库时Customization.md 给出了两种标准方案。4.1 方案一add_subdirectory 自定义命令直接用 CMake 的add_subdirectoryF´ 场景下可改用add_fprime_subdirectory把外部库目录加入构建然后在该目录的CMakeLists.txt中调用add_custom_target适用于构建产物不直接作为链接输入的场景只建立先构建的顺序依赖例如库提供的是运行期脚本或数据add_custom_command适用于需要访问输出文件的场景例如库编译出的静态库/头文件要作为后续目标输入通过OUTPUT/DEPENDS建立真正的文件级依赖。选择依据一句话概括系统是否直接依赖该命令产生的文件。需要文件参与编译链接就用add_custom_command否则用add_custom_target更简单。4.2 方案二ExternalProject_Add当外部库需要下载、版本控制checkout 特定版本以及独立的构建步骤时应改用 CMake 的ExternalProject模块ExternalProject_Add命令。它适合真正的第三方项目在配置/构建阶段拉取源码、执行其自身的构建流程最终将产物纳入 F´ 构建。仓库中其实就有一个下载外部项目再接入构建的现实案例F´ 在启用单元测试时通过 cmake/googletest-download/googletest.cmake 在配置期下载并构建 GoogleTest——先用configure_file生成下载用的CMakeLists.txt再用execute_process执行 CMake 完成拉取最后add_subdirectory将 gtest 目标加入构建EXCLUDE_FROM_ALL避免其进入默认构建。该文件在 cmake/FPrime-Code.cmake 中被条件包含if (BUILD_TESTING AND NOT DEFINED FPRIME_PRESCAN) include(${FPRIME_FRAMEWORK_PATH}/cmake/googletest-download/googletest.cmake) add_subdirectory(${FPRIME_FRAMEWORK_PATH}/STest/ ${CMAKE_BINARY_DIR}/F-Prime/STest) endif()从源码结构看这正是ExternalProject 式下载 add_subdirectory 接入的组合实践可作为集成外部依赖时的参考路径。五、实践清单与注意事项综合文档与源码落地自定义 CMake 时建议遵循以下要点注册时机自定义 target 文件放在部署CMakeLists.txt的两条 includeFPrime.cmake与FPrime-Code.cmake之间注册见 cmake/deployment-CMakeLists.txt.template三函数齐全目标文件必须定义add_global_target、add_module_target、add_deployment_target后两者可为空实现否则setup_global_target的plugin_include_helper路由会失败见 cmake/target/target.cmake全局目标必须过add_custom_targetTARGET_NAME必须传给add_custom_target需要随默认构建运行时加ALL参数依赖自动编码产物模块级命令若需要Ac.cpp/Ac.hpp务必通过DEPENDS ${AC_GENERATED}挂依赖参考 cmake/target/impl.cmake工具目标不放进MOD_DEPS可执行文件之间的依赖用add_dependencies建立见 cmake/API.cmake 的 Caveats优先CMAKE_COMMAND -E而非裸 shell 命令保证跨平台参考 cmake/target/check.cmake文件操作示例目录复制与占位文件创建可仿照 Customization.md 的dict示例用-E copy_directory与-E touch完成外部库二选一产物不被直接依赖 →add_custom_target产物作为输入 →add_custom_command需要下载/版本控制/独立构建 →ExternalProject_Add。结语F´ 的 CMake 系统是一个标准 CMake 之上的薄封装 插件化目标体系register_fprime_executable让你轻松产出依赖 F´ 代码的工具register_fprime_target hook 文件add_global_target/add_module_target/add_deployment_target让你按统一模式接入全局与模块级构建目标仓库内置的dict、impl、check、install、version、fpp_locs等目标cmake/target/ 目录就是最直接的学习范本而add_custom_command/ExternalProject_Add则覆盖了外部构建系统的集成需求。掌握这些模式之后任何标准构建系统没提供的项目级需求都可以用标准 CMake 方式在 F´ 中安全地实现。赞分享嵌入式系统编程【免费下载链接】fprimeF´ - A flight software and embedded systems framework项目地址https://gitcode.com/gh_mirrors/fpri/fprime点击查看免费下载相关推荐F´ 飞行软件框架 CMake 定制指南自定义工具、构建目标与外部库集成F´ 飞行软件框架 CMake 定制指南自定义工具、构建目标与外部库集成 导读 F´F Prime飞行软件框架内置了一套完整且高度自动化的 CMake 构嵌入式系统编程F´ CMake 定制实战工具程序、自定义 Make Target 与外部库集成全指南F´ CMake 定制实战工具程序、自定义 Make Target 与外部库集成全指南 F´F Prime飞行软件与嵌入式系统框架提供了一套基于 CMak嵌入式系统编程如何用taskt免费RPA工具实现Windows自动化零代码桌面机器人终极指南如何用taskt免费RPA工具实现Windows自动化零代码桌面机器人终极指南 taskt是一款完全免费开源的Windows桌面自动化工具基于C 和.NET嵌入式系统编程上一篇reFlutter终极Flutter逆向工程框架让动态分析变得前所未有的简单下一篇lint-staged 中的标准输入处理逻辑readStdin.js 深入创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
企业数字化 ERP 产品动态
相关推荐
BullMQ Pro 安装指南:NPM Token、私有 Registry 配置与 Pro 类使用 后端消息队列任务调度 【免费下载链接】bullmq BullMQ - Message Queue and Batch processing for NodeJS, Python, .NET, Elixir, Rust and PHP based on Redis or PostgreSQL 项目地址: https://gitcode.com/gh_mirrors/bu/bullmq 点击查看 免费下载 本文基于 do… · 2026/9/25 3:11:21
Codex辅助论文写作全流程:从文献检索到LaTeX排版实战 1. 论文辅助工具链的选型逻辑与整体架构1.1 为什么是 Codex 而不是传统写作软件写论文这件事,真正耗时间的从来不是"打字",而是信息检索、结构梳理、公式推导、代码验证、格式校对这五件事的反复循环。传统写作软件(Word、LaTeX 编… · 2026/9/25 3:11:15
PixVerse会员试用GPT Image 2.5:图像生成成本与实操指南 1. 拆解“PixVerse 会员试用 GPT Image 2.5”背后的真实需求1.1 这个标题到底在说什么先把话说直白一点:这个标题的核心信息量其实集中在两个点上——PixVerse 的会员体系和GPT Image 2.5 的图像生成能力。很多人第一次看到这个组合会有点懵,因为 PixVer… · 2026/9/25 4:52:42
DCPcrypt2在Delphi12.3下的AES文件加密与哈希校验实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:52:42
EMG手势识别实战:从EMG1数据集到稳定分类的完整链路 简介:本资源是一套基于真实表面肌电(sEMG)信号的手势识别完整实现方案,面向生物医学工程、人机交互及模式识别方向的本科生、研究生与算法工程师,解决肌肉电信号采集、特征建模与实时手势分类等核心问题。压缩包共156个… · 2026/9/25 4:52:42
深入理解Linux USB协议栈:核心框架、URB与驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:52:36
用OpenCvSharp给USB摄像头做H264录像:FFmpeg管道绕开编码器坑 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 4:52:36
GitPuk 接入 soular:用 OIDC 实现统一登录的完整指南 最近有个同学在群里问:团队内部部署了一套 GitPuk 做代码托管,又上了一套 soular 做身份认证,两边账号各管各的,新同事入职得在两个系统里分别建号,离职又要分别注销,有没有办法把登录统一起来?… · 2026/9/25 4:52:30
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37