Skip to main content

Ubuntu setup and an iPhone over USB

This guide starts with Ubuntu 24.04 ARM64 and ends with a signed app on an iPhone. Use a Linux VM on Apple hardware for the validated setup.

You need your Xcode SDKs, an Apple Development identity, a provisioning profile, and a USB connection to the phone. Allocate space for Xcode, extracted SDKs, compiler tools, dependencies, and build products.

Install the release​

Install the runtime and setup utilities:

sudo apt-get update
sudo apt-get install ca-certificates curl libssl3t64 libgcc-s1 python3-venv usbmuxd

Download and verify the CLI archive:

CLI_VERSION=0.1.18
mkdir -p "$HOME/downloads/sweetpad-$CLI_VERSION"
cd "$HOME/downloads/sweetpad-$CLI_VERSION"
curl -fLO "https://github.com/sweetpad-dev/sweetpad/releases/download/cli-v$CLI_VERSION/sweetpad-cli-$CLI_VERSION-linux-arm64.tar.gz"
curl -fLO "https://github.com/sweetpad-dev/sweetpad/releases/download/cli-v$CLI_VERSION/sweetpad-cli-$CLI_VERSION-linux-arm64.tar.gz.sha256"
sha256sum -c "sweetpad-cli-$CLI_VERSION-linux-arm64.tar.gz.sha256"
tar -xzf "sweetpad-cli-$CLI_VERSION-linux-arm64.tar.gz"
bash install.sh
export PATH="$HOME/.local/bin:$PATH"
sweetpad --version

The installer defaults to your local user prefix. It also accepts --prefix /absolute/path. The archive includes a sample project and public toolchain setup sources. Installing the CLI requires no Rust compiler or SweetPad checkout.

Prepare the Apple toolchain​

Provide your own Xcode copy at a path visible to Ubuntu. The examples use Apple hardware; obtain and use SDK files under Apple's Xcode agreement.

Run the installed setup script:

SWEETPAD_SKIP_RUST=1 XCODE_APP=/path/to/Xcode.app \
bash "$HOME/.local/share/sweetpad/setup/sweetpad-lib/ci/linux-setup.sh"
export PATH="$HOME/.local/bin:$HOME/bin:$HOME/swift/swift-6.4.2-RELEASE/usr/bin:$PATH"

The script installs the pinned Swift toolchain, Swift Build, macro plugin, and supporting Linux tools. It imports SDK data from the Xcode copy that you supply. Existing setup results can be reused. SWEETPAD_REFRESH_SDK=1 refreshes a stale extracted SDK.

Persist the PATH entries in your shell configuration after setup. Keep the Linux Swift toolchain ahead of other Swift installations.

OrbStack on a Mac​

An OrbStack machine can see the Mac's files at the same paths. The repository setup script can create and provision the Ubuntu machine from macOS:

git clone --branch cli-v0.1.18 --depth 1 https://github.com/sweetpad-dev/sweetpad.git
cd sweetpad
SWEETPAD_SKIP_RUST=1 bash sweetpad-lib/ci/linux-setup.sh
orb -m sweetpad-linux

Install the Linux archive inside that machine using the release steps in this guide. Mac execution of the setup script also exports localized App Intents resources into the private SDK.

Build without a phone​

Use the packaged sample to confirm the compiler and SDK setup:

sweetpad build \
--project "$HOME/.local/share/sweetpad/examples/LinuxApp/LinuxApp.xcodeproj" \
--scheme LinuxApp --destination 'generic/platform=iOS Simulator' \
--json --non-interactive \
-- -derivedDataPath "$HOME/builds/LinuxApp" ARCHS=arm64 CODE_SIGNING_ALLOWED=NO

This creates simulator products. Running them still requires a Mac. For your own app, select its project or workspace and scheme.

Connect the iPhone​

Enable Developer Mode on the iPhone. Connect it with a data-capable USB cable. Then unlock it. Trust the Linux host when the phone asks.

Pass USB into a VM​

On the Mac, select and attach only the intended iPhone:

orb usb list
orb usb attach IPHONE_USB_ID -m sweetpad-linux

The VM owns that USB connection until detachment. On a direct Ubuntu installation, the cable already belongs to the Linux host.

Install the pinned adapter​

Run these commands inside Ubuntu:

python3 -m venv "$HOME/.local/share/sweetpad/device-tools"
"$HOME/.local/share/sweetpad/device-tools/bin/python" -m pip install pymobiledevice3==11.50.0
export SWEETPAD_DEVICE_PYTHON="$HOME/.local/share/sweetpad/device-tools/bin/python"
sudo systemctl start usbmuxd
"$SWEETPAD_DEVICE_PYTHON" -m pymobiledevice3 lockdown pair
sweetpad device list --json --non-interactive

Accept the Trust prompt on the phone during pairing. Use the device UDID from the list in the remaining commands. The SweetPad adapter expects USB trust to exist; listing a device does not create that trust.

Build and install the iPhone app​

Run these commands from your app's project directory. Replace the project, scheme, device ID, and product names with your own values.

Configure the identity and profile using the signing guide. Then build for the device SDK:

sweetpad build --project MyApp.xcodeproj --scheme MyApp \
--destination 'generic/platform=iOS' --json --non-interactive \
-- -derivedDataPath "$HOME/builds/MyApp" ARCHS=arm64

sweetpad device install "$HOME/builds/MyApp/Build/Products/Debug-iphoneos/MyApp.app" \
--device IPHONE_UDID --json --non-interactive

sweetpad app launch --project MyApp.xcodeproj --scheme MyApp \
--device-id IPHONE_UDID --derived-data-path "$HOME/builds/MyApp" \
--json --non-interactive

If your project changes the product name or configuration, use the product path from the build output. Installation accepts an existing signed app or IPA; it does not compile or sign it again.

Read logs and stop the app​

Use a bounded log stream:

sweetpad app logs --project MyApp.xcodeproj --device-id IPHONE_UDID \
--timeout 30s -o ndjson --non-interactive
sweetpad app stop --project MyApp.xcodeproj --device-id IPHONE_UDID \
--json --non-interactive

Logs follow the app recorded by its device launch. The adapter supports live scoped logs, not device log history. For a startup marker, subscribe to logs and relaunch the app from another terminal.

Return USB to the Mac​

After the VM session, detach the selected device on macOS:

orb usb detach IPHONE_USB_ID

If Mac tools do not see the phone again, reconnect the cable.

Troubleshooting​

SymptomFirst check
No USB deviceConfirm the cable, VM attachment, and local usbmuxd service.
Pairing failsUnlock the phone and accept its Trust prompt.
Device services failConfirm Developer Mode and the pinned Python adapter.
App installation failsCheck the profile, bundle identifiers, entitlements, and registered device.
The wrong transport is selectedRemove SWEETPAD_DEVICE_NETWORK_CONFIG from this shell to select USB.
A macro cannot loadRerun toolchain setup to refresh the macro launcher and its Swift link.

Run sweetpad help linux-devices for Wi-Fi pairing and discovery.