为 Windows XP 构建 Principia
早在 2014 年 Principia 最初为 Windows 发布时,该游戏可以在早至 Windows XP 的版本上运行。考虑到 Principia 1.4 在 Windows XP 仍然有主流支持的情况下发布,这在当时当然是有意义的,并且在当时的工具和依赖项与之兼容并没有真正的理由不支持它。快进到今天,Principia 作为一个开源项目。虽然 Windows 版应该仍然可以在 Windows 7 及更早版本上运行,但我们对现代工具链、依赖项和系统库(如 UCRT)的使用意味着由于生态系统的变化,真正保证支持更长时间是困难的。然而,这一直是我想要改变的事情,将 Principia 重新带回 Windows XP,并制作一个可以在其上运行的完全开源的游戏版本。关于 Principia 的技术细节,我想首先描述与此努力相关的技术细节。Principia 是一个最初设计用于 2012 年左右手机运行的游戏,因此只要其支持至少 OpenGL 2.0,应该没有问题可以在非常旧的硬件上运行。Principia 依赖项极少,并利用 SDL 进行跨平台支持。SDL(包括 SDL2 和更新的 SDL3)仍支持 Windows XP,正如之前提到的,Principia 也曾在 Windows XP 上运行。因此,除非我在开放源代码版本的工作中进行了一些更改打破了 XP 兼容性,否则应该可以在不进行太多代码更改的情况下在 XP 上重新运行。主要问题只是工具链和其他一些依赖项已经迁移到更新的 Windows 版本上。Principia 的 Windows 版本仅正式支持使用 mingw-w64 Windows 工具链编译。虽然历史上这是因为 MSVC 缺乏对在 Principia 的后端引擎 TMS 中使用的 C99 特性的支持,我不确定现在的情况如何。然而,mingw-w64 还包含各种用于简单 C 函数的 polyfills,这些函数实际上在 Windows 上并不存在,除非有人非常感兴趣用 MSVC 构建 Principia,这种情况可能不会在短期内改变。尽管如此,FOSS 工具链通常是最容易获得更新版本的选择,可以针对旧版本的 Windows。然而,我们用于官方 Windows 构建的当前基于 LLVM 的 mingw-w64 工具链不适合于 Windows XP,因为它链接了 UCRT,LLVM 的 libc++ 是 7+,而任何其他支持库都建成了期望 Vista 中始终存在的符号。因此,我们将需要走出这一点,寻找其他解决方案……或从源代码构建某物。让我们来构建自己的工具链!当往回追溯到 Vista/7 之前,您可以找到的现有 mingw-w64 工具链的兼容性开始下降。任何基于 LLVM 的工具链对于 C++ 项目的最低要求大约是 Windows 7,因为 libc++ 不支持任何更早的版本,而其他基于 GCC 的工具链则是根据预构建支持库总是存在 Vista+ API 进行构建的。虽然有些工具链的主要目的是针对早至 95 版本,但我最终选择了自己的工具。这可能是最简单的选择,因为我特别希望拥有一个我可以在 Linux 主机上运行的跨编译工具链,目标是 Windows。好的,所以我们将编译 GCC、binutils、mingw-w64……还有什么?哦,天哪……幸运的是,我手头有一张王牌,是由 Martin Storsjö 编写的 Dockerfile(您可能知道他是 llvm-mingw 的家伙),他在 #mingw-w64 IRC 频道中链接过。满怀热情和好奇心,我已经拿到了这个 Dockerfile,将其重写为一个简单的 shell 脚本,并将其拆分为每个组件的不同步骤。我对我手头的版本进行了一些调整,将三元组更改为 i686-w64-mingw32,以支持 32 位 Windows,切换到 MSVCRT 作为目标系统运行时,并将默认 WIN32_WINNT 设置为 0x0501(Windows NT 5.1,对应 Windows XP)。然后运行它,看是否仍然能够构建……它在构建 libgmp(GNU MP 大数库)的第一步时已经失败,并且出现了一个有关没有功能性编译器的奇怪错误。困惑不已,我查看了 autotools 生成的 config.log,看到它报告了一个尝试编译一些非常奇怪的代码的错误:for ( i = 0 ; i < 1 ; i ++ ){ if ( e ( got , got , 9 , d [ i ]. n ) == 0 ) h (); g ( i , d [ i ]. src , d [ i ]. n , got , d [ i ]. want , 9 ); if ( d [ i ]. n ) h ();} 我在用最新的 GCC 16 编译,而截至写作时,GMP 的最新稳定版本(6.3.0)在默认设置下不支持在 GCC 15+ 上编译。构建系统具有一个编译时检查,包含带有空参数的函数的代码。在旧版本的 C 中,这意味着可以传递任意数量的参数(并为了防止这一点)
本站免费、广告极少。如果觉得有帮助,可以请我们喝杯咖啡 —— 任何金额都对持续运营有实际帮助。
☕请我喝杯咖啡