c++ - 使用 Visual C++ 编译器在 Windows 上构建库时如何正确设置目标操作系统版本

标签 c++ windows winapi visual-c++ cmake

我在 Windows 平台上使用具有 C++11 功能的 Visual C++ 2013 编译器构建一个跨平台库,使用 CMake(NMake 生成器)作为构建系统。我正在使用 Windows 7。

我的库使用了一些仅在 Windows 8/7 中可用的函数/枚举值/结构成员。

我希望能够为 Windows XP、Windows Vista、Windows 7 和 Windows 8/8.1 操作系统版本以及 x86、x64 和 arm 架构构建库,即不是只针对 Windows XP 并在任何地方工作的单一构建,但是许多针对特定操作系统的不同构建,因为较新的操作系统版本具有我的库可以提供的更多有用功能。

我的问题是:

  1. 如何告诉编译器以特定操作系统版本(即 XP、Vista、7、8、8.1 等)为目标?

  2. 如何告诉编译器以特定架构(即 x86、x64、arm 等)为目标?

  3. 如果我使用仅在 Windows 8/7 中可用的函数/枚举值/结构成员,但构建我的库是针对 Windows XP 的,会发生什么情况?编译器会警告我这些东西在 Windows XP 上不存在吗?还是会在 Windows XP 系统上编译但无法运行?

  4. 当我针对 Windows XP 进行编译时,我该如何使我的代码跳过 Windows XP 中不存在的内容(Windows 7/8 函数等)?

  5. 针对不同的操作系统版本时,我使用哪个 Windows SDK 版本有关系吗?我似乎已经安装了 8.1、8.0 和 7.1 Windows SDK。即使针对 Windows XP,我也始终使用最新的 SDK 版本可以吗?

以下是我找到的一些答案,但我不确定它们是否正确或完整:

  1. 我只需要将 _WIN32_WINNTWINVER 定义设置为 appropriate values for the target system就是这样,除此之外我不需要设置任何东西,我的应用程序将仅在指定的系统(即 Windows XP)上运行。

    • 在使用“C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat”设置编译器环境变量时,我需要使用适当的选项,即“C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat amd64"适用于 64 位。
    • 我还需要指定 appropriate /SUBSYSTEM value到链接器,即 /SUBSYSTEM:WINDOWS,5.02/SUBSYSTEM:WINDOWS,6.00 for x64。但是 5.026.00 有什么区别呢?为什么两个值指定相同的东西(64 位)? 5.016.00也是一样,为什么都指定32位?我认为 64/32 位具有单个值就足够了。

      • 这些值(5.015.026.00)看起来类似于来自 WINVER 的平台值(1 ).除了架构之外,他们是否还设置了目标操作系统?但是 (1) 中的 WINVER=502 用于针对 Windows Server 2003,根据维基百科,它同时发布了 64 位和 32 位版本,但在这里 5.02 严格代表 64 位, 这没有意义...
  2. 编译器将无法编译,因为 (1) 中的 WINVER 定义将排除目标操作系统中不存在的函数和内容(Windows 头文件使用 #ifdef 东西)。

  3. 我应该在我自己的代码中#ifdef 基于 WINVER 的东西,就像 Windows header 所做的那样,并在需要时为缺失的功能提供替代方案。

  4. 不知道。

请注意,我没有使用 Visual Studio IDE,所以告诉我在 IDE 中设置选项 X 有点毫无意义。

我来自 Linux 开发,所以 Windows 的东西对我来说有点新鲜。

最佳答案

您对自己问题的大部分回答都是正确的。一些澄清和更正:

子系统版本与目标架构正交。 /subsystem 文档所说的是 x86 的最低子系统版本是 5.01,x64 的最低子系统版本是 5.02。对于控制台和 Windows 应用程序,子系统版本与内部操作系统版本号相同。 5.01 是 x86 Windows XP; 5.02 是 x64 Windows XP。 Windows XP 有两个不同的版本号,因为 x64 Windows XP 的发布时间晚于 x86 Windows XP。较新的操作系统对所有体系结构具有相同的版本号(例如,Windows Vista 是 x86 和 x64 的 6.0 版)。

请注意,通过设置子系统版本,您可以限制运行程序的操作系统集。例如,如果您将子系统版本设置为 6.2,您的程序将只能在 Windows 8 及更高版本上运行。如果您尝试在例如Windows 7,它不会运行。 (对于 DLL 也是如此:如果您的 DLL 的目标操作系统比您正在运行的操作系统更新,加载程序将不会加载 DLL,至少不会加载代码执行。)

参见维基百科页面 "List of Microsoft Windows versions"获取操作系统版本列表。 Windows XP 是 Visual Studio 2013 支持的最旧的 Windows 版本。

Windows 8 SDK 仅支持低至 Windows Vista 的软件开发。如果要将 _WIN32_WINNTWINVER 设置为针对 Windows XP 构建,则需要使用 Windows 7 SDK(Visual Studio 2013 将安装这两个 SDK)。

除非您的程序对于每个目标操作系统都有很大不同,否则构建一个在您想要支持的最旧操作系统 (Windows XP) 上运行的二进制文件并延迟加载或动态加载(通过LoadLibrary/GetProcAddress)您希望在较新操作系统中使用的任何功能(当该功能可用时)。

关于c++ - 使用 Visual C++ 编译器在 Windows 上构建库时如何正确设置目标操作系统版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30960872/

相关文章:

c++ - 内核参数的 CUDA C++ 模板化

c# - 允许对象移动的 WPF 容器

c# - 有没有办法将事件处理程序附加到 C# 中正在运行的进程列表?

winapi - CreateFont的charset参数到底设置了什么?

c++ - 在c++ mfc vs2015中获取弹出资源菜单项的id

c++ - 我可以使用 Qt 将字节写入音频输出吗?

c++ - FreeType2 - 字体较小

c++ - 从 c++11 中的用户定义文字返回 std::array

c++ - 在 wxWidgets (Windows) 的 ToolBar 中添加 ComboBox

c++ - .rc 文件中的 TEXTINCLUDE 部分重复