现在才发现,学习 Visual Studio 不是一件容易的事情。特别是涉及 MSBuild 生成,还有很多内容要学习。举例来说,昨天我使用 MSBuild 结合链接 VC-LTL5 和 YY-Thunks 来编译 Python 3.10 源码就折腾了半天。好在运气不错,我成功编译出一个可以在 Windows XP 上运行的 Python 3.10。
批量链接 VC-LTL5 和 YY-Thunks 的关键就在于「Directory.Build.props」文件。关于「Directory.Build.props」,网上能查到一些资料,可以简单参考 自定义生成 - MSBuild - 20230505,这里要感谢小鸭子提示,真的是一步到位解决问题。
Python 源码「PCBuild」文件夹下就有「Directory.Build.props」,这个文件「故意留空」,目的是防止受上级目录中同名文件的影响。于是,直接编辑「Directory.Build.props」:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<!-- This is intentionally left blank but exists to avoid being imported from some directory above -->
<PropertyGroup>
<WindowsTargetPlatformVersion>10.0.23451.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformMinVersion>5.1.2600.0</WindowsTargetPlatformMinVersion>
<CleanImport>true</CleanImport>
<ForceImportAfterCppProps>$(VC_LTL)\VC-LTL helper for Visual Studio.props</ForceImportAfterCppProps>
<YY_Thunks_File>YY_Thunks_for_WinXP.obj</YY_Thunks_File>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(ProjectName)'!='python3dll'">
<Link>
<AdditionalDependencies>
$(YY_THUNKS)\objs\$(PlatformShortName)\$(YY_Thunks_File);%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
</Project>
在这里面,我做了如下配置:
- 设定 Windows SDK 版本,例如我的 SDK 版本是 10.0.23451.0
- 设定参数「WindowsTargetPlatformMinVersion」和「CleanImport」,这个「VC-LTL helper for Visual Studio.props」会用到
- 在合适的时机「ForceImportAfterCppProps」导入「VC-LTL helper for Visual Studio.props」
- 设定「YY_Thunks_File」为「YY_Thunks_for_WinXP.obj」
- 设定「运行库」为「/MT」模式
- 设定除「python3dll」项目,链接「YY_Thunks_File」
说明一下,「VC_LTL」和「YY_THUNKS」是我自己设置的环境变量,分别指向 VC-LTL 和 YY-Thunks 的 Release 中的「-Binary.」压缩包解压后的根目录。之后,转到 Python 源码根目录,按照官方的方法编译,这里我要编译 win32 即 x86 目标,执行如下代码:
.\PCbuild\build.bat -p win32
来看看最终的效果图吧!
这里挖个坑,我正考虑编写一个适用于 MSBuild 的 Thunk 配置选项,关于 Thunk 可以参考之前写的文章 为 Windows XP 编译 Rust 程序,敬请期待吧!
20230508 添加
经过测试,同样的方法编译出来的 Python 3.11 无法在 Windows 7 以下运行。原因是找不到「SetWaitableTimerEx」这个函数,我已经向 YY-Thunks 仓库提了一个 Issue #55 。等日后这个函数添加上去了,就可以在 Windows XP 上愉快的使用 Python 3.11 啦。
20230511 添加
「SetWaitableTimerEx」已经增加上去啦,现在可以在 Windows XP 上愉快的使用 Python 3.11 啦!