Case study / Principia
Adding iOS without turning Principia into a separate project.
Principia is a long-running community physics sandbox with an established C++ codebase and existing desktop and Android targets. The iOS work adds a device build, Apple-specific integration, packaging, and runtime fixes while keeping the repository recognizably upstream.
- Original
- Bithack / Principia community ↗
- Port repo
- NyerahMT / principia-ios ↗
- Target
- iOS 15+ / iPhone / iPad / ARM64
- Priority
- Small, maintainable upstream diff
The constraint was the repo, not just the phone.
Principia already had years of history, multiple supported platforms, its own build system, community workflows, and an active upstream project. A port that only worked by heavily rewriting the source tree would have solved the immediate problem and created a permanent maintenance problem.
The iOS work was approached as another platform target rather than a new version of Principia. Existing project files and documentation stay intact wherever possible; Apple-specific build and packaging work lives alongside the existing platform infrastructure.
A useful detail
The port repository’s README is byte-for-byte the same file as upstream. That is deliberate. The point is to add an iOS path to Principia, not rebrand or fork the project into something unrelated.
A reproducible iOS device build
The repository includes an iOS GitHub Actions workflow that builds a real ARM64 device target on macOS. CMake and Ninja configure the application for iphoneos, with an iOS 15 deployment target and ccache used to speed repeated builds.
The workflow also builds the dependencies the application needs for Apple hardware rather than assuming desktop libraries will be available on the runner.
- CMake 3.31 + Ninja device build
- ARM64 /
iphoneostarget - iOS 15.0 deployment target
- Vendored SDL3 build path
- Dependency and compiler caching in GitHub Actions
- Release IPA assembled and verified in CI
Cross-compiling the dependency stack
Principia depends on libraries that cannot simply be copied from a desktop build. The iOS dependency script cross-compiles static ARM64 versions of zlib, libpng, libjpeg-turbo, FreeType, and curl against the selected Apple SDK.
For curl, the iOS build uses Apple’s Secure Transport path. The result is a controlled dependency prefix that the main Principia CMake build can consume in CI.
- zlib
- libpng
- libjpeg-turbo
- FreeType
- curl with Secure Transport
Making the bundle behave like an iOS app
Building the executable is only part of the port. The CI path assembles the .app bundle, copies Principia’s data, generates the required icon sizes, writes Apple bundle metadata, and packages an IPA.
The bundle declares both iPhone and iPad families, landscape orientation, iOS Files support, document opening in place, and the existing principia:// URL scheme.
- iPhone and iPad device families
- Landscape orientation
- Files sharing and document access
principia://URL handling- Generated iPhone and iPad app icon sizes
- Automated IPA packaging
The device-only bugs were the real porting work.
Once the game built and ran, the remaining problems were the kind that only show up when desktop software meets the iOS lifecycle: suspend and resume behavior, rendering state after Control Center or app switching, mobile input, interface scaling, and device-specific presentation.
Those fixes are less visible than the initial build system work, but they are the difference between “the executable launches” and “the application survives normal use on an iPhone.”
Engineering priority
Keep platform fixes narrow. The less unrelated source code the iOS port has to own, the easier it is to follow upstream Principia changes later.
Why this case matters
Principia is a good example of the type of port NyerahWorks is built around: an existing project with real history, real users, and an upstream community that should not have to absorb a giant platform-specific rewrite.
The goal is not to make the iOS code look clever. It is to make iOS boring enough that the project can keep moving.