我正在寻找可以帮助将嵌入式C项目组织为“模块”和“组件”的高级构建系统/工具。请注意,这两个术语具有很高的主观性,因此以下给出了我的定义。
构建系统/工具应-
我可以编写自己的构建工具,并在其中花费大量时间。但是,这不是我的专业领域,如果有人已经创建了这样的工具,我就不想重新发明轮子。
最佳答案
实现该目标的常规方法是将每个模块的源代码放在单独的目录中。每个目录可以包含该模块的所有源文件和头文件。
每个模块的公共(public)头可以放置在单独的头通用目录中。对于每个 header ,我可能会使用从公共(public)目录到相关模块目录的符号链接(symbolic link)。
编译规则只是声明,除了公共(public)目录中的头文件外,没有模块可以包含其他模块的头文件。这样可以达到以下结果:除了公共(public) header (因此强制执行私有(private)屏障)之外,没有模块可以包含其他模块的 header 。
自动防止循环依赖性并非易事。问题是您只能通过一次查看多个源文件来确定是否存在循环依赖性,而编译器一次只能查看一个。
考虑一对模块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也不能提示。
让我们假设使用ModuleB的设施对ModuleA是合法的。因此,在编译ModuleA1.c或ModuleA2.c时,同时包含ModuleA.h和ModuleB.h不会有问题。
但是,为了防止循环依赖性,您必须能够禁止ModuleB1.c和ModuleB2.c中的代码使用ModuleA.h。
据我所知,唯一的方法是某种技术,该技术要求ModuleB的私有(private) header 说“已经包含了ModuleA”,即使没有,并且在包含ModuleA.h之前就已经包含了此 header 。
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...
这远非自动的。
您可以对包含的文件进行分析,并要求对依赖项进行无循环的拓扑排序。在UNIX系统上,曾经有一个程序
tsort
(和一个辅助程序lorder
)一起提供了所需的服务,因此可以创建一个静态(.a
)库,该库以不需要重新扫描目录的顺序包含目标文件。文件。 ranlib
程序,最后是ar
和ld
承担着管理单个库的重新扫描的职责,从而使lorder
特别冗余。但是tsort
具有更广泛的用途;它在某些系统上可用(例如MacOS X; RHEL 5 Linux也是如此)。因此,使用GCC和
tsort
的依赖项跟踪,您应该能够检查模块之间是否存在循环。但这必须谨慎处理。可能会有一些IDE或其他工具集可以自动处理这些问题。但是通常程序员可以受到足够的训练,避免出现问题-只要仔细记录了需求和模块间的依赖关系即可。
关于c++ - 嵌入式C/C++项目的构建系统,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7606604/