构建嵌入式C / C ++项目的系统 [英] Build system for an embedded C/C++ project

查看:231
本文介绍了构建嵌入式C / C ++项目的系统的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am looking for a high-level build system/tool that can help organise my embedded C project into "modules" and "components". Note that these two terms are highly subjective so my definitions are given below.


  • 模块是c和h文件的一个连贯的集合,

  • 另一方面,组件(或层)是模块的集合(例如应用层,库层,驱动程序层, RTOS层等)。

构建系统/工具应该 -

The build system/tool should -


  • 阻止组件和模块之间的循环依赖性(模块内的循环依赖性可以)

  • 阻止访问模块的私有屏障。如果其他模块尝试包含模块专用的头文件,则构建系统必须抛出错误。

  • 支持在主机上自动构建和执行单元测试(针对TDD的快速反馈循环)

  • 支持单元测试在目标模拟器上运行

  • 支持代码静态分析

  • 支持代码生成

  • 支持代码重复检测(强制执行DRY原则)

  • 支持代码美化

  • 支持生成单元测试代码覆盖率指标

  • 支持生成代码质量指标

  • 与平台无关。

  • Prevent cyclic dependencies between components and modules (cyclic dependencies inside modules is okay)
  • prevent access to private barriers of a module. If other modules try to include a header file that is private to a module, the build system must throw an error. However, files within a private barrier must be able to include other files inside that barrier.
  • support building and executing of unit tests automatically (fast feedback loop for TDD) on host
  • support unit tests to be run on target simulator
  • support code static analysis
  • support code generation
  • support code duplication detection (enforce DRY principle)
  • support code beautification
  • support generation of unit test code coverage metrics
  • support generation of code quality metrics
  • be platform-independent

我可以编写自己的构建工具,并花费大量的时间。但是,这不是我的专业领域,如果有人已经创建了这样的工具,我不想重新发明轮子。

I could write my own build tool and spend a lot of time on it. However, that is not my area of expertise and I'd rather not re-invent the wheel if someone has already created such a tool.

推荐答案

实现的常规方法是将每个模块的源代码放在单独的目录中。每个目录可以包含模块的所有源文件和头文件。

The conventional way of achieving that would be to place the source code for each module into a separate directory. Each directory can contain all the source and header files for the module.

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

The public header for each module can be placed into a separate, common directory of headers. I'd probably use a symlink from the common directory to the relevant module directory for each header.

编译规则简单地说明没有模块可能包括其他模块的头文件用于公用目录中的头。这实现的结果是没有模块可以包括来自另一个模块的头文件 - 除了公共头(因此强制实施私有屏障)。

The compilation rules simply state that no module may include headers from other modules except for the headers in the common directory. This achieves the result that no module can include headers from another module - except for the public header (thus enforcing the private barriers).

自动防止循环依赖不是微不足道的。问题是你只能通过一次查看几个源文件来确定是否存在循环依赖,编译器一次只查看一个。

Preventing cyclic dependencies automatically is not trivial. The problem is that you can only establish that there is a cyclic dependency by looking at several source files at a time, and the compiler only looks at one at a time.

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

Consider a pair of modules, ModuleA and ModuleB, and a program, Program1, that uses both modules.

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是完全合法的。因此,ModuleA.h不能抱怨ModuleB.h是否包含在同一翻译单元(TU)中,如果ModuleA.h包含在同一个TU中,ModuleB.h也不能抱怨。

When compiling Program1.c, it is perfectly legitimate for it to include both ModuleA.h and ModuleB.h if it makes use of the services of both modules. So, ModuleA.h cannot complain if ModuleB.h is included in the same translation unit (TU), and neither can ModuleB.h complain if ModuleA.h is included in the same TU.

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

Let us suppose it is legitimate for ModuleA to use the facilities of ModuleB. Therefore, when compiling ModuleA1.c or ModuleA2.c, there can be no issue with having both ModuleA.h and ModuleB.h included.

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

However, to prevent cyclic dependencies, you must be able to prohibit the code in ModuleB1.c and ModuleB2.c from using ModuleA.h.

据我所知,唯一的方法是这是一些技术,需要ModuleB的一个专用头,说ModuleA已经包括,即使它不是,这是包括在ModuleA.h之前包括。

As far as I can see, the only way to do this is some technique that requires a private header for ModuleB that says "ModuleA is already included" even though it isn't, and this is included before ModuleA.h is ever included.

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

The skeleton of ModuleA.h will be the standard format (and ModuleB.h will be similar):

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

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

Now, if the code in ModuleB1.c contains:

#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...

这远远不是自动的。

您可以对包含的文件进行分析,并要求有一个无环拓扑排序的依赖关系。以前在UNIX系统上有一个程序 tsort (以及一个伴随程序 lorder ),它们共同提供所需的服务从而可以创建包含对象文件的静态( .a )库,其顺序不需要重新扫描存档。 ranlib 程序,最终 ar ld 管理单个图书馆的重新扫描的职责,从而使 lorder 特别多余。但 tsort 有更多的一般用途;它在一些系统(MacOS X,例如,RHEL 5 Linux)上可用。

You could do an analysis of the included files, and require that there is a loop-less topological sort of the dependencies. There used to be a program tsort on UNIX systems (and a companion program, lorder) which together provided the services needed so that a static (.a) library could be created that contained the object files in an order that did not require rescanning of the archive. The ranlib program, and eventually ar and ld took on the duties of managing the rescanning of a single library, thus making lorder in particular redundant. But tsort has more general uses; it is available on some systems (MacOS X, for instance; RHEL 5 Linux too).

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

So, using the dependency tracking from GCC plus tsort, you should be able to check whether there are cycles between modules. But that would have to be handled with some care.

可能有一些IDE或其他工具集自动处理这个东西。但是通常程序员可以足够规范以避免问题 - 只要对需求和模块间依赖关系进行仔细记录即可。

There may be some IDE or other toolset that handles this stuff automatically. But normally programmers can be disciplined enough to avoid problems - as long as the requirements and inter-module dependencies are carefully documented.

这篇关于构建嵌入式C / C ++项目的系统的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆