使用在不同时间/团队编译的同一版本Visual Studio中的C++ DLL - 是否具有ABI兼容性?

10

重申一下:我正在寻找同一版本的Visual C++库之间ABI兼容性!

我们想要混合和匹配来自不同团队的一些内部C++ DLL - 这些DLL是在不同时间使用不同的项目文件构建的。由于编译时间很长,我们确切地希望避免大型单块构建,其中每个团队重新编译另一个团队库的源代码。

当使用具有C++接口的C++ DLL时,相当 清楚 是只有当所有DLL都使用相同的编译器/Visual Studio版本编译时才能这样做。

对我而言不太明显的是,要获得ABI兼容性,需要什么完全相同。

  • 显然,调试(_DEBUG)和发布(NDEBUG)不能混用——但这也可以从它们链接到不同版本的共享运行时的事实中得出。
  • 您是否需要完全相同的编译器版本,或者只需生成的DLL链接到相同的共享C++运行时,基本上链接到相同的redistributable即可?(我认为在传递完整的C++对象时,静态方式不可行)
  • 有没有已记录的编译器(和链接器)选项列表,需要对于两个相同vc++版本的C++ DLL兼容?
    • 例如,是否需要相同的/O开关 - 优化级别是否影响ABI兼容性?(我非常确定不会)
    • 或者两个版本是否都必须使用相同的/EH开关
    • 或者/volatile:ms|iso ... ?
基本上,我希望为一个Visual-C++ DLL创建一组(元)数据,用于描述它的ABI兼容性。如果存在差异,则我目前只关注VS2015。

一般来说,您应该尽量确保所有二进制文件使用相同版本的CRT。否则可能会工作,但不能保证。我无法回答关于C++编译器设置的问题,但最好的做法是标准化团队中所有编译器/链接器设置。 - Chris O
_ITERATOR_DEBUG_LEVEL也是必须相等的一个东西,因为它会影响std-lib对象的布局。 - Martin Ba
https://github.com/microsoft/vcpkg/blob/master/docs/users/triplets.md - Martin Ba
1个回答

3

最近几天一直在思考这个问题,我试图看看是否存在一些使用案例,使得开发人员已经需要对他们的C++构建进行分类以确保二进制文件兼容性。

其中一个地方是NuGet的本机包。因此,我查看了一个包,特别是cpprestsdk

可下载软件包中的二进制文件如下所示:

native\v120\windesktop\msvcstl\dyn\rt-dyn\x64\Release\
        ^      ^         ^      ^    ^     
  VS version   |       not sure |    uses cpp-runtime dynamically
               |               lib itself dynamic (as opposed to static)
    or WinXP or WinApp(WinRT?)
                 

我从这个示例中提取出来,因为我找不到其他文档。我还知道boost二进制文件的生成目录也以类似的方式分开。

因此,为了获得一个元数据列表以识别ABI兼容性,我可以初步列出以下内容:

  • VC版本(即使用的C和CPP运行时库的版本)
    • 这里的一个要点是,例如vc140现在应该已经足够了-鉴于CRT是如何链接的,所有可能的针对版本化CRT组件的错误修复必须是ABI兼容的,因此无论使用哪个版本构建给定的预编译库都不会有影响。
  • 纯本机|托管(/CLI)|WinRT
  • CRT的使用方式(静态/动态)
  • 位数/平台(Win32、x64、ARM等)
  • Release或Debug版本(即我们链接到哪个版本的CRT)
  • 附加项:_ITERATOR_DEBUG_LEVEL …如果每个人都使用默认值,那么很好,如果某个项目没有使用默认值,则必须声明

另外,以下是我最好的猜测:

  • /O不能影响结果——我们经常混合使用具有不同优化设置的二进制文件,特别是在同一二进制文件内的目标文件中也是如此。
  • /volatile -由于这是一个代码生成问题,我很难想象这会如何破坏ABI。
  • /EH -除了禁用所有异常的选项外,在这种情况下,您显然无法调用任何抛出异常的函数,我非常有信心从ABI的角度来看这是安全的: 这里可能存在一些潜在的陷阱,但我认为它们不能真正归类为ABI兼容。(也许某些复杂的回调链可以说是ABI不兼容,不确定)

其他:

  • 默认调用约定(/G..): 我认为这会在链接时出现问题,当混合导出符号和头声明不匹配时。
  • /Zc:wchar_t -将在链接时出现问题(实际上是ABI兼容的,但符号不匹配。)
  • 启用RTTI (/GR) -对于这个问题我不太确定-我从未禁用过它。

非常有帮助的答案。我想知道“字符集”是否也是一个问题;Unicode vs MBCS vs ASCII? - dicksters
@dicksters - 我相信UNICODE和MBCS并不重要,因为所有这些设置宏所做的就是编译不同的API,例如FoobarA() vs FoobarW()等。 - Martin Ba

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接