- README rewritten as a step-by-step guide for non-developers - install.sh: build, install and copy data with plain error messages - build_native.py: bundle identifier from the user's provisioning profile (Xcode project named factorio), version check on every build, friendly errors
142 lines
6.9 KiB
Markdown
142 lines
6.9 KiB
Markdown
# Building, installing and running
|
|
|
|
All commands run from the repository root on the Mac. Nothing needs to be installed with pip;
|
|
the scripts use only the Python standard library and Xcode's command-line tools.
|
|
|
|
## 1. Prepare the Mac
|
|
|
|
1. Install **Xcode** from the App Store, open it once, and install the **iOS** platform when it
|
|
asks (Xcode → Settings → Components).
|
|
2. Sign into your Apple developer account: Xcode → Settings → Accounts.
|
|
3. Install **Factorio for macOS through Steam** and let it finish downloading. The build expects
|
|
version **2.0.77**; it checks the SHA-256 of the executable's ARM64 slice
|
|
(`2cb4de127b50d54c6c5666acfef2263fae16d11a3361ad39353ecf8a66a4d9c7`) and stops if it differs. Turning off automatic Steam updates for the game
|
|
keeps the build working until the port is updated for a newer version.
|
|
|
|
The default game location is
|
|
`~/Library/Application Support/Steam/steamapps/common/Factorio/factorio.app/Contents`. Pass
|
|
`--game /path/to/factorio.app/Contents` (or set `FX_GAME`) if yours is elsewhere.
|
|
|
|
## 2. Prepare the iPhone
|
|
|
|
1. Connect the iPhone by cable, unlock it and tap **Trust** for this Mac.
|
|
2. Enable **Developer Mode**: Settings → Privacy & Security → Developer Mode, then restart.
|
|
3. Check that the Mac sees it:
|
|
|
|
```sh
|
|
xcrun devicectl list devices
|
|
```
|
|
|
|
The phone should be listed as `available (paired)`.
|
|
|
|
## Signing
|
|
|
|
The app is signed with your **Apple Development** certificate and a development provisioning
|
|
profile from `~/Library/Developer/Xcode/UserData/Provisioning Profiles`. The build chooses:
|
|
|
|
1. with `--bundle-id` (or `FX_BUNDLE_ID`): a profile for exactly that App ID, else a wildcard
|
|
(`TEAMID.*`) profile;
|
|
2. otherwise: the newest profile whose App ID contains `factorio`, and that App ID becomes the
|
|
app's bundle identifier;
|
|
3. otherwise: a wildcard profile, with bundle identifier `local.factorio.native`.
|
|
|
|
It signs with the keychain identity whose certificate is embedded in the chosen profile; the team
|
|
comes from the profile (override with `--team` / `FX_TEAM`). Expired profiles are ignored.
|
|
|
|
The README's step 4 creates a suitable profile: an empty Xcode iOS App project named `factorio`,
|
|
with automatic signing for your team, run once on the iPhone. Its App ID
|
|
(`com.<you>.factorio`) is unique to you, which Apple requires for explicit App IDs.
|
|
|
|
Free Apple accounts work the same way, but the installed app expires after seven days and has to
|
|
be reinstalled with `./install.sh` (saves are kept). This has been tested with a paid account
|
|
only.
|
|
|
|
## 3. Build and install
|
|
|
|
```sh
|
|
./install.sh # same as: python3 tools/build_native.py --install --push-data
|
|
```
|
|
|
|
`install.sh` runs the steps below with short progress messages and writes the full output to
|
|
`build/install.log`. What happens:
|
|
|
|
1. **Inputs.** The ARM64 slice of the game executable is extracted with `lipo` into
|
|
`build/factorio.arm64`. The Wuffs PNG decoder source (v0.3.4) is downloaded into
|
|
`third_party/wuffs/` and checked against its pinned SHA-256.
|
|
2. **Retarget.** `tools/retarget.py` writes `build/native/Factorio.dylib`, changing only Mach-O
|
|
header bytes, and records the changes in `build/native/retarget.json`.
|
|
3. **Shims and host.** The shim libraries and the small host executable are compiled for iOS
|
|
with clang; the app icon is generated from the game's own icon.
|
|
4. **Bundle and sign.** `build/native/Factorio.app` is assembled, signed, and installed with
|
|
`devicectl`.
|
|
5. **Data.** `--push-data` copies the game's `data/` folder (~1.5 GB) into the app's
|
|
`Documents/factorio/data` on the phone. This is only needed the first time, after deleting the
|
|
app, or after a game update.
|
|
|
|
The bundle never contains game data. Game settings, saves and logs are written to
|
|
`Documents/factorio/` inside the app's container and survive reinstalls.
|
|
|
|
## 4. Run
|
|
|
|
Tap the **Factorio** icon on the home screen, or launch it from the Mac with the console
|
|
attached:
|
|
|
|
```sh
|
|
python3 tools/build_native.py --no-build --launch
|
|
```
|
|
|
|
The phone must be unlocked for a launch from the Mac. Console output (the shim's `[fx]` lines and
|
|
Factorio's own log) is shown and saved to `build/native/console.log`. The first start after
|
|
installing takes the longest; the main menu normally appears after about 16 seconds.
|
|
|
|
## Options
|
|
|
|
| Option | Environment | Default |
|
|
| --- | --- | --- |
|
|
| `--game PATH` | `FX_GAME` | Steam location (see above) |
|
|
| `--team ID` | `FX_TEAM` | Taken from the provisioning profile |
|
|
| `--bundle-id ID` | `FX_BUNDLE_ID` | From the provisioning profile (see [Signing](#signing)) |
|
|
| `--device ID` | `FX_DEVICE` | First paired device |
|
|
| `--no-build` | | Install/launch the existing bundle |
|
|
|
|
`python3 tools/build_native.py --help` prints the same list.
|
|
|
|
## Rendering resolution
|
|
|
|
By default the game renders at the panel's native resolution. To render fewer pixels (for
|
|
battery or frame rate), put a divisor in `Documents/factorio/render-divisor.txt` on the phone,
|
|
for example `1.5`, using Finder's file sharing for the app or `devicectl device copy to`. Valid
|
|
values are 1 to 4. Restart the app afterwards.
|
|
|
|
## Copying saves
|
|
|
|
Saves are in `Documents/factorio/write/saves/`. With the phone connected, Finder shows the app's
|
|
files under the phone → Files → Factorio. A save from the Mac can be copied in the same way:
|
|
|
|
```sh
|
|
xcrun devicectl device copy to --device <id> --domain-type appDataContainer \
|
|
--domain-identifier <bundle identifier> \
|
|
--source ~/Library/Application\ Support/factorio/saves/my-save.zip \
|
|
--destination Documents/factorio/write/saves/my-save.zip
|
|
```
|
|
|
|
## Troubleshooting
|
|
|
|
| Symptom | Cause and fix |
|
|
| --- | --- |
|
|
| `wrong Factorio version` | The installed game is not 2.0.77. Select that version in Steam (game Properties → Betas) or pass `--game` to a 2.0.77 install. |
|
|
| `no provisioning profile found` | See [Signing](#signing). |
|
|
| `Unable to launch … because the device was not, or could not be, unlocked` | Unlock the phone and run the launch again. |
|
|
| App shows "Game data missing" | Run `python3 tools/build_native.py --no-build --push-data`. |
|
|
| App closes during play | Run with `--launch`, then `python3 tools/symbolize_native.py` to turn the `[fx-crash]` lines in `build/native/console.log` into function names. If there is no crash report, iOS may have stopped it for memory; check Settings → Privacy & Security → Analytics & Improvements → Analytics Data for a `JetsamEvent` report. |
|
|
| Image looks blurry | Check that `render-divisor.txt` is absent or contains `1`. Text size is set separately with Factorio's UI scale. |
|
|
|
|
## Diagnostics
|
|
|
|
- `python3 tools/native_audit.py build/factorio.arm64` lists, per library, the game's imports
|
|
that the iOS SDK does not provide. Every missing symbol must be implemented by a shim.
|
|
- `python3 tools/symbolize_native.py [console.log]` symbolizes crash reports using the
|
|
`factorio.dSYM` that ships with the macOS game.
|
|
- `tests/native/png_parity.m` checks the PNG decoder against macOS ImageIO for every PNG in the
|
|
game data; the build command is in [native-port.md](native-port.md#verification).
|