如何使用完全不同的构建系统处理第三方库?

Bil*_*eal 23 c c++ dependencies build-dependencies

C++(和C,虽然它更重要)标准状态,程序中的所有翻译单元需要具有相同的定义; 这包括编译器开关之类的东西.例如,在MSVC++中,必须链接到C运行时库的正确版本(/MT/MD/MTd/MDd所有翻译单元).

但是,我们想要使用几个第三方依赖项,并且有几件事情:

  • 他们都使用不同的构建系统(有一个autoconf,有一个cmake,并且有一个似乎有它自己的手工卷制的东西..)
  • 构建系统并非都在其配置中公开这些类型的交换机,并且硬编码的交换机在不同的系统中设置不同.(例如,一个库的力量/MD/MDd,而另一种力量/MT/MTd)

我们不确定处理这类事情的最佳方法是什么.我们讨论了以下选项:

  • 围绕任何第三方依赖关系构建我们自己的构建系统.
    • PRO:我们知道事情会匹配
    • PRO:我们知道我们可以以正确的方式进行跨平台支持
    • CON:我们并不确切知道每个第三方构建系统是如何工作的
    • CON:很多很多工作
    • CON:如果第三方依赖关系发生更改,则会中断
  • 尝试使用第三方构建系统,并尝试修改它们以执行我们需要的操作.
    • PRO:似乎工作量减少了
    • CON:我们可能打破第三方系统
    • CON:如果第三方依赖关系发生更改,则会中断
    • CON:强迫我们自己的构建变得非常复杂

我们不知道该怎么办; 我们无法相信我们一个人就有这些问题.我们应该选择上述选项之一,还是我没想过的第三种选择?

jal*_*alf 6

您并不严格地说需要所有库链接到同一个运行时.假设它们是DLL,如果它们通过DLL边界传递CRT数据结构,那只是一个问题.FILE*使用一个运行时在DLL中创建,并从与另一个运行时链接的DLL中使用它是一种灾难.调用mallocnew从DLL使用一个运行时,和free/ delete从另一个会引起很多有趣的问题.

但只要所有与CRT相关的内容都保存在DLL内部,您就可以安全地链接到使用另一个CRT的DLL.这也意味着您的调试版本可以使用与发布CRT链接的库.同样,只要您不尝试跨库混合CRT数据结构.

另请注意,大多数编译器标志不会影响ABI,因此它们可以安全地在库(或文件)之间保持不同.改变ABI的那些通常很明显,就像强行打包或堆叠对齐一样.

所以我们做的基本上是这样的:

  • 只要有可能,我们自己建立图书馆.在大多数情况下,这意味着我们可以通过相当简单的方法控制它应链接的运行时.这可能需要对构建系统进行非常少量的调整,但通常,只需指定是否构建调试版本或发布版本,大多数构建系统都可以选择.(如果库使用Visual Studio作为其构建系统,我们会尽可能将其升级到2010)
  • 我们使用库自己的构建系统.其他任何东西只是苦难的一个秘诀.您希望能够相信构建系统实际上与库源代码保持同步,并且确保使用源代码附带的构建系统的最简单方法.
  • 如果构建库是不切实际的,我们只是按原样使用它,然后我们只需要分发链接的任何运行时.我们试图避免这种情况,但是当没有其他选择可用时,它足够安全.
  • 当我们构建一个库时,我们会准确记录它在内部wiki上的完成情况.如果我们必须升级到更新版本的库或重建它,这将是一个巨大的帮助.

我们目前依赖于三种不同的VS运行时(2005年,2008年和2010年),这是一个很难处理,但它的工作原理.对于其中的一个或两个,我们总是使用发布版本,即使在我们自己的代码的调试版本中也是如此.

维护起来有点混乱,但它确实有效.我无法真正看到更好的方法.

当然,您应该最小化您拥有的第三方依赖项,并且当您选择第三方库时,其构建系统绝对应该是一个需要考虑的因素.有些是很多更痛苦比别人工作.

但最终,您可能最终不得不使用一些只是没有运行良好的构建系统的库,或者构建它们会非常痛苦,只是不值得努力,或者你可以在哪里' t创建库的调试版本.然后只需拿走你能得到的东西.让它使用它喜欢使用的任何运行时.


Mar*_* Ba 2

我认为您是故意不提及任何特定的库?

不管怎样,你应该问自己,你的构建系统中是否真的需要这个第三方代码。

我们使用的第 3 方库会编译一次(使用各自的构建脚本)并检查正确的 VC 开关,然后将 DLL 或 LIB 文件签入使用该库的应用程序的源代码管理中。

因此,对于每个第 3 方版本,我们只需要编译第 3 方库一次,并且我们不会因为构建第 3 方库的复杂性而给我们的构建系统带来负担。

我想这两种方法都有有效的论据,也许您可​​以在问题中提供一些详细信息,为什么您需要/想要在构建系统中使用第 3 方库。