tools(tmux): support target devices
This introduces the following support:
./tools/tmux -t <user>@<host> out/linux_gcc_debug_arm64
It also does the following:
* Runs the script through `shellcheck`
* `shellcheck` is a linter for shell files and checks conformance
* Formats the script with `shfmt`
* Provides a consistent style for the script
* `shfmt -i 2 -ci -w tools/tmux`
* Allows arguments to the script
* `-c`: configuration
* `-t`: target
* `-C`: the build directory (similar to `ninja`)
* Allows build directory as trailing argument, similar to other tools
* Pulls the trace into `trace.protobuf` for easy uploading to UI
* Adds documentation about target `tmux` support
Change-Id: Ic422de55fe7c59cb10cf53f241522cfe46dfea31
diff --git a/docs/running.md b/docs/running.md
index 564283e..13b13ff 100644
--- a/docs/running.md
+++ b/docs/running.md
@@ -29,6 +29,12 @@
`CONFIG` variable (e.g., [this](https://android.googlesource.com/platform/external/perfetto/+/master/test/configs/ftrace.cfg)) into a protobuf and setup the right paths.
Furthermore it will automatically rebuild if necessary.
+When doing a Linux cross-build it is possible to specify a target to run the
+daemons on via SSH:
+```bash
+CONFIG=ftrace.cfg OUT=out/default TARGET=user@my-device-host ./tools/tmux
+```
+
Running from an Android P+ in-tree build
----------------------------------------
Make sure that Perfetto daemons (`traced` / `traced_probes`) are running.
diff --git a/tools/tmux b/tools/tmux
index 1d155e7..9f00b5f 100755
--- a/tools/tmux
+++ b/tools/tmux
@@ -21,67 +21,110 @@
TMPDIR=/tmp
fi
-function is_monolithic {
+function get_gn_value() {
local out=$1
- gn args $out --list --short | grep 'monolithic_binaries = true' 2>&1 >/dev/null
- return $?
+ local key=$2
+ gn args "$out" --list --short | sed -n -e "s/$key = \"\(.*\)\"/\1/p"
}
-function is_android {
+function is_monolithic() {
local out=$1
- gn args $out --list --short | grep 'target_os = "android"' 2>&1 >/dev/null
- return $?
+ value=$(get_gn_value "$out" "monolithic_binaries")
+ test "$value" == "true"
}
-function is_mac {
+function is_android() {
+ local out=$1
+ value=$(get_gn_value "$out" "target_os")
+ test "$value" == "android"
+}
+
+function is_gn_target_and_host_value_equal() {
+ local out=$1
+ local key=$2
+ local host
+ local target
+ host=$(get_gn_value "$out" "host_$key")
+ target=$(get_gn_value "$out" "target_$key")
+ [ -z "$target" ] && target="$host"
+ test "$target" == "$host"
+}
+
+function is_cross_compilation() {
+ local out=$1
+ if is_gn_target_and_host_value_equal "$out" cpu &&
+ is_gn_target_and_host_value_equal "$out" os; then
+ false
+ else
+ true
+ fi
+}
+
+function is_mac() {
! test -d /proc
return $?
}
-function tmux_ensure_bash {
+function tmux_ensure_bash() {
if [[ $SHELL == *"fish" ]]; then
tmux send-keys "bash" Enter
fi
}
-function reset_tracing {
- if is_android $OUT; then
+function reset_tracing() {
+ if is_android "$OUT"; then
adb shell 'echo 0 > /d/tracing/tracing_on'
elif ! is_mac; then
+ # shellcheck disable=SC2016
+ local script='
if [ ! -w /sys/kernel/debug ]; then
echo "debugfs not accessible, try sudo chown -R $USER /sys/kernel/debug"
- sudo chown -R $USER /sys/kernel/debug
+ sudo chown -R "$USER" /sys/kernel/debug
fi
echo 0 > /sys/kernel/debug/tracing/tracing_on
+ '
+
+ if is_cross_compilation "$OUT"; then
+ # shellcheck disable=SC2029
+ ssh "$TARGET" "sh -c '$script'"
+ else
+ sh -c "$script"
+ fi
fi
}
-function adb_supports_push_sync {
- adb --help 2>&1 | grep 'push.*\[--sync\]' 2>&1 >/dev/null
+function adb_supports_push_sync() {
+ adb --help 2>&1 | grep 'push.*\[--sync\]' >/dev/null 2>&1
}
-function push {
- if is_android $OUT; then
+function push() {
+ if is_android "$OUT"; then
local maybe_sync=''
if adb_supports_push_sync; then
- maybe_sync='--sync '
+ maybe_sync='--sync'
fi
- echo adb push $maybe_sync $1 $DIR
- adb push $maybe_sync $1 $DIR
+ echo adb push $maybe_sync "$1" "$DIR"
+ adb push $maybe_sync "$1" "$DIR"
+ elif is_cross_compilation "$OUT"; then
+ echo scp "$1" "$TARGET:$DIR"
+ scp "$1" "$TARGET:$DIR"
else
- echo cp $1 $DIR
- cp $1 $DIR
+ echo cp "$1" "$DIR"
+ cp "$1" "$DIR"
fi
}
-function pull {
- if is_android $OUT; then
- echo adb pull $DIR/$1 $2
- adb pull $DIR/$1 $2
+function pull() {
+ if is_android "$OUT"; then
+ echo adb pull "$DIR/$1" "$2"
+ adb pull "$DIR/$1" "$2"
+ elif is_cross_compilation "$OUT"; then
+ echo scp "$TARGET:$DIR/$1" "$2"
+ scp "$TARGET:$DIR/$1" "$2"
else
- echo mv $DIR/$1 $2
- mv $DIR/$1 $2
+ echo mv "$DIR/$1" "$2"
+ mv "$DIR/$1" "$2"
fi
}
@@ -89,19 +132,57 @@
SKIP_CONVERTERS=0
TMUX_LAYOUT="even-vertical"
-while getopts "bl:n" o; do
+while getopts "bl:nt:c:C:" o; do
case "$o" in
- b) BACKGROUND=1;;
- l) TMUX_LAYOUT=${OPTARG};;
- n) SKIP_CONVERTERS=1;;
- *) echo "Invalid option $o"; exit;;
+ b) BACKGROUND=1 ;;
+ l) TMUX_LAYOUT=${OPTARG} ;;
+ n) SKIP_CONVERTERS=1 ;;
+ t) TARGET=${OPTARG} ;;
+ c) CONFIG=${OPTARG} ;;
+ C) OUT=${OPTARG} ;;
+ *)
+ echo "Invalid option $o"
+ exit
+ ;;
esac
done
-# If not set guess the OUT dir using the latest directory.
+# Allow out to be passed as argument
+shift $((OPTIND - 1))
+OUT="${OUT:-$1}"
+
+# Warn about invalid output directories
+if [ -z "$OUT" ]; then
+ echo "Usage: $0 [OPTION]... [OUTPUT]"
+ echo ""
+ echo "Options:"
+ echo " -b run in the background"
+ echo " -l tmux pane layout"
+ echo " -n skip post-trace convertors"
+ echo " -t TARGET SSH device target"
+ echo " -c CONFIG trace configuration file"
+ echo " -C OUTPUT output directory"
+ echo ""
+ echo "Environment variables:"
+ echo " TARGET SSH device target"
+ echo " CONFIG trace configuration file"
+ echo " OUTPUT output directory"
+ exit 1
+fi
+
+# Warn about invalid output directories
if [ ! -f "$OUT/args.gn" ]; then
echo "OUT=$OUT doesn't look like an output directory."
- echo "Please specify a directory by doing: export OUT=out/xxx"
+ echo "Please specify a directory by doing:"
+ echo " export OUT=out/xxx $0"
+ exit 1
+fi
+
+# If we are cross-compiling we need to know the SSH target
+if is_cross_compilation "$OUT" && ! ssh -q "$TARGET" exit; then
+ echo "TARGET=$TARGET doesn't look like a valid SSH target."
+ echo "Please specify a SSH cross-compilation target by doing:"
+ echo " export TARGET=<user>@<host> $0"
exit 1
fi
@@ -109,55 +190,57 @@
# CONFIG=ftrace.cfg or to :test. Defaults to :test.
CONFIG="${CONFIG:-:test}"
-if is_android $OUT ; then
+if is_android "$OUT"; then
DIR=/data/local/tmp
+elif is_cross_compilation "$OUT"; then
+ DIR=$(ssh "$TARGET" mktemp -d $TMPDIR/perfetto.XXXXXX)
elif is_mac; then
DIR=$(mktemp -d $TMPDIR/perfetto.XXXXXX)
else
DIR=$(mktemp -p $TMPDIR -d perfetto.XXXXXX)
fi
-tools/ninja -C $OUT traced traced_probes perfetto trace_to_text test/configs
+tools/ninja -C "$OUT" traced traced_probes perfetto trace_to_text test/configs
-push $OUT/traced
-push $OUT/traced_probes
-push $OUT/perfetto
+push "$OUT/traced"
+push "$OUT/traced_probes"
+push "$OUT/perfetto"
reset_tracing
-if is_android $OUT; then
+if is_android "$OUT"; then
PREFIX="PERFETTO_CONSUMER_SOCK_NAME=@perfetto_test_consumer PERFETTO_PRODUCER_SOCK_NAME=@perfetto_test_producer"
else
PREFIX=""
fi
-if ! is_monolithic $OUT; then
+if ! is_monolithic "$OUT"; then
PREFIX="$PREFIX LD_LIBRARY_PATH=$DIR"
- push $OUT/libperfetto.so
+ push "$OUT/libperfetto.so"
fi
CONFIG_DEVICE_PATH="$CONFIG"
CMD_OPTS=""
if [[ "$CONFIG" == *.protobuf ]]; then
CONFIG_DEVICE_PATH="$CONFIG"
- CONFIG_PATH=$OUT/$CONFIG;
+ CONFIG_PATH=$OUT/$CONFIG
if [[ ! -f $CONFIG_PATH ]]; then
- echo 'Config "'$CONFIG_PATH'" not known.'
+ echo "Config \"$CONFIG_PATH\" not known."
exit 1
fi
- push $CONFIG_PATH
+ push "$CONFIG_PATH"
elif [[ "$CONFIG" != ":test" ]]; then
- CONFIG_DEVICE_PATH="$(basename $CONFIG)"
+ CONFIG_DEVICE_PATH="$(basename "$CONFIG")"
CONFIG_PATH=test/configs/$CONFIG
# Check if this is a valid absolute path
if [[ ! -f $CONFIG_PATH ]]; then
CONFIG_PATH=$CONFIG
if [[ ! -f $CONFIG_PATH ]]; then
- echo 'Config "'$CONFIG'" not known.'
+ echo "Config \"$CONFIG\" not known."
exit 1
fi
fi
CMD_OPTS="--txt $CMD_OPTS"
- push $CONFIG_PATH
+ push "$CONFIG_PATH"
fi
POSTFIX=""
@@ -184,41 +267,50 @@
tmux split-window -v
tmux split-window -v
-tmux select-layout ${TMUX_LAYOUT}
+tmux select-layout "${TMUX_LAYOUT}"
tmux select-pane -t 0
tmux send-keys "clear" C-m
-if is_android $OUT; then
+if is_android "$OUT"; then
tmux send-keys "adb shell" C-m
fi
tmux select-pane -t 1
tmux send-keys "clear" C-m
-if is_android $OUT; then
+if is_android "$OUT"; then
tmux send-keys "adb shell" C-m
fi
tmux select-pane -t 2
tmux send-keys "clear" C-m
-if is_android $OUT; then
+if is_android "$OUT"; then
tmux send-keys "adb shell" C-m
fi
sleep 2
tmux select-pane -t 1
+if is_cross_compilation "$OUT"; then
+ tmux send-keys "ssh $TARGET" Enter
+fi
tmux_ensure_bash
tmux send-keys "PS1='[traced]$ '" Enter
tmux send-keys "cd $DIR" Enter
tmux send-keys "$PREFIX ./traced 2>&1 | tee traced.log $POSTFIX" Enter
tmux select-pane -t 0
+if is_cross_compilation "$OUT"; then
+ tmux send-keys "ssh $TARGET" Enter
+fi
tmux_ensure_bash
tmux send-keys "PS1='[traced_probes]$ '" Enter
tmux send-keys "cd $DIR" Enter
tmux send-keys "$PREFIX ./traced_probes 2>&1 | tee traced_probes.log $POSTFIX" Enter
tmux select-pane -t 2
+if is_cross_compilation "$OUT"; then
+ tmux send-keys "ssh $TARGET" Enter
+fi
tmux_ensure_bash
tmux send-keys "PS1='[consumer]$ '" Enter
tmux send-keys "cd $DIR" Enter
@@ -229,18 +321,19 @@
tmux -2 attach-session -t demo
if [[ BACKGROUND -eq 1 ]]; then
- exit 0;
+ exit 0
fi
reset_tracing
TRACE=$HOME/Downloads/trace
-pull trace /tmp/trace.protobuf
+echo -e "\n\x1b[32mPulling trace into $TRACE.protobuf\x1b[0m"
+pull trace "$TRACE.protobuf"
if [[ SKIP_CONVERTERS -eq 0 ]]; then
echo -e "\n\x1b[32mPulling trace into $TRACE.pbtext\x1b[0m"
- $OUT/trace_to_text text < /tmp/trace.protobuf > $TRACE.pbtext
+ "$OUT/trace_to_text" text <"$TRACE.protobuf" >"$TRACE.pbtext"
echo -e "\n\x1b[32mPulling trace into $TRACE.json\x1b[0m"
- $OUT/trace_to_text systrace < /tmp/trace.protobuf > $TRACE.json
+ "$OUT/trace_to_text" systrace <"$TRACE.protobuf" >"$TRACE.json"
# Keep this last so it can fail.
fi