使用Visual Studio 2019,安装“对VS 2017 (v141)工具的C++ Windows XP支持”后,用该v141_xp
平台工具集生成的执行文件在Windows XP SP3下仍无法运行,Release版本报错,Debug版本提示“在KERNEL32.DLL中找不到xxxxxx”,典型的找不到的有InitializeSRWLock
或InitializeCriticalSectionEx
或GetLogicalProcessorInformation
等。
用dumpbin /imports
能看到对上述函数的引用,但根据MSDN说法,这些函数只在Vista及之后的版本才提供,与编译器的XP支持的设定不符。
显然出现这些问题是因为代码里指示了要用这些函数。但到底是哪里用到了呢?参考文献3描述了一次分析过程。
这里直接给结论。主要问题在于
<mutex>
和<thread>
等的引用链条当中有地方使用了这些函数,根据参考文献4的分析,可能是只做了64位XP的适配,毕竟这个年代没什么商业软件用XP的需求了,而工业软件很多懒得换工具链;一方面,要用兼容XP的方式生成boost的thread等库。根据参考文献1,以及对涉及到的库的代码研究,在用b2生成库时,需要加如下参数(但这么写的结果不对,见下文说明):
define=BOOST_USE_WINAPI_VERSION=0x0501 define=_WIN32_WINNT=0x0501 define_BOOST_USE_WINDOWS_H
同时,考虑到v141_xp
平台工具集会修改引用目录等,需要在编译boost之前先调整环境变量。环境变量可以从使用v141_xp
平台工具集的项目的属性里复制。
另一方面,如果代码中使用了 <mutex>
和<thread>
等,需要把它们换成boost的对应物。同时也需要给项目的编译条件添加上面的宏定义。
理论上似乎这样就好了,但实际上使用了上述手段之后,仍然会莫名其妙地存在对高版本API的引用。参考文件2里描述了这个奇怪的现象,并提供了解决方法:BOOST_USE_WINAPI_VERSION
的值,设定时候不能写字面值,要写成常量宏BOOST_WINAPI_VERSION_WINXP
。奇怪的是这样的确就好了。
define=BOOST_USE_WINAPI_VERSION=BOOST_WINAPI_VERSION_WINXP define=_WIN32_WINNT=0x0501 define_BOOST_USE_WINDOWS_H
这样生成出来的执行文件在XP上运行成功了。