【问题标题】:vs2012 toolset compatibilityvs2012 工具集兼容性
【发布时间】:2013-01-03 18:33:38
【问题描述】:

在我的 VS2012 中,我有 4 个可用的工具集:v90、v100、v110 和 v110_xp。我用两个项目 testlib(一个静态库)和 testexe(控制台应用程序)做了一个简单的测试。该接口只是一个带有签名void test() 的函数。结果:

  • testlib(v90), testexe(v90 以外的任何东西) -> 不链接
  • testlib(v100), testexe(v110 or v110_xp) -> 链接

然而,我觉得 v100 和 v110 会链接起来有点奇怪,所以我试图让场景复杂一点。现在我的方法看起来像这样:std::map<std::string, std::string> test(const std::string& arg)。正如预期的那样,testlib(v100) 和 testexe(v110) 没有链接 (mismatch detected for '_MSC_VER')。

但 testlib(v110) 和 testexe(v110_xp) 仍然可以链接,并且生成的 exe 可以在 Windows XP 上运行。这只是偶然还是这是受支持的情况?如果这只是偶然,那么欢迎使用仅使用 v110_xp 中提供的功能并破坏这种兼容性的示例代码。我想知道是否应该将我的库的两个版本部署到我的客户,或者只使用 v110 编译的版本。

【问题讨论】:

  • 您遗漏了 2012 年 11 月的 CTP,它至少试图接近实现 C++11 标准(您知道这很难;问 Herb =P)。
  • 听起来您正在从库中公开基于标准的对象(例如 std::string 等),并希望它与基于不同工具链的所述库的客户端“正常工作” .即使它们是特定于供应商的(在这种情况下,全部来自 MS),也不能保证仅名称修饰算法的差异,更不用说完整的 ABI 对于任何基于 lib 的代码实现。无关:顺便说一句,我不知道 2012 带有 v9 工具链。你有vs2008在同一台机器上吗?
  • 是的,我在这台机器上安装了 vs2008、vs2010 和 vs2012 - 我的问题的介绍可能有点误导。

标签: c++ visual-c++ visual-studio-2012 msvcrt


【解决方案1】:

“工具集”这个词在描述 v110 和 v110_xp 之间的差异时有点用词不当。您仍在使用相同的构建工具。而且您仍然拥有相同版本的 CRT。通过比较您在两个版本之间加载的 DLL 的 Debug + Windows + Module 列表中看到的内容,您可以看到一些内容。记下 msvcr110.dll 的名称和位置。

CRT 实际上是由 Update 1 更新的,它现在支持 XP 和更新的 Windows 版本。这通过它在运行时动态绑定到后来的 winapi 函数来工作,使用 GetProcAddress(),如果在 XP 上运行时找不到它们,就会一瘸一拐地继续前进。

不同的是您获得了另一个版本的 Windows SDK。最后一个仍然与 XP 7.1 兼容的版本。您会在 C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A 中找到它。当您使用 v110 工具集构建时,您将使用存储在 C:\Program Files (x86)\Windows Kits\8.0 中的 SDK 包含和库文件

当您在 c:\program files (x86)\msbuild 目录中搜索该字符串时,可以看到使用 v110_xp 时的具体更改:

  • 包含和 lib 文件等的目录已更改为 Windows 7.1 SDK 路径
  • 添加了 _USING_V110_SDK71_ 预处理器符号,其他任何重要的地方都没有使用
  • 链接器的 /SUBSYSTEM 选项已更改为仅需要 Windows 版本 5.02,即 XP 版本号。

长话短说,混合使用 v110 和 v110_xp 工具集构建的模块不是问题。

【讨论】:

  • 我没有说 CRT 或内存分配。我提到了导入/导出类,以及在不同的 DLL 中可互换地使用类(如矢量)。假设 vector 在 A.DLL 上分配,并被传递给 B.DLL - 两个 DLL 都使用不同的编译器/链接器。这是一个众所周知、存在且可能无法解决的问题!
  • 这就是为什么认为值得一提的原因。这个无法解决的问题其实已经解决了;)
  • 我不同意。假设我有一个使用 VS2008 构建的 DLL,它采用 map<CString, long>。现在我从 VS2010/12 构建的 DLL 调用它——你怎么能确定它不会引起任何问题?这不是关于内存分配,而是关于对象本身。
  • 不,这个修复当然不能追溯。它无法访问旧的 DLL 并替换 CRT。它适用于 VS2012 构建及更高版本,OP 的情况。
  • 永远没有解决方法来设置 _WIN32_WINNT 宏错误。您必须以您想要支持的 Windows 版本为目标。如果那是 XP,那么您必须将其设置为 0x0501,这样您就不会意外使用仅在更高版本的 Windows 中可用的 winapi 函数。这与工具集完全无关,它是一般要求。
【解决方案2】:

官方不支持混合v110_xp 可执行文件和v110 库。

在与 Microsoft 单独上报此问题后,他们回答了以下问题:

Q1:使用这些库 (v110) 并使用工具集 v110_xp 构建的应用程序能否在 Windows XP 机器上正常运行?

只有使用 v110_xp 工具集构建的可执行文件才能在 Windows XP 机器上正常运行。因此,如果应用程序需要在 Windows XP 机器上正常运行,您需要确保您的项目从默认的 v110 工具集切换到项目属性页中新引入的 v110_xp 工具集,包括可执行文件和 DLL,如果有的。

Q2:我们是否需要发布使用工具集 v110_xp 构建的这些库的另一个版本?

我认为这取决于您需要在哪种平台上部署应用程序。如果您的部署计划包括 Windows XP 机器,则有必要发布使用 v110_xp 工具集构建的可执行文件/DLL 的新版本。但是,考虑到使用 v110_xp 工具集构建的相同可执行文件/DLL 也可以在 Vista 及更高版本上运行,我建议您可以只保留使用 v110_xp 工具集构建的可执行文件/DLL 的单个版本,这可以在所有其他平台上运行。当 Windows XP 不再在您的部署计划中时,您可以将整个可执行文件/DLL 转换为使用 v110 工具集进行重建。如果你想分别针对Windows XP和其他系统,如果你能同时维护两个版本的可执行文件/DLL当然会很好。

Q3:Microsoft 是否支持在 Windows XP 上使用工具集 v110 构建的库?

答案是否定的。如果您想在 Windows XP 上正常运行应用程序,一切都需要在 v110_xp 模式下构建。

【讨论】:

  • 对 DLL 有意义。但最初的问题是关于静态库的。
  • 正如 HansPassant 指出的那样:“您仍然拥有相同版本的 CRT”。我想说的是,在我看来,这两个答案并不矛盾,而且都是有效的。除了 HansPassant 的那个与这个问题更相关(但仍然感谢分享这个)。
  • @TomaszGrobelny Microsoft 的回应是针对共享库和静态库。 Windows target a specific CRT 上的静态库,所以你最终还是会一团糟。
  • 我有一个不能在 Windows XP 上运行的 exe。我能检测到它不是在 v110_xp 模式下编译的吗?
【解决方案3】:

请不要将具有/导出类的 DLL 与不同版本的 Visual Studio 混合使用(即使是微小的版本差异)。 STL 和 MFC 具有构建在模板之上的类(类本身可能没有为用户模板化),这会阻止不同版本之间的链接和/或编译。

一个简单的例子是CString:与MFC 的静态和动态链接将有不同的CString 实现。 Unicode 和 ANSI CStrings 也不同。另一个例子是 STL 本身:Debug build vector 与 release build vector 不同。此外,在 STL 集合的情况下,编译器设置也会改变容器的大小/实现(如 vectorlist)。

因此,最好不要导入具有这些类型的类作为参数的导出类/函数。甚至不要以不透明的方式传递它们(比如在 void-pointer 之上)。

【讨论】:

  • 好的,我知道混合不同的版本是不可能的(如上图)。但现在我只使用最新的 VS2012 及其特定工具集(v110 和 v110_xp)。我可以混合使用这两个工具集吗?
猜你喜欢
  • 2012-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-02
  • 2013-05-24
  • 1970-01-01
  • 2021-07-19
  • 1970-01-01
相关资源
最近更新 更多