From f9c4935762a3f21f9e199ea84f9a7c636a937038 Mon Sep 17 00:00:00 2001 From: Siddarth Kumar Date: Thu, 15 Feb 2024 19:41:55 +0530 Subject: [PATCH] fix: make run-ios-device script 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) --- Makefile | 7 +--- nix/mobile/ios/default.nix | 2 +- nix/overlay.nix | 12 ------ scripts/run-ios-device.sh | 75 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 78 insertions(+), 18 deletions(-) create mode 100755 scripts/run-ios-device.sh diff --git a/Makefile b/Makefile index 11a8d1de954..a4b1cdcb718 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/nix/mobile/ios/default.nix b/nix/mobile/ios/default.nix index affb530363c..ca423f50f17 100644 --- a/nix/mobile/ios/default.nix +++ b/nix/mobile/ios/default.nix @@ -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. diff --git a/nix/overlay.nix b/nix/overlay.nix index 63875026fd6..b0029f92f7c 100644 --- a/nix/overlay.nix +++ b/nix/overlay.nix @@ -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 { diff --git a/scripts/run-ios-device.sh b/scripts/run-ios-device.sh new file mode 100755 index 00000000000..c64445ff358 --- /dev/null +++ b/scripts/run-ios-device.sh @@ -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'