|
| 1 | +# spell-checker:ignore termux keyevent sdcard binutils unmatch adb's dumpsys logcat pkill |
| 2 | + |
| 3 | +# There are three shells: the host's, adb, and termux. Only adb lets us run |
| 4 | +# commands directly on the emulated device, only termux provides a GNU |
| 5 | +# environment on the emulated device (to e.g. run cargo). So we use adb to |
| 6 | +# launch termux, then to send keystrokes to it while it's running. |
| 7 | +# This means that the commands sent to termux are first parsed as arguments in |
| 8 | +# this shell, then as arguments in the adb shell, before finally being used as |
| 9 | +# text inputs to the app. Hence, the "'wrapping'" on those commands. |
| 10 | +# There's no way to get any feedback from termux, so every time we run a |
| 11 | +# command on it, we make sure it ends by creating a unique *.probe file at the |
| 12 | +# end of the command. The contents of the file are used as a return code: 0 on |
| 13 | +# success, some other number for errors (an empty file is basically the same as |
| 14 | +# 0). Note that the return codes are text, not raw bytes. |
| 15 | + |
| 16 | + |
| 17 | +this_repo="$(dirname $(dirname -- "$(readlink -- "${0}")"))" |
| 18 | + |
| 19 | +help () { |
| 20 | + echo \ |
| 21 | +"Usage: $0 COMMAND [ARG] |
| 22 | +
|
| 23 | +where COMMAND is one of: |
| 24 | + snapshot APK install APK and dependencies on an emulator to prep a snapshot |
| 25 | + (you can, but probably don't want to, run this for physical |
| 26 | + devices -- just set up termux and the dependencies yourself) |
| 27 | + sync [REPO] push the repo at REPO to the device, deleting and restoring all |
| 28 | + symlinks (locally) in the process; by default, REPO is: |
| 29 | + $this_repo |
| 30 | + build run \`cargo build --features feat_os_unix_android\` on the |
| 31 | + device, then pull the output as build.log |
| 32 | + tests run \`cargo test --features feat_os_unix_android\` on the |
| 33 | + device, then pull the output as tests.log |
| 34 | +
|
| 35 | +If you have multiple devices, use the ANDROID_SERIAL environment variable to |
| 36 | +specify which to connect to." |
| 37 | +} |
| 38 | + |
| 39 | +hit_enter() { |
| 40 | + adb shell input keyevent 66 |
| 41 | +} |
| 42 | + |
| 43 | +launch_termux() { |
| 44 | + echo "launching termux" |
| 45 | + if ! adb shell 'am start -n com.termux/.HomeActivity' ; then |
| 46 | + echo "failed to launch termux" |
| 47 | + exit 1 |
| 48 | + fi |
| 49 | + # the emulator can sometimes be a little slow to launch the app |
| 50 | + while ! adb shell 'ls /sdcard/launch.probe' 2>/dev/null; do |
| 51 | + echo "waiting for launch.probe" |
| 52 | + sleep 5 |
| 53 | + adb shell input text 'touch\ /sdcard/launch.probe' && hit_enter |
| 54 | + done |
| 55 | + echo "found launch.probe" |
| 56 | + adb shell 'rm /sdcard/launch.probe' && echo "removed launch.probe" |
| 57 | +} |
| 58 | + |
| 59 | +run_termux_command() { |
| 60 | + command="$1" # text of the escaped command, including creating the probe! |
| 61 | + probe="$2" # unique file that indicates the command is complete |
| 62 | + launch_termux |
| 63 | + adb shell input text "$command" && hit_enter |
| 64 | + while ! adb shell "ls $probe" 2>/dev/null; do echo "waiting for $probe"; sleep 30; done |
| 65 | + return_code=$(adb shell "cat $probe") |
| 66 | + adb shell "rm $probe" |
| 67 | + echo "return code: $return_code" |
| 68 | + return $return_code |
| 69 | +} |
| 70 | + |
| 71 | +snapshot () { |
| 72 | + apk="$1" |
| 73 | + echo "running snapshot" |
| 74 | + adb install -g "$apk" |
| 75 | + probe='/sdcard/pkg.probe' |
| 76 | + command="'yes | pkg install rust binutils openssl -y; touch $probe'" |
| 77 | + run_termux_command "$command" "$probe" |
| 78 | + echo "snapshot complete" |
| 79 | + adb shell input text "exit" && hit_enter && hit_enter |
| 80 | +} |
| 81 | + |
| 82 | +sync () { |
| 83 | + repo="$1" |
| 84 | + echo "running sync $1" |
| 85 | + # android doesn't allow symlinks on shared dirs, and adb can't selectively push files |
| 86 | + symlinks=$(find "$repo" -type l) |
| 87 | + # dash doesn't support process substitution :( |
| 88 | + echo $symlinks >symlinks |
| 89 | + git -C "$repo" diff --name-status | cut -f 2 >modified |
| 90 | + modified_links=$(join symlinks modified) |
| 91 | + if [ ! -z "$modified_links" ]; then |
| 92 | + echo "You have modified symlinks. Either stash or commit them, then try again: $modified_links" |
| 93 | + exit 1 |
| 94 | + fi |
| 95 | + if ! git ls-files --error-unmatch $symlinks >/dev/null; then |
| 96 | + echo "You have untracked symlinks. Either remove or commit them, then try again." |
| 97 | + exit 1 |
| 98 | + fi |
| 99 | + rm $symlinks |
| 100 | + # adb's shell user only has access to shared dirs... |
| 101 | + adb push "$repo" /sdcard/coreutils |
| 102 | + git -C "$repo" checkout $symlinks |
| 103 | + # ...but shared dirs can't build, so move it home as termux |
| 104 | + probe='/sdcard/mv.probe' |
| 105 | + command="'mv /sdcard/coreutils ~/; touch $probe'" |
| 106 | + run_termux_command "$command" "$probe" |
| 107 | +} |
| 108 | + |
| 109 | +build () { |
| 110 | + probe='/sdcard/build.probe' |
| 111 | + command="'cd ~/coreutils && cargo build --features feat_os_unix_android 2>/sdcard/build.log; echo \$? >$probe'" |
| 112 | + echo "running build" |
| 113 | + run_termux_command "$command" "$probe" |
| 114 | + return_code=$? |
| 115 | + adb pull /sdcard/build.log . |
| 116 | + cat build.log |
| 117 | + return $return_code |
| 118 | +} |
| 119 | + |
| 120 | +tests () { |
| 121 | + launch_termux |
| 122 | + probe='/sdcard/tests.probe' |
| 123 | + command="'cd ~/coreutils && cargo test --features feat_os_unix_android --no-fail-fast >/sdcard/tests.log 2>&1; echo \$? >$probe'" |
| 124 | + run_termux_command "$command" "$probe" |
| 125 | + return_code=$? |
| 126 | + adb pull /sdcard/tests.log . |
| 127 | + cat tests.log |
| 128 | + return $return_code |
| 129 | +} |
| 130 | + |
| 131 | +#adb logcat & |
| 132 | +exit_code=0 |
| 133 | + |
| 134 | +if [ $# -eq 1 ]; then |
| 135 | + case "$1" in |
| 136 | + sync) sync "$this_repo"; exit_code=$?;; |
| 137 | + build) build; exit_code=$?;; |
| 138 | + tests) tests; exit_code=$?;; |
| 139 | + *) help;; |
| 140 | + esac |
| 141 | +elif [ $# -eq 2 ]; then |
| 142 | + case "$1" in |
| 143 | + snapshot) snapshot "$2"; exit_code=$?;; |
| 144 | + sync) sync "$2"; exit_code=$?;; |
| 145 | + *) help; exit 1;; |
| 146 | + esac |
| 147 | +else |
| 148 | + help |
| 149 | + exit_code=1 |
| 150 | +fi |
| 151 | + |
| 152 | +#pkill adb |
| 153 | +exit $exit_code |
0 commit comments