Visual Stuido笔记:C++二进制兼容性之间的兼容性
1. 简介
Visual Studio 2013和更早的Microsoft C++(MSVC)编译器工具集不能保证主要版本的二进制兼容性。您无法将这些工具集的不同版本构建的对象文件,静态库,动态库和可执行文件链接。 ABI,对象格式和运行时库是不兼容的。
我们在Visual Studio 2015及以后的版本中改变了这种行为。由任何这些版本的编译器编译的运行时库和应用程序都是兼容的。它反映在C++工具集的主要数字中,自Visual Studio 2015以来的所有版本开始为14个。(Visual Studio 2015的工具集版本为V140,2017年V141,2017年的V141,2019年V142,2022年的V143)。假设您拥有由Visual Studio 2015构建的第三方库。您仍然可以在Visual Studio 2017、2019或2022构建的应用程序中使用它们。无需使用匹配的工具集重新编译。 Microsoft Visual C ++重新分布软件包(可重新分布)的最新版本适用于所有这些软件包。
2. 二进制兼容性的限制
- 旧版本编译的库可以给更新的库或程序使用,比如v140(VS2015)编译的,可以给v143(VS2022)的用,新版本编译的给老版本用时,有一些限制条件。
- 有些时候,更新版本vs编译的库,如果所有导出都遵循C语言调用惯例(extern “C”),也可以给老版本vs用。但是,唯一的官方支持案例是使用较旧的工具集使用较新的Windows SDK。
新版本msvc工具集兼容老版本msvc工具集,但新版本有的功能老版本没有,所以最好的方案是都升级的最新vs编译。若要混用,也是用新的vs使用老版本vs编译的库,最差的方案是用老版本vs库用新版本vs编译出的库,需要小心处理。
未防止本人理解有误,可直接参看微软官方说明https://learn.microsoft.com/en-us/cpp/porting/binary-compat-2015-2017?view=msvc-170&source=recommendations,下文贴出文章的部分内容:
V140,V141,V142和V143工具集和次要编号版本更新之间对二进制兼容性有三个重要限制:
- 可以组合使用V140,V141,V142和V143工具集创建的二进制文件。关键规则是,链接器应仅与由与本身相同(或更早)的工具集构建的输入工作。这适用于应用程序,导入库,静态库和其他文件链接输入文件。在某些情况下,一个用于一个的导入库隐式链接可以使用工具集的较早版本链接由较晚版本的工具集构建的DLL,特别是如果导入库严格使用extern "C"用于进口/出口。以下是这一切含义的一些示例:
- 使用2017年工具集编译的应用程序(V141,版本15.0至15.9)可以链接到使用Visual Studio 2022版本17.8(V143)编译的静态库,但是必须使用版本17.8或更高版本的工具集完成链接。
- 使用VS2015、2017、2019或2022构建的应用程序和库可以将链接在一起,但是链接必须使用工具集的版本进行,该工具集的最新版本比最近的工具集更近或更新,该工具集用于构建您通过链接器的任何二进制文件。例如,给定三个二进制文件,使用VS2015版本14.3,VS 2017版本15.9和VS2019版本16.11的工具集构建,您可以使用任何16.11或更高版本的工具集版本链接它们。
- 如果使用较新的工具集构建DLL,则导入库有时可以与较旧的工具集一起使用,如果所有导出都遵循C语言调用惯例(extern “C”)。但是,唯一的官方支持案例是使用较旧的工具集使用较新的Windows SDK。
- 您的应用程序使用的可重新分布具有类似的二进制兼容性限制。当您混合由工具集的不同支持版本构建的二进制文件时,可重新分配版本必须至少与任何应用程序组件使用的最新工具集一样新。
- 静态库或对象文件使用/GL(整个程序优化)编译器开关或使用/LTCG(链接时间代码生成) 不是跨版本的二进制兼容,包括次要版本更新。所有对象文件和库都使用/GL和/LTCG必须将完全相同的工具集用于编译和最终链接。例如,使用使用的代码/GL在Visual Studio 2019版本中,16.7工具集无法通过使用的代码链接到代码/GL在Visual Studio 2019版本16.8工具集中。编译器发出致命错误C1047.
上文说明:
使用2017年工具集编译的应用程序(V141,版本15.0至15.9)可以链接到使用Visual Studio 2022版本17.8(V143)编译的静态库,但是必须使用版本17.8或更高版本的工具集完成链接。
这句话理解起来有点费劲,使用vs IDE,编译(cl.exe)与链接程序(link.exe)无法分开设置。若要分开的话,可以在nmake脚本或命令行下用路径分别指定。
如果使用较新的工具集构建DLL,则导入库有时可以与较旧的工具集一起使用,如果所有导出都遵循C语言调用惯例(extern “C”)。但是,唯一的官方支持案例是使用较旧的工具集使用较新的Windows SDK。
这里说到,老的vs的程序要用新版本编译的库且所有导出都遵循C语言调用惯例(extern “C”),唯一的官方支持案例是老的vs中的程序要用较新的Windows SDK来编译。
3. 参看
https://learn.microsoft.com/en-us/cpp/porting/binary-compat-2015-2017?view=msvc-170&source=recommendations