Skip to content

Commit

Permalink
fix: make run-ios-device script
Browse files Browse the repository at this point in the history
fixes #16310

We used to reply on `react-native cli` and would pass a `--device` flag to deploy the debug variant of `iOS` app on connected `iPhone`.
`react-native cli` under the hood uses `ios-deploy` library to achieve this functionality.
This showed many weird issues, specifically in locating connected devices and failures at build step with ambiguous error messages.

This commit fixes it by using our custom script `run-ios-devices.sh` which does not rely on `ios-deploy`.
We use `libimobiledevice` to identify `UDID` of a connected `iPhone`.
We use `xcrun devicectl device install app` and `xcrun devicectl device process launch` to install and launch the app.

This works well with `Xcode 15` and `iOS 17.x`.
We can now remove `ios-deploy` from `iOS` shell and `nix` overlay.

- connect your iPhone to your Laptop via a cable
- `make run-clojure`
- `make run-ios-device`
(note: no need to pass device name now)
  • Loading branch information
siddarthkay committed Feb 16, 2024
1 parent 2e23dc7 commit f9c4935
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 18 deletions.
7 changes: 2 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -294,11 +294,8 @@ show-ios-devices: ##@other shows connected ios device and its name
# TODO: fix IOS_STATUS_GO_TARGETS to be either amd64 or arm64 when RN is upgraded
run-ios-device: export TARGET := ios
run-ios-device: export IOS_STATUS_GO_TARGETS := ios/arm64;iossimulator/amd64
run-ios-device: ##@run iOS app and start it on a connected device by its name
ifndef DEVICE_NAME
$(error Usage: make run-ios-device DEVICE_NAME=your-device-name)
endif
react-native run-ios --device "$(DEVICE_NAME)"
run-ios-device: ##@run iOS app and start it on the first connected iPhone
@scripts/run-ios-device.sh

#--------------
# Tests
Expand Down
2 changes: 1 addition & 1 deletion nix/mobile/ios/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ in {
buildInputs = with pkgs; [
xcodeWrapper watchman procps
flock # used in nix/scripts/node_modules.sh
ios-deploy # used in 'make run-ios-device'
xcbeautify # used in 'make run-ios'
libimobiledevice # used in `make run-ios-device`
];

# WARNING: Executes shellHook in reverse order.
Expand Down
12 changes: 0 additions & 12 deletions nix/overlay.nix
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,6 @@ in {
react-native = callPackage ./deps/react-native { };
};

# Fix for missing libarclite_macosx.a in Xcode 14.3.
# https://github.com/ios-control/ios-deploy/issues/580
ios-deploy = super.darwin.ios-deploy.overrideAttrs (old: rec {
version = "1.12.2";
src = super.fetchFromGitHub {
owner = "ios-control";
repo = "ios-deploy";
rev = version;
sha256 = "sha256-TVGC+f+1ow3b93CK3PhIL70le5SZxxb2ug5OkIg8XCA";
};
});

# Clojure's linter receives frequent upgrades, and we want to take advantage
# of the latest available rules.
clj-kondo = super.clj-kondo.override rec {
Expand Down
75 changes: 75 additions & 0 deletions scripts/run-ios-device.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
#!/usr/bin/env bash
set -euo pipefail
set -m # needed to access jobs

GIT_ROOT=$(cd "${BASH_SOURCE%/*}" && git rev-parse --show-toplevel)

# We run Metro in background while calling adb.
cleanupMetro() {
pkill -f run-metro.sh
rm -f metro-server-logs.log
}

# Using function gives a neater jobspec name.
runMetro() {
nohup "${GIT_ROOT}/scripts/run-metro.sh" 2>&1 \
| tee metro-server-logs.log
}

waitForMetro() {
set +e # Allow grep command to fail in the loop.
TIMEOUT=5
echo "Waiting for Metro server..." >&2
while ! grep -q "Welcome to Metro" metro-server-logs.log; do
echo -n "." >&2
sleep 1
if ((TIMEOUT == 0)); then
echo -e "\nMetro server timed out, exiting" >&2
set -e # Restore errexit for rest of script.
return 1
fi
((TIMEOUT--))
done
set -e # Restore errexit for rest of script.
}

# find the first connected iPhone's UUID
DEVICE_UUID=$(idevice_id -l)

# Check if any device is connected
if [ -z "$DEVICE_UUID" ]; then
echo "No connected iPhone device detected."
exit 1
else
echo "Connected iPhone UDID: $DEVICE_UUID"
fi

BUILD_DIR="${GIT_ROOT}/build"
XCRUN_LOG_DIR="${GIT_ROOT}/build/XcrunLog"

#iOS build of debug scheme
xcodebuild -workspace "ios/StatusIm.xcworkspace" -configuration Debug -scheme StatusIm -destination id="$DEVICE_UUID" -derivedDataPath "${BUILD_DIR}" | xcbeautify

APP_PATH="${BUILD_DIR}/Build/Products/Debug-iphoneos/StatusIm.app"

# Install on the connected device
xcrun devicectl device install app --device "$DEVICE_UUID" "$APP_PATH" --json-output "$XCRUN_LOG_DIR"

# Extract installationURL
INSTALLATION_URL=$(jq -r '.result.installedApplications[0].installationURL' "$XCRUN_LOG_DIR")

# launch the app and put it in background
xcrun devicectl device process launch --no-activate --verbose --device "$DEVICE_UUID" "$INSTALLATION_URL" --json-output "$XCRUN_LOG_DIR"

# Extract background PID of status app
STATUS_PID=$(jq -r '.result.process.processIdentifier' "$XCRUN_LOG_DIR")

trap cleanupMetro EXIT ERR INT QUIT
runMetro &
waitForMetro

# now that metro is ready, resume the app from background
xcrun devicectl device process resume --device "$DEVICE_UUID" --pid "$STATUS_PID"

# bring metro job to foreground
fg 'runMetro'

0 comments on commit f9c4935

Please sign in to comment.