mirror of
https://git.suyu.dev/suyu/breakpad.git
synced 2025-12-26 09:14:58 +01:00
Fix 'make check' for Android
This patch allows 'make check' to work when performing
an Automake-based build of Breakpad for Android. This
requires to have an Android device connected, and the
'adb' tool in your path.
You can test that with something like:
configure --host=arm-linux-androideabi
make check
This is achieved by adding a new small shell script
under android/test-shell.sh, which is invoked by the
Makefile (see TESTS_ENVIRONMENT definition in
Makefile.am).
By default, this runs all unit tests, including those
for the processor and tools (which normally never run
on an Android device).
Note that the test suites fails (e.g. 11 failing tests
for the client library). This will be addressed in later
patches.
+ Modify android/run-checks.sh to run the client library
test suite on the device by default.
+ Add a new option (--all-tests) to android/run-checks.sh
which forces it to run the unit test suite for the host
binaries, and the full suite on the Android device.
+ Update README.ANDROID appropriately.
Review URL: https://breakpad.appspot.com/441002
git-svn-id: http://google-breakpad.googlecode.com/svn/trunk@1023 4c0a9323-5329-0410-9bdc-e9ce6186880e
This commit is contained in:
parent
02f664dbf4
commit
fa064e215b
6 changed files with 668 additions and 214 deletions
|
|
@ -40,59 +40,14 @@ PROGDIR=$(dirname "$0")
|
|||
PROGDIR=$(cd "$PROGDIR" && pwd)
|
||||
PROGNAME=$(basename "$0")
|
||||
|
||||
# Utility functions
|
||||
|
||||
TMPDIR=
|
||||
|
||||
# Used to exit the program after removing the temporary directory.
|
||||
clean_exit () {
|
||||
if [ "$TMPDIR" ]; then
|
||||
if [ -z "$NO_CLEANUP" ]; then
|
||||
log "Cleaning up: $TMPDIR"
|
||||
rm -rf "$TMPDIR"
|
||||
else
|
||||
dump "Temporary directory contents preserved: $TMPDIR"
|
||||
fi
|
||||
fi
|
||||
exit "$@"
|
||||
}
|
||||
|
||||
# Dump a panic message then exit.
|
||||
panic () {
|
||||
echo "ERROR: $@"
|
||||
clean_exit 1;
|
||||
}
|
||||
|
||||
# If the previous command failed, dump a panic message then exit.
|
||||
fail_panic () {
|
||||
if [ $? != 0 ]; then
|
||||
panic "$@"
|
||||
fi;
|
||||
}
|
||||
|
||||
# Extract number of cores to speed up the builds
|
||||
get_core_count () {
|
||||
case $(uname -s) in
|
||||
Linux)
|
||||
grep -c -e '^processor' /proc/cpuinfo
|
||||
;;
|
||||
Darwin)
|
||||
sysctl -n hw.ncpu
|
||||
;;
|
||||
CYGWIN*|*_NT-*)
|
||||
echo $NUMBER_OF_PROCESSORS
|
||||
;;
|
||||
*)
|
||||
echo 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
. $PROGDIR/common-functions.sh
|
||||
|
||||
DEFAULT_ABI="armeabi"
|
||||
VALID_ABIS="armeabi armeabi-v7a x86 mips"
|
||||
|
||||
ABI=
|
||||
ADB=
|
||||
ALL_TESTS=
|
||||
ENABLE_M32=
|
||||
HELP=
|
||||
HELP_ALL=
|
||||
|
|
@ -101,7 +56,6 @@ NO_CLEANUP=
|
|||
NO_DEVICE=
|
||||
NUM_JOBS=$(get_core_count)
|
||||
TMPDIR=
|
||||
VERBOSE=0
|
||||
|
||||
for opt do
|
||||
# The following extracts the value if the option is like --name=<value>.
|
||||
|
|
@ -109,6 +63,7 @@ for opt do
|
|||
case $opt in
|
||||
--abi=*) ABI=$optarg;;
|
||||
--adb=*) ADB=$optarg;;
|
||||
--all-tests) ALL_TESTS=true;;
|
||||
--enable-m32) ENABLE_M32=true;;
|
||||
--help|-h|-?) HELP=TRUE;;
|
||||
--help-all) HELP_ALL=true;;
|
||||
|
|
@ -117,8 +72,8 @@ for opt do
|
|||
--tmp-dir=*) TMPDIR=$optarg;;
|
||||
--no-cleanup) NO_CLEANUP=true;;
|
||||
--no-device) NO_DEVICE=true;;
|
||||
--quiet) VERBOSE=$(( $VERBOSE - 1 ));;
|
||||
--verbose) VERBOSE=$(( $VERBOSE + 1 ));;
|
||||
--quiet) decrease_verbosity;;
|
||||
--verbose) increase_verbosity;;
|
||||
-*) panic "Invalid option '$opt', see --help for details.";;
|
||||
*) panic "This script doesn't take any parameters. See --help for details."
|
||||
;;
|
||||
|
|
@ -180,6 +135,12 @@ if [ "$HELP" -o "$HELP_ALL" ]; then
|
|||
--abi=<name> to override this. Valid ABI names are:
|
||||
|
||||
$VALID_ABIS
|
||||
|
||||
The script will only run the client library unit test on the device
|
||||
by default. You can use --all-tests to also build and run the unit
|
||||
tests for the Breakpad tools and processor, but be warned that this
|
||||
adds several minutes of testing time. --all-tests will also run the
|
||||
host unit tests suite.
|
||||
"
|
||||
|
||||
fi # HELP_ALL
|
||||
|
|
@ -197,67 +158,13 @@ if [ "$HELP" -o "$HELP_ALL" ]; then
|
|||
--adb=<path> Specify adb program path.
|
||||
--no-cleanup Don't remove temporary directory after completion.
|
||||
--no-device Do not try to detect devices, nor run crash test.
|
||||
--all-tests Run all unit tests (i.e. tools and processor ones too).
|
||||
--verbose Increase verbosity.
|
||||
--quiet Decrease verbosity."
|
||||
|
||||
clean_exit 0
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Dump message to stdout, unless verbosity is < 0, i.e. --quiet was called
|
||||
dump () {
|
||||
if [ "$VERBOSE" -ge 0 ]; then
|
||||
echo "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# If --verbose was used, dump a message to stdout.
|
||||
log () {
|
||||
if [ "$VERBOSE" -ge 1 ]; then
|
||||
echo "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
# Run a command. Output depends on $VERBOSE:
|
||||
# $VERBOSE <= 0: Run command, store output into the run log
|
||||
# $VERBOSE >= 1: Dump command, run it, output goest to stdout
|
||||
# Note: Ideally, the command's output would go to the run log for $VERBOSE >= 1
|
||||
# but the 'tee' tool doesn't preserve the status code of its input pipe
|
||||
# in case of error.
|
||||
run () {
|
||||
local LOGILE
|
||||
if [ "$RUN_LOG" ]; then
|
||||
LOGFILE=$RUN_LOG
|
||||
else
|
||||
LOGFILE=/dev/null
|
||||
fi
|
||||
|
||||
if [ "$VERBOSE" -ge 1 ]; then
|
||||
echo "COMMAND: $@"
|
||||
"$@"
|
||||
else
|
||||
"$@" >>$LOGFILE 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
# Same as run(), but only dump command output for $VERBOSE >= 2
|
||||
run2 () {
|
||||
local LOGILE
|
||||
if [ "$RUN_LOG" ]; then
|
||||
LOGFILE=$RUN_LOG
|
||||
else
|
||||
LOGFILE=/dev/null
|
||||
fi
|
||||
|
||||
if [ "$VERBOSE" -ge 1 ]; then
|
||||
echo "COMMAND: $@"
|
||||
fi
|
||||
if [ "$VERBOSE" -ge 2 ]; then
|
||||
"$@"
|
||||
else
|
||||
"$@" >>$LOGFILE 2>&1
|
||||
fi
|
||||
}
|
||||
|
||||
TESTAPP_DIR=$PROGDIR/sample_app
|
||||
|
||||
# Select NDK install directory.
|
||||
|
|
@ -277,6 +184,23 @@ if [ ! -f "$NDK_BUILD" ]; then
|
|||
panic "Your NDK directory is not valid (missing ndk-build): $NDK_DIR"
|
||||
fi
|
||||
|
||||
# Ensure the temporary directory is deleted on exit, except if the --no-cleanup
|
||||
# option is used.
|
||||
|
||||
clean_tmpdir () {
|
||||
if [ "$TMPDIR" ]; then
|
||||
if [ -z "$NO_CLEANUP" ]; then
|
||||
log "Cleaning up: $TMPDIR"
|
||||
rm -rf "$TMPDIR"
|
||||
else
|
||||
dump "Temporary directory contents preserved: $TMPDIR"
|
||||
fi
|
||||
fi
|
||||
exit "$@"
|
||||
}
|
||||
|
||||
atexit clean_tmpdir
|
||||
|
||||
# If --tmp-dir=<path> is not used, create a temporary directory.
|
||||
# Otherwise, start by cleaning up the user-provided path.
|
||||
if [ -z "$TMPDIR" ]; then
|
||||
|
|
@ -294,101 +218,26 @@ else
|
|||
fi
|
||||
fi
|
||||
|
||||
# Ensure a clean exit when the script is:
|
||||
# - Interrupted by Ctrl-C (INT)
|
||||
# - Interrupted by log out (HUP)
|
||||
# - Being asked to quit nicely (TERM)
|
||||
# - Being asked to quit and dump core (QUIT)
|
||||
trap "clean_exit 1" INT HUP TERM QUIT
|
||||
|
||||
# The 'adb shell' command is pretty hopeless, try to make sense of it by:
|
||||
# 1/ Removing trailing \r from line endings.
|
||||
# 2/ Ensuring the function returns the command's status code.
|
||||
#
|
||||
adb_shell () {
|
||||
local RET ADB_LOG
|
||||
ADB_LOG=$(mktemp "$TMPDIR/adb-XXXXXXXX")
|
||||
"$ADB" shell "$@" ";" echo \$? > "$ADB_LOG" 2>&1
|
||||
sed -i -e 's![[:cntrl:]]!!g' "$ADB_LOG" # Remove \r.
|
||||
RET=$(sed -e '$!d' "$ADB_LOG") # Last line contains status code.
|
||||
sed -e '$d' "$ADB_LOG" # Print everything except last line.
|
||||
rm -f "$ADB_LOG"
|
||||
return $RET
|
||||
}
|
||||
|
||||
check_for_adb () {
|
||||
local ADB_VERSION ADB_DEVICES NUM_DEVICES FINGERPRINT
|
||||
|
||||
# Auto-detect ADB in current path when needed.
|
||||
if [ -z "$ADB" ]; then
|
||||
ADB=$(which adb 2>/dev/null)
|
||||
if [ -z "$ADB" ]; then
|
||||
panic "The 'adb' tool is not in your path! Use either --no-device to\
|
||||
only check the builds, or --adb=<path> to specify the tool path."
|
||||
fi
|
||||
log "Found ADB path: $ADB"
|
||||
else
|
||||
log "Using ADB path: $ADB"
|
||||
fi
|
||||
|
||||
# Check that it works.
|
||||
ADB_VERSION=$("$ADB" version 2>/dev/null)
|
||||
case $ADB_VERSION in
|
||||
"Android Debug Bridge "*) # Pass.
|
||||
log "Found ADB version: $ADB_VERSION"
|
||||
;;
|
||||
*) # Fail.
|
||||
panic "Your ADB binary does not seem to work: $ADB"
|
||||
;;
|
||||
esac
|
||||
|
||||
# Count the number of connected devices.
|
||||
ADB_DEVICES=$("$ADB" devices 2>/dev/null | awk '$2 == "device" { print $1; }')
|
||||
if [ "$ADB_DEVICES" ]; then
|
||||
NUM_DEVICES=$(echo "$ADB_DEVICES" | wc -l)
|
||||
else
|
||||
NUM_DEVICES=0
|
||||
fi
|
||||
case $NUM_DEVICES in
|
||||
0)
|
||||
panic "No Android device connected! Connect one, or use --no-device \
|
||||
to only check the builds."
|
||||
;;
|
||||
1)
|
||||
export ANDROID_SERIAL=$ADB_DEVICES
|
||||
;;
|
||||
*)
|
||||
if [ "$ANDROID_SERIAL" ]; then
|
||||
ADB_DEVICES=$ANDROID_SERIAL
|
||||
NUM_DEVICES=1
|
||||
else
|
||||
dump "ERROR: More than one Android device connected. Please define \
|
||||
ANDROID_SERIAL"
|
||||
dump " in your environment, or use --no-device to only check \
|
||||
the builds."
|
||||
clean_exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
FINGERPRINT=$(adb_shell getprop ro.build.fingerprint)
|
||||
dump "Using device: $ANDROID_SERIAL ($FINGERPRINT)"
|
||||
}
|
||||
|
||||
if [ -z "$NO_DEVICE" ]; then
|
||||
check_for_adb
|
||||
if ! adb_check_device $ADB; then
|
||||
echo "$(adb_get_error)"
|
||||
echo "Use --no-device to build the code without running any tests."
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
BUILD_LOG="$TMPDIR/build.log"
|
||||
RUN_LOG="$TMPDIR/run.log"
|
||||
CRASH_LOG="$TMPDIR/crash.log"
|
||||
|
||||
set_run_log "$RUN_LOG"
|
||||
|
||||
TMPHOST="$TMPDIR/host-local"
|
||||
|
||||
cd "$TMPDIR"
|
||||
|
||||
# Build host version of the tools
|
||||
dump "Building host tools."
|
||||
dump "Building host binaries."
|
||||
CONFIGURE_FLAGS=
|
||||
if [ "$ENABLE_M32" ]; then
|
||||
CONFIGURE_FLAGS="$CONFIGURE_FLAGS --enable-m32"
|
||||
|
|
@ -399,14 +248,23 @@ fi
|
|||
run2 "$PROGDIR/../configure" --prefix="$TMPHOST" $CONFIGURE_FLAGS &&
|
||||
run2 make -j$NUM_JOBS install
|
||||
)
|
||||
fail_panic "Can't build host-tools!"
|
||||
fail_panic "Can't build host binaries!"
|
||||
|
||||
if [ "$ALL_TESTS" ]; then
|
||||
dump "Running host unit tests."
|
||||
(
|
||||
run cd "$TMPDIR/build-host" &&
|
||||
run2 make -j$NUM_JOBS check
|
||||
)
|
||||
fail_panic "Host unit tests failed!!"
|
||||
fi
|
||||
|
||||
TMPBIN=$TMPHOST/bin
|
||||
|
||||
# Generate a stand-alone NDK toolchain
|
||||
|
||||
# Extract CPU ABI and architecture from device, if any.
|
||||
if [ "$ADB" ]; then
|
||||
if adb_check_device; then
|
||||
DEVICE_ABI=$(adb_shell getprop ro.product.cpu.abi)
|
||||
DEVICE_ABI2=$(adb_shell getprop ro.product.cpu.abi2)
|
||||
if [ -z "$DEVICE_ABI" ]; then
|
||||
|
|
@ -477,15 +335,17 @@ esac
|
|||
NDK_STANDALONE="$TMPDIR/ndk-$ARCH-toolchain"
|
||||
echo "Generating NDK standalone toolchain installation"
|
||||
mkdir -p "$NDK_STANDALONE"
|
||||
# NOTE: The --platform=android-9 is required to provide <regex.h> for GTest.
|
||||
run "$NDK_DIR/build/tools/make-standalone-toolchain.sh" \
|
||||
--arch="$ARCH" \
|
||||
--platform=android-9 \
|
||||
--install-dir="$NDK_STANDALONE"
|
||||
fail_panic "Can't generate standalone NDK toolchain installation!"
|
||||
|
||||
# Rebuild the client library, processor and tools with the auto-tools based
|
||||
# build system. Even though it's not going to be used, this checks that this
|
||||
# still works correctly.
|
||||
echo "Building Android binaries with configure/make"
|
||||
echo "Building full Android binaries with configure/make"
|
||||
TMPTARGET="$TMPDIR/target-local"
|
||||
(
|
||||
PATH="$NDK_STANDALONE/bin:$PATH"
|
||||
|
|
@ -498,6 +358,40 @@ TMPTARGET="$TMPDIR/target-local"
|
|||
)
|
||||
fail_panic "Could not rebuild Android binaries!"
|
||||
|
||||
# Build and/or run unit test suite.
|
||||
# If --no-device is used, only rebuild it, otherwise, run in on the
|
||||
# connected device.
|
||||
if [ "$NO_DEVICE" ]; then
|
||||
ACTION="Building"
|
||||
# This is a trick to force the Makefile to ignore running the scripts.
|
||||
TESTS_ENVIRONMENT="TESTS_ENVIRONMENT=true"
|
||||
else
|
||||
ACTION="Running"
|
||||
TESTS_ENVIRONMENT=
|
||||
fi
|
||||
if [ "$ALL_TESTS" ]; then
|
||||
dump "$ACTION full Android unit tests."
|
||||
else
|
||||
dump "$ACTION Android client library unit tests."
|
||||
fi
|
||||
|
||||
(
|
||||
PATH="$NDK_STANDALONE/bin:$PATH"
|
||||
run cd "$TMPDIR"/build-target &&
|
||||
if [ -z "$ALL_TESTS" ]; then
|
||||
# Reconfigure to avoid building the unit tests for the tools
|
||||
# and processor, unless --all-tests is used.
|
||||
run2 "$PROGDIR"/../configure --prefix="$TMPTARGET" \
|
||||
--host="$GNU_CONFIG" \
|
||||
--disable-tools \
|
||||
--disable-processor
|
||||
fi &&
|
||||
run make -j$NUM_JOBS check $TESTS_ENVIRONMENT
|
||||
)
|
||||
if [ -z "$NO_DEVICE" ] && verbosity_is_lower_than 2; then
|
||||
dump " Unit tests failed as expected. Use --verbose to see results."
|
||||
fi
|
||||
|
||||
# Copy sources to temporary directory
|
||||
PROJECT_DIR=$TMPDIR/project
|
||||
dump "Copying test program sources to: $PROJECT_DIR"
|
||||
|
|
@ -510,7 +404,7 @@ fail_panic "Could not copy test program sources to: $PROJECT_DIR"
|
|||
dump "Building test program with ndk-build"
|
||||
export NDK_MODULE_PATH="$PROGDIR"
|
||||
NDK_BUILD_FLAGS="-j$NUM_JOBS"
|
||||
if [ "$VERBOSE" -ge 2 ]; then
|
||||
if verbosity_is_higher_than 1; then
|
||||
NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS NDK_LOG=1 V=1"
|
||||
fi
|
||||
run "$NDK_DIR/ndk-build" -C "$PROJECT_DIR" $NDK_BUILD_FLAGS APP_ABI=$ABI
|
||||
|
|
@ -533,7 +427,7 @@ fi
|
|||
# Run the program there
|
||||
dump "Installing test program on device"
|
||||
DEVICE_TMP=/data/local/tmp
|
||||
run "$ADB" push "$TESTAPP_FILE" "$DEVICE_TMP/"
|
||||
adb_push "$TESTAPP_FILE" "$DEVICE_TMP/"
|
||||
fail_panic "Cannot push test program to device!"
|
||||
|
||||
dump "Running test program on device"
|
||||
|
|
@ -541,7 +435,7 @@ adb_shell cd "$DEVICE_TMP" "&&" ./$TESTAPP > "$CRASH_LOG" 2>/dev/null
|
|||
if [ $? = 0 ]; then
|
||||
panic "Test program did *not* crash as expected!"
|
||||
fi
|
||||
if [ "$VERBOSE" -ge 1 ]; then
|
||||
if verbosity_is_higher_than 0; then
|
||||
echo -n "Crash log: "
|
||||
cat "$CRASH_LOG"
|
||||
fi
|
||||
|
|
@ -554,11 +448,11 @@ if [ -z "$MINIDUMP_NAME" ]; then
|
|||
fi
|
||||
|
||||
dump "Extracting minidump: $MINIDUMP_NAME"
|
||||
run "$ADB" pull "$DEVICE_TMP/$MINIDUMP_NAME" .
|
||||
adb_pull "$DEVICE_TMP/$MINIDUMP_NAME" .
|
||||
fail_panic "Can't extract minidump!"
|
||||
|
||||
dump "Parsing test program symbols"
|
||||
if [ "$VERBOSE" -ge 1 ]; then
|
||||
if verbosity_is_higher_than 1; then
|
||||
log "COMMAND: $TMPBIN/dump_syms \
|
||||
$PROJECT_DIR/obj/local/$ABI/$TESTAPP >$TESTAPP.sym"
|
||||
fi
|
||||
|
|
@ -586,7 +480,7 @@ fail_panic "minidump_stackwalk doesn't work!"
|
|||
|
||||
dump "Checking stack trace content"
|
||||
|
||||
if [ "$VERBOSE" -ge 1 ]; then
|
||||
if verbosity_is_higher_than 1; then
|
||||
cat "$BUILD_LOG"
|
||||
fi
|
||||
|
||||
|
|
@ -622,7 +516,7 @@ fi
|
|||
LOCATIONS=$(awk '$2 ~ "^test_google_breakpad!.*" { print $3; }' "$BUILD_LOG")
|
||||
|
||||
if [ -z "$LOCATIONS" ]; then
|
||||
if [ "$VERBOSE" -lt 1 ]; then
|
||||
if verbosity_is_lower_than 1; then
|
||||
cat "$BUILD_LOG"
|
||||
fi
|
||||
panic "No source location found in stack trace!"
|
||||
|
|
@ -646,8 +540,8 @@ if [ "$BAD_LOCATIONS" ]; then
|
|||
dump "ERROR: Generated stack trace doesn't contain valid source locations:"
|
||||
cat "$BUILD_LOG"
|
||||
echo "Bad locations are: $BAD_LOCATIONS"
|
||||
clean_exit 1
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "All clear! Congratulations."
|
||||
clean_exit 0
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue