嵌入式 C/C++ 项目的构建系统

2024-04-11

我正在寻找一个高级构建系统/工具,可以帮助将我的嵌入式 C 项目组织成“模块”和“组件”。请注意,这两个术语非常主观,因此我的定义如下。

  • 模块是 c 和 h 文件的内聚集合,但只有一个对其他模块可见的公共 h 文件。
  • 另一方面,组件(或层)是模块的集合(例如应用程序层、库层、驱动程序层、RTOS 层等)。

构建系统/工具应该 -

  • 防止组件和模块之间的循环依赖(模块内的循环依赖是可以的)
  • 防止访问模块的私有屏障。如果其他模块尝试包含模块私有的头文件,则构建系统必须抛出错误。但是,私有屏障内的文件必须能够包含该屏障内的其他文件。
  • 支持在主机上自动构建和执行单元测试(TDD 的快速反馈循环)
  • 支持在目标模拟器上运行的单元测试
  • 支持代码静态分析
  • 支持代码生成
  • 支持代码重复检测(强制DRY原则)
  • 支持代码美化
  • 支持生成单元测试代码覆盖率指标
  • 支持生成代码质量指标
  • 独立于平台

我可以编写自己的构建工具并花很多时间在上面。然而,这不是我的专业领域,如果有人已经创建了这样的工具,我宁愿不重新发明轮子。


实现这一目标的传统方法是将每个模块的源代码放入单独的目录中。每个目录可以包含模块的所有源文件和头文件。

每个模块的公共标头可以放置在单独的公共标头目录中。我可能会为每个标头使用从公共目录到相关模块目录的符号链接。

编译规则只是规定,除了公共目录中的标头之外,任何模块都不能包含来自其他模块的标头。这实现了任何模块都不能包含来自另一个模块的标头 - 除了公共标头(从而强制执行私有屏障)。

自动防止循环依赖并非易事。问题在于,您只能通过一次查看多个源文件来确定是否存在循环依赖关系,而编译器一次只查看一个。

考虑一对模块(ModuleA 和 ModuleB)以及一个使用这两个模块的程序(Program1)。

base/include
        ModuleA.h
        ModuleB.h
base/ModuleA
        ModuleA.h
        ModuleA1.c
        ModuleA2.c
base/ModuleB
        ModuleB.h
        ModuleB1.c
        ModuleB2.c
base/Program1
        Program1.c

编译 Program1.c 时,如果它使用 ModuleA.h 和 ModuleB.h 的服务,则完全合法地包含这两个模块的服务。因此,如果 ModuleB.h 包含在同一翻译单元 (TU) 中,则 ModuleA.h 不能抱怨,如果 ModuleA.h 包含在同一 TU 中,ModuleB.h 也不能抱怨。

让我们假设 ModuleA 使用 ModuleB 的设施是合法的。因此,在编译 ModuleA1.c 或 ModuleA2.c 时,同时包含 ModuleA.h 和 ModuleB.h 不会有问题。

但是,为了防止循环依赖,您必须能够禁止 ModuleB1.c 和 ModuleB2.c 中的代码使用 ModuleA.h。

据我所知,执行此操作的唯一方法是某种技术,该技术需要 ModuleB 的私有标头,该标头显示“ModuleA 已包含”,即使它没有包含在内,并且这是在包含 ModuleA.h 之前包含的。

ModuleA.h 的骨架将是标准格式(ModuleB.h 也将类似):

#ifndef MODULEA_H_INCLUDED
#define MODULEA_H_INCLUDED
...contents of ModuleA.h...
#endif

现在,如果 ModuleB1.c 中的代码包含:

#define MODULEA_H_INCLUDED
#include "ModuleB.h"
...if ModuleA.h is also included, it will declare nothing...
...so anything that depends on its contents will fail to compile...

这远非自动的。

您可以对包含的文件进行分析,并要求存在依赖关系的无循环拓扑排序。曾经有一个节目tsort在 UNIX 系统上(以及一个配套程序,lorder)共同提供所需的服务,以便静态(.a)可以按顺序创建包含目标文件的库,不需要重新扫描存档。这ranlib程序,最终ar and ld承担了管理单个图书馆重新扫描的职责,从而使lorder特别多余。但tsort具有更通用的用途;它在某些系统上可用(例如 MacOS X;RHEL 5 Linux)。

因此,使用 GCC plus 的依赖跟踪tsort,您应该能够检查模块之间是否存在循环。但这必须小心处理。

可能有一些 IDE 或其他工具集可以自动处理这些事情。但通常情况下,只要仔细记录需求和模块间依赖关系,程序员就可以遵守足够的纪律来避免出现问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

嵌入式 C/C++ 项目的构建系统 的相关文章

  • 在 VS2017 下使用 Conan 和 CMake 项目进行依赖管理

    我正在尝试使用 CMake 与 VS2017 集成为 C 设置一个开发环境 以便在 Linux x64 下进行编译 为了更好地管理依赖关系 我选择使用 Conan 但我对这个软件还很陌生 我想知道让 VS2017 识别项目依赖关系的最佳方法
  • 内联函数/方法

    声明 内联函数必须在调用之前定义 这个说法正确吗 EDIT 该问题最初是德语 内联功能穆森 弗 伊赫雷姆 奥夫鲁夫定义 sein 也许它对任何人都有帮助 是的 它是正确的 但只是部分正确 它可能正确地重新构建如下 内联函数必须在每个翻译单位
  • 将字节数组转换为托管结构

    更新 这个问题的答案帮助我编写了开源项目GitHub 上的 AlicanC 现代战争 2 工具 https github com AlicanC AlicanC s Modern Warfare 2 Tool 你可以看到我是如何阅读这些数据
  • 为什么Apache MPM prefork.c 使用互斥体来保护accept()?

    我坐下来读书Apache 的 MPM prefork c http code metager de source xref apache httpd server mpm prefork prefork c这段代码使用了一个名为accept
  • 如何尝试/捕获所有异常

    我正在完成由其他人启动的 UWP 应用程序 该应用程序经常崩溃 我总是陷入困境应用程序 at if global System Diagnostics Debugger IsAttached global System Diagnostic
  • 为什么大多数平台上没有“aligned_realloc”?

    MSVC有自己的非标准函数 aligned malloc aligned realloc and aligned free C 17和C11引入了 std aligned alloc 其结果可以是de分配有free or realloc B
  • SFINAE 如何使用省略号?

    过去 当使用 SFINAE 选择构造函数重载时 我通常使用以下内容 template
  • 获取尚未实例化的类的函数句柄

    我对 C 相当陌生 我想做的事情可能看起来很复杂 首先 我想获取一些函数的句柄以便稍后执行它们 我知道我可以通过以下方式实现这一目标 List
  • 从 Code::Blocks 运行程序时出现空白控制台窗口 [重复]

    这个问题在这里已经有答案了 当我尝试在 Code Blocks 中构建并运行新程序时 控制台窗口弹出空白 我必须单击退出按钮才能停止它 它对我尝试过的任何新项目 包括 Hello world 都执行此操作 奇怪的是 它对于我拥有的任何旧项目
  • 预处理后解析 C++ 源文件

    我正在尝试分析c 使用我定制的解析器的文件 写在c 在开始解析之前 我想摆脱所有 define 我希望源文件在预处理后可以编译 所以最好的方法是运行C Preprocessor在文件上 cpp myfile cpp temp cpp or
  • 分配器感知容器和propagate_on_container_swap

    The std allocator traits模板定义了一些常量 例如propagate on container copy move assign让其他容器知道它们是否应该在复制或移动操作期间复制第二个容器的分配器 我们还有propag
  • C# 中的常量和只读? [复制]

    这个问题在这里已经有答案了 可能的重复 const 和 readonly 之间有什么区别 https stackoverflow com questions 55984 what is the difference between cons
  • 使用 mingw32 在 Windows 上构建 glew 时“DllMainCRTStartup@12”的多个定义

    我关注了这个主题 使用 mingw 使建筑物在 Windows 上闪闪发光 https stackoverflow com questions 6005076 building glew on windows with mingw 6005
  • DataTable:通过 LINQ 或 LAMBDA 进行动态 Group By 表达式

    我有一个数据表 我想在其中对未指定数量的字段进行分组 发生这种情况的原因是用户可以选择他想要分组的字段 所以 实际上 我将选择推入列表中 在这个选择上 我必须对我的数据表进行分组 想象一下这段代码 VB 或 C 都一样 public voi
  • 使用 iTextSharp 5.3.3 和 USB 令牌签署 PDF

    我是 iTextSharp 和 StackOverFlow 的新手 我正在尝试使用外部 USB 令牌在 C 中签署 PDF 我尝试使用从互联网上挖掘的以下代码 Org BouncyCastle X509 X509CertificatePar
  • C 中带有指针的结构的内存开销[重复]

    这个问题在这里已经有答案了 我意识到当我的结构包含指针时 它们会产生内存开销 这里有一个例子 typedef struct int num1 int num2 myStruct1 typedef struct int p int num2
  • 受限 AppDomain 中的代码访问安全异常

    Goal 我需要在权限非常有限的 AppDomain 中运行一些代码 它不应该访问任何花哨或不安全的内容 except对于我在其他地方定义的一些辅助方法 我做了什么 我正在创建一个具有所需基本权限的沙箱 AppDomain 并创建一个运行代
  • 为什么文件更新时“如果较新则复制”不复制文件?

    我在 Visual Studio Express 中有一个解决方案 如下所示 The LogicSchemaC 中的类 将在运行时解析指定的 XML 文件 以下是在main的方法Program cs LogicSchema ls new L
  • 以 UTF8 而不是 UTF16 输出 DataTable XML

    我有一个 DataTable 我正在使用 WriteXML 创建一个 XML 文件 尽管我在以 UTF 16 编码导出它时遇到问题 并且似乎没有明显的方法来更改它 我了解 NET 在字符串内部使用 UTF 16 这是正确的吗 然后 我通过
  • 如何使用 C# 以低分辨率形式提供高分辨率图像

    尝试使用 300dpi tif 图像在网络上显示 目前 当用户上传图像时 我正在动态创建缩略图 如果创建的页面引用宽度为 500x500px 的高分辨率图像 我可以使用相同的功能即时转换为 gif jpg 吗 将创建的 jpg 的即将分辨率

随机推荐

  • 市政数据集? [关闭]

    Closed 这个问题是无关 help closed questions 目前不接受答案 我正在寻找一些数据来创建查找表 具体来说 美国每个州的所有县以及每个县的所有城市 我在哪里可以找到这样的市政数据集 编辑 我正在查看 census g
  • 为什么 subprocess.Popen 不起作用

    我尝试了很多事情 但由于某种原因我无法让事情发挥作用 我正在尝试使用 Python 脚本运行 MS VS 的 dumpbin 实用程序 这是我尝试过的 以及对我不起作用的 1 tempFile open C Windows temp tem
  • difflib.SequenceMatcher isjunk 参数未考虑?

    在 python difflib 库中 SequenceMatcher 类的行为是否异常 或者我是否误读了假定的行为 为什么 isjunk 论点在这种情况下似乎没有任何区别 difflib SequenceMatcher None AA A
  • 错误“无法推断 (a ~ b)”是什么意思?

    我正在修改以下代码作为作业的一部分 rand Random a gt State StdGen a rand do gen lt get let x gen random gen put gen return x 我被要求写一个函数rand
  • onReceive 方法没有被调用

    public class BroadcastTest extends Activity BroadcastReceiver receiver Called when the activity is first created Overrid
  • React Router 3,与查询参数完全匹配

    在 React Router 3 中 如何精确匹配包含查询参数的路由 像这样的事情
  • 无法推送到 Codeplex 上的 Hg 项目

    我正在尝试对使用 Mercurial 的 Codeplex 项目进行更改 我收到以下错误 中止 HTTP 错误 500 找到放弃的事务 运行 hg recovery 我在我的家用电脑上尝试过 但遇到了同样的错误 我运行 hg recover
  • Django站点地图索引分页URL格式

    我创建了一个站点地图索引 https docs djangoproject com en dev ref contrib sitemaps creating a sitemap index对于我的 Django 站点 因为我有超过 50k
  • 病毒或机器故障导致“无法创建Java虚拟机”?

    我用的是双核XP机安装了 4GB 内存 但仅2 5GB由于 32 位事实 由操作系统报告 我正在积极修改旧的 JAVA 应用程序至少一个月 使用最新的Eclipse 编辑 构建和运行 和Ant 另一种构建和运行的方式 在里面Eclipse运
  • 当用户切换选项卡时暂停 html5 视频

    我的网页上嵌入了一个 HTML5 视频
  • VBA在指定范围内查找指定单元格值并选择它

    我在创建一个宏时遇到问题 该宏将在 信息 工作表的范围内找到活动工作表中的指定值 如果在范围内找不到单元格值 那么它会给我一个消息框 指出 未找到值 我有以下内容 但它不起作用 Sub testrot Dim i As String Dim
  • 匹配元组作为映射的输入

    尝试对映射中的元组进行模式匹配 fn main let z vec 1 2 3 4 let sums z iter map a b a b println sums 产生错误 error E0308 mismatched types gt
  • 如何在 R 中处理 BigINT [重复]

    这个问题在这里已经有答案了 我有一个 BigInt 数字 如果我尝试将其存储在 R 中 R gt a lt 9223372036854775807 R gt a 1 9 223372e 18 正如您所注意到的 它丢失了最后几位数字的信息 我
  • 带有忽略大小写的 JDBC URL 不适用于 H2 数据库连接

    我试图在 SQL 模式下使用 h2 数据库 我能够创建一个全部大写的模式 并在其下创建一些表 但是 除非我匹配所有大写的架构名称 否则我在休眠上运行的应用程序似乎无法工作 我认为 h2 可以在 JDBC 连接字符串中使用 IGNROECAS
  • 如何在 WordPress 多站点设置中显示来自其他站点的帖子?

    我使用 WordPress 3 0 的多站点功能设置了一个小型站点网络 我想创建另一个网站 从其他各个网站中提取某些帖子进行显示 这个新的 中心 站点对于用户来说似乎是它自己的独立站点 具有域映射 但其内容来自其他站点的帖子 如何在 Wor
  • 在 ionic v1 中滚动到 div 时使其固定

    我试图在滚动到 div 时修复它 但问题是我尝试定位的 div 位于 ion content 中 并且它不允许我使用简单的 jQuery 或 CSS 解决方案来实现此功能 根据我读过的答案 离子内容的滚动部分正在扰乱它的工作 我很好奇与这个
  • 检查一个时间间隔内的任何日期是否在另一个时间间隔内的任何日期内

    我有 2 个日期间隔 我想看看是否有任何日期interval A在之内interval B 我理想地寻找 dplyr 解决方案 The data library lubridate interval A lt new Interval Da
  • 如何使用 JAX-RS NewCookie 删除服务器上的 cookie?

    我想删除服务器上的cookie 通过设置Expires到过去 我怎样才能做到这一点javax ws rs core NewCookie 我正在尝试这个 但它不起作用 return Response ok entity hello world
  • 如何使用 .Net(在 Windows Phone 上)阅读公共 Twitter 源

    我正在尝试读取用户的公共 Twitter 状态 以便可以在我的 Windows Phone 应用程序中显示它 我用 Scott Gu 的例子 http weblogs asp net scottgu archive 2010 03 18 b
  • 嵌入式 C/C++ 项目的构建系统

    我正在寻找一个高级构建系统 工具 可以帮助将我的嵌入式 C 项目组织成 模块 和 组件 请注意 这两个术语非常主观 因此我的定义如下 模块是 c 和 h 文件的内聚集合 但只有一个对其他模块可见的公共 h 文件 另一方面 组件 或层 是模块