← 返回信息流
AI 资讯Hacker News·1 小时前

在 Windows XP 上构建 Principia 项目

原标题:Building Principia for Windows XP

速览

本文详细记录了在 Windows XP 这一古老操作系统上构建 Principia 项目的过程。尽管 XP 已停止支持,但通过特定的配置和工具链调整,仍可实现项目的编译与运行。这一实践展示了跨平台兼容性的技术细节。

AI 深度解读

构建 Principia 以运行于 Windows XP:一次复古兼容性的技术深潜

背景

Principia 是一款基于 Kerbal Space Program(坎巴拉太空计划)物理引擎的开源模组,以其高精度的轨道力学模拟而闻名。该模组最初于 2014 年发布 Windows 版本,当时为了兼容更广泛的硬件,官方支持从 Windows XP 开始的系统版本。考虑到当时 Principia 1.4 版本发布时,Windows XP 仍处于主流支持周期,且当时的构建工具和依赖项均兼容该系统,这一策略在当时合情合理。

然而,随着时间推移,Principia 作为一个开源项目,其技术栈发生了显著变化。虽然理论上 Windows 版本应能向后兼容至 Windows 7,但由于现代工具链、依赖项以及系统库(如通用 C 运行时 UCRT)的演进,确保其在未来长期稳定运行变得愈发困难。尽管当前版本仅保证支持到 Windows 7,但作者始终怀有一个愿景:将 Principia 带回 Windows XP,并产出一个完全开源、可在该古老系统上运行的构建版本。

核心内容

技术可行性分析

Principia 最初设计用于运行在 2012 年左右的智能手机上,因此其对硬件的要求极低。只要系统支持 OpenGL 2.0,它理应能在非常老旧的硬件上流畅运行。Principia 的依赖项极少,并利用 SDL(Simple DirectMedia Layer)实现跨平台支持。无论是 SDL2 还是更新的 SDL3,均保留了对 Windows XP 的支持。因此,除非作者在开源化过程中引入了破坏 XP 兼容性的代码变更,否则理论上只需少量修改即可让其在 XP 上重新运行。

主要障碍在于工具链(Toolchain)及部分依赖项已不再支持旧版 Windows。

工具链的挑战与自建方案

Principia 的 Windows 版本官方仅支持使用 mingw-w64 工具链进行编译。历史上,这是因为 MSVC(Microsoft Visual C++)缺乏对 Principia 后端引擎 TMS 所使用的 C99 特性的支持。虽然 mingw-w64 包含了一些 Windows 原生不存在的简单 C 函数的 polyfills(多态填充),但在没有强烈兴趣迁移至 MSVC 的情况下,这一现状短期内不会改变。

自由开源软件(FOSS)工具链通常最容易获取支持旧版 Windows 的现代版本。然而,MSYS2 提供的基于 LLVM 的 mingw-w64 工具链并不适合目标为 Windows XP,原因包括:

  1. 链接至 UCRT(通用 C 运行时)。
  2. LLVM 的 libc++ 最低支持 Windows 7+。
  3. 其他支持库在构建时假定 Vista 及更高版本的符号始终存在。

鉴于现成的 mingw-w64 工具链在 Vista/7 之前的兼容性开始下降(LLVM 工具链因 libc++ 限制最低支持 Win7,GCC 工具链则假定 Vista+ API 存在),作者决定自行构建一个交叉编译工具链,以便在 Linux 主机上编译针对 Windows 的 32 位可执行文件。

构建自定义工具链的过程

作者基于 Martin Storsjö(llvm-mingw 项目维护者)提供的 Dockerfile 进行了修改,将其重写为 Shell 脚本并分步执行。关键配置调整如下:

  • 目标三元组(Triplet):设置为 i686-w64-mingw32 以支持 32 位 Windows。
  • 系统运行时:切换为 MSVCRT(而非 UCRT)。
  • 最低 Windows 版本:设置 WIN32_WINNT0x0501(即 Windows NT 5.1,对应 Windows XP)。

遇到的第一个障碍:GMP 编译失败 在构建 GNU MP Bignum 库(libgmp)时,构建因编译器错误而失败。日志显示,GCC 16 默认使用 C23 标准,而在 C23 中,空参数列表 () 意味着“无参数”,这与旧版 C 标准中“任意参数”的含义不同。GMP 6.3.0 的构建系统包含一段旧式代码,导致 GCC 16 将其误判为编译器故障。

  • 解决方案:作者通过配置 GMP 使用 -std=gnu99 标准解决了此问题,无需重新生成 autotools 文件。

后续构建流程 问题解决后,构建过程相对顺利:依次编译 MPFR、MPC、binutils、GCC,然后使用新编译的 GCC 构建 mingw-w64 的 CRT 和库,最后构建 GCC 自身的库。

遇到的第二个障碍:libstdc++ 对 Vista+ API 的依赖 在编译 GCC 期间,作者发现 GCC 16 附带的 libstdc++ 新增了对 Vista 及以上版本 Win32 API 函数 GetDynamicTimeZoneInformation 的硬性依赖,该函数用于 std::chrono 中的时区处理。

  • 解决方案:作者借鉴了 w64devkit(32 位版本同样使用 GCC 16 且支持 XP)的方案。该方案通过补丁将上述 API 依赖改为动态链接:尝试获取符号,若不存在则回退。鉴于 Principia 几乎不使用 C++20 特性(std::chrono 为 C++20 特性,Principia 主要使用 C++11),直接存根(stubbing)该函数亦可,但采用现成的干净补丁更为稳妥。

最终,作者成功构建了一个确信能生成 Windows XP 可执行文件的工具链。通过 Wine 运行一个简单的 Hello World 程序进行了冒烟测试,证实编译器确实能创建可运行的 Windows 可执行文件。

依赖项的构建

在构建 Principia 之前,需使用新工具链构建其外部依赖项,包括:

  • curl
  • Freetype
  • libjpeg-turbo
  • libpng
  • SDL
  • zlib

其中,curl 成为最大的麻烦点。curl 8.19.0 已正式放弃对 Windows XP 的支持。更棘手的是,即使是 8.18.0 版本,也试图在 msvcrt.dll 中定位 freopen_s 函数,而该函数在 XP 中不存在。最终,作者选择了较新的 curl 8.17.0 版本。

对于其他通用库的交叉编译,作者使用了 Luanti 核心开发者 sfan5 提供的构建脚本仓库。

关键要点

  • 兼容性愿景:作者旨在为 Principia 创建一个完全开源的构建版本,使其能在 Windows XP 上运行,尽管现代工具链通常不再支持该系统。
  • 工具链选择:现成的基于 LLVM 的 mingw-w64 工具链(如 MSYS2 提供)因依赖 UCRT 和 libc++(最低支持 Win7)而不适用。作者选择自建基于 GCC 的交叉编译工具链。
  • C 标准冲突:GCC 16 默认启用 C23 标准,导致 GMP 6.3.0 中旧式空参数列表代码编译失败。通过指定 -std=gnu99 解决。
  • API 依赖处理:GCC 16 的 libstdc++ 硬依赖 Vista 的 GetDynamicTimeZoneInformation 函数。通过应用类似 w64devkit 的动态符号获取补丁,实现了对 XP 的兼容。
  • 依赖项版本妥协:curl 8.19.0+ 不再支持 XP 且引入了 XP 不存在的 freopen_s 函数。作者回退至 curl 8.17.0 以维持兼容性。
  • 硬件要求极低:Principia 设计之初即面向低端硬件,只要支持 OpenGL 2.0 即可运行,因此在 XP 上运行无性能瓶颈。

意义与影响

这一技术实践展示了在开源社区中,通过手动构建和维护定制化工具链,可以突破现代开发环境对老旧系统的抛弃趋势。对于 Principia

查看原文 →voxelmanip.se