# How to Compile the Swift CLI for vphone-cli: Complete Build Guide

> Compile the Swift CLI for vphone-cli using the provided script. Automate Swift compilation, Git hash injection, code signing, and macOS app bundle creation for a seamless build.

- Repository: [Lakr/vphone-cli](https://github.com/Lakr233/vphone-cli)
- Tags: how-to-guide
- Published: 2026-09-06

---

**Use [`./scripts/build.sh`](https://github.com/Lakr233/vphone-cli/blob/main/./scripts/build.sh) to compile the Swift CLI for vphone-cli, which automates the full build pipeline: Swift release compilation, Git hash injection, ad-hoc code signing with private PV=3 entitlements, and macOS app bundle creation.**

The vphone-cli project provides a command-line interface for managing virtualized iOS environments on macOS. Written in Swift 6.0, the executable requires specialized handling due to its reliance on Apple's private virtualization entitlements. This guide walks through compiling the Swift CLI from source, referencing the actual implementation in the [Lakr233/vphone-cli](https://github.com/Lakr233/vphone-cli) repository.

## Prerequisites for Building vphone-cli

Before compiling, ensure your environment meets these requirements:

- **macOS 15 or later** – Required for private virtualization APIs
- **Xcode with Swift 6.0 toolchain** – For release builds
- **Homebrew** – To install supporting tools

Install all host dependencies via Homebrew:

```bash
brew install python@3.13 aria2 wget gnu-tar openssl@3 ldid-procursus sshpass keystone cmake libusb ipsw zstd

```

These tools provide the Python runtime, download utilities, code signing tools, and libraries used by both the build scripts and the compiled application.

## Step 1: Clone the Repository with Submodules

The vphone-cli build depends on external components. Clone with submodules to retrieve all required sources:

```bash
git clone --recurse-submodules https://github.com/Lakr233/vphone-cli.git
cd vphone-cli

```

The [`scripts/setup_tools.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/setup_tools.sh) script then builds the external C/C++ toolchain (including `trustcache`, `insert_dylib`, and other helpers) and creates a Python virtual environment:

```bash
./scripts/setup_tools.sh

```

## Step 2: Compile and Sign with build.sh

The [`scripts/build.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/build.sh) file is the **single entry point** for building the Swift CLI. According to the source code at [lines 36-44](https://github.com/Lakr233/vphone-cli/blob/main/scripts/build.sh#L36-L44), this script performs:

1. **Swift compilation** – `swift build -c release`
2. **Version injection** – Writes the current Git commit hash into [`sources/vphone-cli/VPhoneBuildInfo.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneBuildInfo.swift)
3. **Code signing** – Applies ad-hoc signature with `sources/vphone.entitlements`
4. **Bundle creation** – Copies the signed binary into `.build/vphone-cli.app`
5. **Guest daemon compilation** – Cross-compiles `vphoned` for iOS arm64 (unless disabled)

Run the complete build:

```bash
./scripts/build.sh

```

### Skip the Guest Daemon Build

On machines lacking an iOS arm64 toolchain, omit the guest daemon as shown at [lines 27-34](https://github.com/Lakr233/vphone-cli/blob/main/scripts/build.sh#L27-L34):

```bash
./scripts/build.sh --no-vphoned

```

## Understanding the Code Signing Requirements

The vphone-cli binary requires **private entitlements** for PV=3 (Apple's private virtualization mode). macOS rejects unsigned binaries requesting these capabilities.

The build script handles this in two phases:

- **Binary signing** – `codesign --sign -` applies an ad-hoc signature with `sources/vphone.entitlements`
- **Bundle re-signing** – After adding Resources (scripts, helpers, and `vphoned`), the entire `.app` bundle is re-signed to seal the directory

The entitlements file at `sources/vphone.entitlements` contains the private keys enabling VM functionality.

## Verify the Compiled Binary

Confirm successful compilation by running:

```bash
./.build/vphone-cli.app/Contents/MacOS/vphone-cli --help

```

Display the embedded version information:

```bash
./.build/vphone-cli.app/Contents/MacOS/vphone-cli version

```

## One-Command Build Pipeline

Execute the complete workflow from clone to running CLI:

```bash
git clone --recurse-submodules https://github.com/Lakr233/vphone-cli.git && \
cd vphone-cli && \
brew install python@3.13 aria2 wget gnu-tar openssl@3 ldid-procursus sshpass keystone cmake libusb ipsw zstd && \
./scripts/setup_tools.sh && \
./scripts/build.sh && \
./.build/vphone-cli.app/Contents/MacOS/vphone-cli --help

```

## Key Source Files

| File | Purpose |
|------|---------|
| [`scripts/build.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/build.sh) | Central build orchestration – compilation, signing, bundling |
| `sources/vphone.entitlements` | Private PV=3 entitlements required for virtualization |
| [`sources/vphone-cli/VPhoneBuildInfo.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneBuildInfo.swift) | Auto-generated file storing Git commit for version display |
| [`scripts/setup_tools.sh`](https://github.com/Lakr233/vphone-cli/blob/main/scripts/setup_tools.sh) | Toolchain setup and Python environment creation |
| `scripts/vphoned/Makefile` | iOS arm64 cross-compilation for guest daemon |

## Summary

- **Use [`./scripts/build.sh`](https://github.com/Lakr233/vphone-cli/blob/main/./scripts/build.sh)** as the single entry point to compile the Swift CLI for vphone-cli
- **Run with `--no-vphoned`** when cross-compilation for iOS arm64 is unavailable
- **Ad-hoc code signing** with private entitlements is mandatory for macOS to launch the VM
- **Version information** is injected at build time via Git commit hash in [`VPhoneBuildInfo.swift`](https://github.com/Lakr233/vphone-cli/blob/main/VPhoneBuildInfo.swift)

## Frequently Asked Questions

### What macOS version is required to compile vphone-cli?

macOS 15 or later is required. The private virtualization APIs (PV=3) used by vphone-cli are only available on recent macOS versions, and the Swift 6.0 toolchain assumes modern SDK features.

### Can I build vphone-cli without an iOS development setup?

Yes. Pass the `--no-vphoned` flag to [`./scripts/build.sh`](https://github.com/Lakr233/vphone-cli/blob/main/./scripts/build.sh) to skip cross-compiling the guest daemon. This produces a functional CLI for host-side operations, though full VM guest management requires the complete build.

### Why does the build script sign the binary twice?

The first signing applies private entitlements to the bare executable. After bundling Resources (which modifies the app structure), the entire `.app` bundle must be re-signed to create a valid, sealed package that macOS will execute.

### Where is the version information stored in the compiled binary?

The Git commit hash is written to [`sources/vphone-cli/VPhoneBuildInfo.swift`](https://github.com/Lakr233/vphone-cli/blob/main/sources/vphone-cli/VPhoneBuildInfo.swift) during the build process, then compiled into the binary. Use the `version` subcommand to display this identifier at runtime.