3

我正在开发一个 C++ 类的集合,并且正在努力解决如何以一种维护组织的方式共享代码,同时又不影响集合用户的编译易用性。

我见过的选项包括:

  • 分发编译的库文件
  • 将源代码放在头文件中(在这个答案中讨论过隐式内联)
  • 使用符号链接允许编译器查找文件。

我目前正在使用第三个选项,对于我想要包含的每个类,我符号链接每个类头和源文件(例如ln -s <path_to_class folder>/myclass.cpp)这很好用,除了我无法移动项目文件夹位置(它破坏了所有符号链接) 而且我必须让所有这些符号链接的文件挂在身边。

我喜欢第二个选项(它具有 Java 的外观),但是如果所有内容都被声明为内联,我担心代码大小会膨胀。

该集合的用户将在某处创建一个项目文件夹,并以某种方式将该集合包含到他们的编译过程中。

我希望有几件事是可能的:

  1. 轻松编译(类似于gcc *.cpp项目文件夹中的内容)
  2. 以未编译的形式轻松分发库。
  3. 图书馆按模块组织。
  4. 编译后的代码大小并不臃肿。

我不担心文档(Doxygen 负责)或编译时间:整个模块都很小,即使是最慢机器上的最大项目也不会花费超过几秒钟的时间来编译。

我正在使用 GCC 编译器,如果它有什么不同的话。

4

3 回答 3

0

图书馆是您提出的三个中的最佳选择(在我看来)。然后在包含路径中提供头文件,在链接器路径中提供库。

由于您还希望以源代码形式分发库,因此我倾向于在中央存储库中提供压缩存档(gzip、7-zip、tarball 或其他首选格式)。

于 2013-07-30T19:55:36.447 回答
0

如果我理解正确,您不希望用户必须在其构建中包含 .cpp 文件,而只是希望他们使用:(i)直接标头,(ii)使用 lib 的编译形式。

您的要求有点不寻常,但可以实现。在我看来,您可以按以下方式组织代码。首先,有一个全局定义来指示您是否正在编译库:

// global.h
// ...
#define LIB_SOURCE
// ...

然后在每个头文件中,检查是否设置了该定义:如果库作为静态/共享库分发,则不包含定义,否则,“.cpp”文件包含在头文件中。

// A.h
#ifndef _A_H
#include "global.h"
    #ifdef LIB_SOURCE
    #include "A.cpp"
#endif
// ...
#endif

其中 'A.cpp' 将包含实际的实现。

同样,这是一种非常奇怪的做事方式,我实际上建议不要这样做。一种更好的方法(但需要更多工作)是始终分发共享库。但是为了使事情独立于编译器,请围绕它编写一个 C 层。这样,您就有了一个可移植、可维护的库。

至于其他一些要求:

  • 通过提供 Makefile 保持构建过程简单
  • 如果您担心编译库的代码大小,请查看 gcc 的优化选项 (-Os)。如果您担心在标头中以源代码形式分发时库的代码大小,这将更加棘手。由于(内联)代码实际上将位于标头中,因此代码显然会随着用户在 .cpp 文件中的每个包含而增长。
于 2013-07-30T20:13:36.257 回答
0

我最终为所有代码使用了内联标题。你可以在这里看到图书馆:

https://github.com/libpropeller/libpropeller/tree/master/libpropeller

该库的结构如下:

  • 库文件夹
    • A级
      • 类A.h
      • 类A.test.h
    • B类
      • B类.h
      • 类B.test.h
    • C类
    • ...

使用这种结构,我可以将库作为源分发,用户所要做的就是包含-I/path/to/library在他们的 makefile 和#include "library/classA/classA.h"他们的源文件中。

而且,事实证明,具有内联标头实际上会减少代码大小。我对此进行了全面分析,结果表明,头文件中的内联代码允许编译器使最终的二进制文件小约 5%。

于 2013-12-02T16:10:16.360 回答