diff options
author | Googler <noreply@google.com> | 2016-07-07 20:04:34 +0000 |
---|---|---|
committer | Klaus Aehlig <aehlig@google.com> | 2016-07-08 08:43:39 +0000 |
commit | 4be7fdbf74d91acf54300678ced0aac3c878a3df (patch) | |
tree | a0d604b90e8c7e01441821f4d571cafe602c3723 /tools/objc | |
parent | 3348513de992b5a3ab7d22dea9ad265d288c93b6 (diff) |
RELNOTES: use xcrun simctl instead of iossim to launch the app for "blaze run".
--
MOS_MIGRATED_REVID=126837234
Diffstat (limited to 'tools/objc')
-rw-r--r-- | tools/objc/ios_runner.sh.mac_template | 170 |
1 files changed, 157 insertions, 13 deletions
diff --git a/tools/objc/ios_runner.sh.mac_template b/tools/objc/ios_runner.sh.mac_template index e5fb23d942..d7141dc9f1 100644 --- a/tools/objc/ios_runner.sh.mac_template +++ b/tools/objc/ios_runner.sh.mac_template @@ -14,31 +14,175 @@ # See the License for the specific language governing permissions and # limitations under the License. -set -e +# This script is to: +# 1. create a new simulator by running "xcrun simctl create ..." +# 2. launch the created simulator by passing the ID to the simulator app, +# like: "/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app/Contents/MacOS/Simulator" -CurrentDeviceUDID "B647C213-110F-4A6B-827D-BD25313C2D1F" +# 3. install the target app on the created simulator by running +# "xcrun simctl install ..." +# 4. launch the target app on the created simulator by running +# "xcrun simctl launch <device> <app identifier> <args>", and get its PID. We +# pass in the env vars to the app by exporting the env vars adding the prefix +# "SIMCTL_CHILD_" in the calling environment. +# 5. check the app's PID periodically, exit the script when the app is not +# running. +# 6. when exit, will shutdown and delete the new created simulator. +# +# Note: the command "xcrun simctl launch ..." cannot return the app's output, +# so we pass in the StdRedirect.dylib as an $DYLD_INSERT_LIBRARIES, which +# could redirect the output to $GSTDERR and $GSTDOUT. Then we "tail -f" the +# file with the redirected content to show it on the console. + +set -eu if [[ "$(uname)" != Darwin ]]; then echo "Cannot run iOS targets on a non-mac machine." exit 1 fi -# Note: SDK_VERSION and SIM_DEVICE might contain spaces, but they are already +# Note: the sim_device and sdk_version might contain spaces, but they are already # provided in quoted form in the template variables, so we should not quote them # again here. -readonly SDK_VERSION=%sdk_version% -readonly SIM_DEVICE=%sim_device% -readonly APP_DIR=$(mktemp -d -t extracted_app) +TEST_DEVICE_ID=$(xcrun simctl create TestDevice %sim_device% %sdk_version%) + +function KillAllDevices() { + # Kill all running simulators.under Xcode 7+. The error message "No matching + # processes belonging to you were found" is expected when there's no running + # simulator. + pkill Simulator 2> /dev/null || true +} + +# Kill the tail process (we redirect the app's output to a file and use tail to +# stream the file) when the app is not running. +# Default timeout is 600 secs. User could change it by running +# "export TIME_OUT=<new_timeout_in_secs>" before invoking "blaze run" command. +# $1: the PID of the app process +# $2: the PID of the tail process +function exit_when_app_not_running() { + local time_out=${TIME_OUT:-600} + local end_time=$(($(date +%s)+${time_out})) + while kill -0 "$1" &> /dev/null; do + if [[ $(date +%s) -gt $end_time ]]; then + break + fi + sleep 1 + done + kill -9 "$2" &> /dev/null +} + +# Wait until the given simualtor is booted. +# $1: the simulator ID to boot +function wait_for_sim_to_boot() { + i=0 + while [ "${i}" -lt 10 ]; do + # The expected output of "xcrun simctl list" is like: + # -- iOS 8.4 -- + # iPhone 5s (E946FA1C-26AB-465C-A7AC-24750D520BEA) (Shutdown) + # TestDevice (8491C4BC-B18E-4E2D-934A-54FA76365E48) (Booted) + # So if there's any booted simulator, $booted_device will not be empty. + local booted_device=$(xcrun simctl list devices | grep "$1" | grep "Booted" || true) + if [ -n "${booted_device}" ]; then + # Simulator is booted. + return + fi + sleep 1 + i=$(($i+1)) + done + echo "Failed to launch the simulator" + exit 1 +} + +# Clean up the given simulator. +# $1: the simulator ID +function CleanupSimulator() { + # Device may not have started up, so no guarantee shutdown is going to be good. + xcrun simctl shutdown "$1" 2> /dev/null || true + xcrun simctl delete "$1" +} + +trap "CleanupSimulator ${TEST_DEVICE_ID}" EXIT + +readonly STD_REDIRECT_DYLIB="$PWD/%std_redirect_dylib_path%" + +readonly TEMP_DIR=$(mktemp -d -t bazel_temp) +readonly APP_DIR="${TEMP_DIR}/extracted_app" +mkdir "${APP_DIR}" + +KillAllDevices + +# Get the xcode version number, like: 6.4. +# The expected output of "xcodebuild -version" is like: +# Xcode 6.4 +# Build version 6E35b +# +# So the expected output of "xcodebuild -version|grep \"Xcode\"" is like: +# Xcode 6.4 +# +# awk will pull out the version number, e.g. "6.4". +readonly XCODE_VERSION=$(xcodebuild -version | grep "Xcode" | awk '{ print $2 }') +if [[ "${XCODE_VERSION}" == 6.* ]]; then + simulator_name="iOS Simulator" +else + simulator_name="Simulator" +fi + +# Get the developer path, like: /Applications/Xcode.app/Contents/Developer +readonly DEVELOPER_PATH=$(xcode-select -p) + +# Launch the simulator. +"${DEVELOPER_PATH}/Applications/${simulator_name}.app/Contents/MacOS/${simulator_name}" -CurrentDeviceUDID "${TEST_DEVICE_ID}" & +wait_for_sim_to_boot "${TEST_DEVICE_ID}" -args=() -# Pass environment variables prefixed with IOS_ to the simulator, stripping -# the prefix. +# Pass environment variables prefixed with "IOS_" to the simulator, replace the +# prefix with "SIMCTL_CHILD_". blaze/bazel adds "IOS_" to the env vars which +# will be passed to the app as prefix to differentiate from other env vars. We +# replace the prefix "IOS_" with "SIMCTL_CHILD_" here, because "simctl" only +# pass the env vars prefixed with "SIMCTL_CHILD_" to the app. +libs_to_insert="${STD_REDIRECT_DYLIB}" while read -r envvar; do if [[ "${envvar}" == IOS_* ]]; then - args+=(-e "${envvar#IOS_}") + if [[ "${envvar}" == IOS_DYLD_INSERT_LIBRARIES=* ]]; then + libs_to_insert=SIMCTL_CHILD_"${envvar#IOS_}":"${libs_to_insert}" + else + export SIMCTL_CHILD_"${envvar#IOS_}" + fi fi done < <(env) +export SIMCTL_CHILD_DYLD_INSERT_LIBRARIES="${libs_to_insert}" + +readonly RUN_LOG="${TEMP_DIR}/run.log" +touch "${RUN_LOG}" +export SIMCTL_CHILD_GSTDERR="${RUN_LOG}" +export SIMCTL_CHILD_GSTDOUT="${RUN_LOG}" unzip -qq '%ipa_file%' -d "${APP_DIR}" -%iossim% -d "${SIM_DEVICE}" -s "${SDK_VERSION}" \ - "${args[@]}" \ - "${APP_DIR}/Payload/%app_name%.app" \ - "$@" + +xcrun simctl install "$TEST_DEVICE_ID" "${APP_DIR}/Payload/%app_name%.app" + +# Get the bundle ID of the app. +readonly BUNDLE_INFO_PLIST="${APP_DIR}/Payload/%app_name%.app/Info.plist" +readonly BUNDLE_ID=$(/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier" "${BUNDLE_INFO_PLIST}") + +USER_NAME=${USER:-"$(logname)"} +readonly SYSTEM_LOG="/Users/${USER_NAME}/Library/Logs/CoreSimulator/${TEST_DEVICE_ID}/system.log" +rm -f "${SYSTEM_LOG}" + +# Launch the app. The expected output is: +# <bundle name, e.g. example.PrenotCalculatorBinary>: <pid of the app process> +IOS_PID=$(xcrun simctl launch "${TEST_DEVICE_ID}" "${BUNDLE_ID}" "$@") +# The awk command will abstract the pid of the app process. +IOS_PID=$(echo "${IOS_PID}" | awk '{ print $2 }') +echo "Start the app ${BUNDLE_ID} on ${TEST_DEVICE_ID}." + +# Tail the file with the redirected outputs of the app. +tail -f "${RUN_LOG}" & +exit_when_app_not_running "${IOS_PID}" "$!" + +# Check the system.log to see if there was an abnormal exit. +readonly ABNORMAL_EXIT_MSG=$(cat "${SYSTEM_LOG}" | \ + grep "com.apple.CoreSimulator.SimDevice.${TEST_DEVICE_ID}.launchd_sim" | \ + grep "Service exited with abnormal code") +if [ -n "${ABNORMAL_EXIT_MSG}" ]; then + echo "The app exited abnormally: ${ABNORMAL_EXIT_MSG}" + exit 1 +fi |