10

重复一遍:我正在寻找相同Visual-C++ 版本的库之间的 ABI 兼容性!

我们希望混合和匹配来自不同团队的一些内部 C++ DLL——在不同时间使用不同的项目文件构建。由于构建时间长,我们确实希望避免大型单体构建,每个团队都重新编译另一个团队库的源代码。

当使用具有 C++ 接口的 C++ DLL 时,很 明显只有 所有 DLL 都使用相同的编译器/Visual Studio 版本编译时才能执行此操作。

对我来说不太明显的是要获得 ABI 兼容性,必须完全相同。

  • 显然debug ( _DEBUG) 和 release ( NDEBUG) 不能混合使用——但从它们链接到不同版本的共享运行时这一事实也很明显。
  • 您是否需要完全相同的编译器版本,或者生成的 DLL 链接到相同的共享C++ 运行时是否足够——也就是说,基本上是相同的可发行文件?(我认为传递完整的 C++ 对象时静态不会飞)
  • 对于相同 vc++ 版本的两个 C++ DLL 是否需要相同 的编译器(和链接器)选项的文档化列表才能兼容?
    • 例如,是否/O需要相同的开关——优化级别会影响 ABI 兼容性吗?(我很确定不是。)
    • 还是两个版本都必须使用相同的/EH开关
    • 还是/volatile:ms|iso……?

本质上,我想提出一组(元)数据与描述其 ABI 兼容性的 Visual-C++ DLL 相关联。

如果存在差异,我目前只关注 VS2015。

4

1 回答 1

3

过去几天一直在考虑这个问题,我所做的是尝试看看是否存在一些用例,开发人员已经需要对其 C++ 构建进行分类以确保二进制文件兼容。

一个这样的地方是来自 nuget 的 Native Packages。所以我在那里查看了一个包,特别是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 等)
  • 发布或调试版本(即我们链接到哪个版本的 CRT)
  • 加:_ITERATOR_DEBUG_LEVEL...如果每个人都使用默认值,很好,如果项目没有,它必须声明

此外,我对以下项目的最佳猜测:

  • /O一定没关系 - 我们不断混合和匹配具有不同优化设置的二进制文件 - 具体来说,这甚至适用于同一二进制文件中的目标文件
  • /volatile- 因为这是一个代码生成的东西,我很难想象这会如何破坏 ABI
  • /EH- 除了禁用所有异常的选项,在这种情况下你显然不能调用任何抛出的东西,我非常有信心从 ABI 的角度来看这是保存:这里有可能的陷阱,但我认为他们不能真的归类为 ABI 兼容。(可能有些复杂的回调链可以说是ABI不兼容,不确定)

其他:

  • 默认调用约定 ( /G..) :我认为这会在链接时中断,当损坏的导出符号和标头声明不匹配时。
  • /Zc:wchar_t- 将在链接时中断(它实际上与 ABI 兼容,但符号不会匹配。)
  • 启用 RTTI ( /GR) - 不太确定这个 - 我从来没有使用过这个禁用。
于 2016-10-26T20:18:27.570 回答