Coo*_*Cat 7 c++ windows winapi cmake visual-c++
我正在使用Visual C++ 2013编译器在Windows平台上构建一个跨平台库,特别是使用CMake(NMake生成器)构建系统.我正在使用Windows 7.
我的库使用一些仅在Windows 8/7中可用的函数/枚举值/结构成员.
我希望能够为Windows XP,Windows Vista,Windows 7和Windows 8/8.1操作系统版本以及x86,x64和arm架构构建库,即不是仅针对Windows XP并且可以在任何地方工作的单个构建,但是许多不同针对特定操作系统的构建,因为较新的操作系统版本具有我的库可以提供的更多有用功能.
我的问题是:
如何告诉编译器针对特定的OS版本(即XP,Vista,7,8,8.1等)?
如何告诉编译器针对特定架构(即x86,x64,arm等)?
如果我使用仅在Windows 8/7中可用的函数/枚举值/结构成员但是构建面向Windows XP的库,会发生什么?编译器会警告我在Windows XP上不存在这样的东西吗?或者它是否实际编译但无法在Windows XP系统上运行?
我怎么做到这一点,当我为Windows XP编译时,我的代码跳过Windows XP中不存在的东西(Windows 7/8函数等)?
在定位不同的操作系统版本时,我使用哪个Windows SDK版本是否重要?我似乎安装了8.1,8.0和7.1 Windows SDK.如果我总是使用最新的SDK版本,即使面向Windows XP,也没关系?
以下是我找到的一些答案,我不确定是正确还是完整:
我只需要设置_WIN32_WINNT和WINVER定义目标系统的适当值,就是这样,我不需要设置任何东西,我的应用程序将在指定的系统(即Windows XP)上运行.
我还需要指定适当的/SUBSYSTEM值给连接器,即/SUBSYSTEM:WINDOWS,5.02或/SUBSYSTEM:WINDOWS,6.00针对x64.但是5.02和之间有什么区别6.00?为什么两个值指定相同的东西(64位)?同为5.01和6.00,为什么他们都规定32位元?我想用64/32位的单个值就足够了.
5.01,5.02和6.00)看起来类似于WINVER来自(1)的平台值.除了架构之外,他们还设置了目标操作系统吗?但是WINVER=502从(1)用于定位Windows Server 2003,它根据维基百科以64位和32位版本发布,但在这里5.02严格代表64位,这没有意义......编译器将无法编译,因为WINVER(1)中的define将排除目标操作系统中不存在的函数和内容(Windows头文件使用定义的#ifdef东西).
我应该#ifdef基于WINVER我自己的代码,比如Windows标题,并在需要时为缺少的功能提供替代方案.
不知道.
请注意,我没有使用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,至少不会加载代码.)
有关操作系统版本的列表,请参阅Wikipedia的页面"Microsoft Windows版本列表".Windows XP是Visual Studio 2013支持的最旧版本的Windows.
Windows 8 SDK仅支持向Windows Vista开发软件.如果要为Windows XP 设置_WIN32_WINNT或WINVER构建,则需要使用Windows 7 SDK(Visual Studio 2013将安装两个SDK).
除非您的程序对于每个目标操作系统有很大的不同,否则构建一个在您想要支持的最旧操作系统(Windows XP)上运行的二进制文件可能要简单得多,并且可以延迟加载或动态加载(通过LoadLibrary/ GetProcAddress)任何当该功能可用时,您希望在较新的操作系统中使用的功能.
抱歉,这会很长:-(
\n\n\n\n\n1.如何告诉编译器针对特定操作系统版本(即 XP、Vista、7、8、8.1 等)?
\n
通常,您不会告诉编译器针对特定的操作系统版本。相反,您可以使用WINVER 和 _WIN32_WINNT从 SDK 定制头文件。头文件sdkddkver.h提供了有用的命名常量
如果您将 WINVER 和 _WIn32_WINNT 设置得足够高,头文件将声明仅在更高版本的操作系统版本中可用的函数(假设您使用的 SDK 足够新,可以声明这些函数)。
\n\n但现在您有一个程序可以调用旧操作系统版本上可能不存在的函数。如果你幸运的话,有某种兼容性垫片可以帮助你。如果你运气不好,调用未知函数的尝试就会失败。或者做一些比失败更糟糕的事情。但这是我的观点,我找不到具体的内容可以引用。
\n\n\n\n\n2.如何告诉编译器针对特定架构(即x86、x64、arm等)?
\n
你不知道。您可以为每个目标平台使用不同的编译器。如果你往下看,C:\\Program Files (x86)\\Microsoft Visual Studio 12.0\\VC\\你会发现这个bin目录和七个子目录:
amd64
\n amd64_arm
\n amd64_x86
\n 臂
\n x86_amd64
\n x86_arm
您可以使用适当目录中的编译器来为该平台构建代码。在 Win32 版本的 Windows 上,从上面的路径中删除“(x86)”。
\n\n\n\n\n3.如果我使用仅在 Windows 8/7 中可用的函数/枚举值/结构成员会发生什么...
\n
我不确定这是定义的行为。如果您将 _WIn32_WINNT 设置为 _WIN32_WINNT_WIN8,您几乎是在说“我打算在 Windows 8 及更高版本上运行它”。但这是我的观点,并非确定的事实。可能是我没有仔细阅读文档。
\n\n\n\n\n4.如何使我的代码在针对 Windows XP 进行编译时跳过 Windows XP 中不存在的内容(Windows 7/8 函数等)?
\n
您必须明确地为其编码,我不相信有任何东西可以为您解决这个问题。您可以在编译时使用#ifdef_WIN32_WINNT 来执行此操作,也可以在运行时通过确定是否可以调用该函数来执行此操作,然后根据情况调用该函数或避免调用该函数。
在所有可能的世界中(不太可能)最糟糕的情况下,将会发生重大更改,例如,结构参数的 Windows 8 格式与该函数的早期实现不兼容。在这种情况下,您必须弄清楚在调用函数时要使用哪个版本的结构 - 并且标头只会根据 _WIN32_WINNT 值提供一个结构定义。
\n\n\n\n\n5.针对不同操作系统版本时,我使用哪个 Windows SDK 版本重要吗?
\n
大概。旧版本的 SDK 可能不包含更高版本操作系统的函数定义。例如,当创建 Vista 版本的 SDK 时,Windows 8 中引入的大多数功能可能并不存在。
\n\n\n\n\n即使针对 Windows XP,如果我始终使用最新的 SDK 版本,可以吗?
\n
这可能是最安全的做法。如果您使用最新的 SDK 并将 _WIN32_WINNT 设置为 _WIN32_WINNT_WINXP,那么可能会发生正确的事情 - 假设您想在 XP 上运行。
\n\n我说“可能”是因为 XP 是一个特殊情况。它不受支持。最新的 SDK 可能已经或可能未通过将 _WIN32_WINNT 设置为 XP 值进行测试。
\n\n\n\n\n1.我只需要设置_WIN32_WINNT和WINVER定义...
\n
这应该会为您提供一个代码文件,该文件将在 _WIN32_WINNT 值标识的操作系统版本上正确执行。它很可能也适用于更高版本的操作系统(微软在推出更新的操作系统版本时会尽力不破坏现有程序)。它可能会也可能不会在早于 _Win32_WINNT 识别的操作系统版本上正确运行 - 我不会冒险。
\n\n\n\n\n\xe2\x80\xa2我在设置编译器环境变量时需要使用适当的选项
\n
由于您使用的是 NMAKE,我不确定这个问题的答案。vcvarsall.bat 文件设置各种环境变量(除其他外)可以控制使用哪一组编译器(通过控制 MSBUILD 在何处查找编译器等二进制文件)。但我不知道NMAKE是否运行MSBUILD或关注那些环境变量或有自己不同的变量集或什么。
\n\n\n\n\n\xe2\x80\xa2I 还需要为链接器指定适当的 /SUBSYSTEM 值,即 x64 的 /SUBSYSTEM:WINDOWS,5.02 或 /SUBSYSTEM:WINDOWS,6.00
\n
SUBSYSTEM 主要/次要值与平台类型(ARM、x86、x64 等)没有直接关系。它们指定代码文件运行的最低操作系统级别。因此,SUBSYSTEM 5.01 表示“此代码文件将在 XP 上运行”,而 SUBSYSTEM 5.02 表示“此代码文件将在 Windows Server 2003 上运行,但不能在 XP 上运行”。理想情况下,您应该将子系统主要/次要与 _WIN32_WINNT 匹配,以避免文件在不支持它的旧操作系统版本上运行的风险。
\n\n至少我记得是这样的 - 我没有可以用来确认我是否正确记得这一点的 XP 环境。
\n