1# 2# Copyright (C) 2012 The Android Open Source Project 3# 4# Licensed under the Apache License, Version 2.0 (the "License"); 5# you may not use this file except in compliance with the License. 6# You may obtain a copy of the License at 7# 8# http://www.apache.org/licenses/LICENSE-2.0 9# 10# Unless required by applicable law or agreed to in writing, software 11# distributed under the License is distributed on an "AS IS" BASIS, 12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13# See the License for the specific language governing permissions and 14# limitations under the License. 15# 16 17# This script is used to run a series of tests on a given standalone 18# toolchain. You need to define the following variables before calling it: 19# 20# PREFIX Full binary prefix to the toolchain binaries, 21# e.g. '/path/to/toolchain/bin/arm-linux-androideabi-' 22# This script will use ${PREFIX}gcc to invoke the compiler, 23# ${PREFIX}ar for the archiver, etc... 24# 25# CFLAGS Compiler flags for C programs. 26# CXXFLAGS Compiler flags for C++ programs. 27# LDFLAGS Linker flags (passed to ${PREFIX}gcc, not ${PREFIX}ld) 28# 29 30PROGNAME=$(basename "$0") 31PROGDIR=$(dirname "$0") 32NDK_ROOT=$(cd "$PROGDIR/../.." && pwd) 33. $NDK_ROOT/build/core/ndk-common.sh 34 35panic () { 36 echo "ERROR: $@" >&2; exit 1 37} 38 39fail_panic () { 40 if [ $? != 0 ]; then panic "$@"; fi 41} 42 43 44# Command-line processing 45# 46# Note: try to keep in alphabetical order, same for the --option cases below. 47# 48ABI= 49HELP= 50LIST_TESTS= 51NO_SYSROOT= 52SYSROOT= 53TEST_SUBDIRS= 54VERBOSE=1 55 56# Parse options 57for opt; do 58 optarg=`expr "x$opt" : 'x[^=]*=\(.*\)'` 59 case $opt in 60 --abi=*) 61 ABI=$optarg 62 ;; 63 --help|-h|-?) 64 HELP=true 65 ;; 66 --list) 67 LIST_TESTS=true 68 ;; 69 --no-sysroot) 70 NO_SYSROOT=true 71 ;; 72 --prefix=*) 73 PREFIX=$optarg 74 ;; 75 --quiet|-q) 76 VERBOSE=$(( $VERBOSE - 1 )) 77 ;; 78 --sysroot=*) 79 SYSROOT=$optarg 80 ;; 81 --verbose|-v) 82 VERBOSE=$(( $VERBOSE + 1 )) 83 ;; 84 -*) 85 panic "Unknown option '$opt'. See --help for list of valid ones." 86 ;; 87 *) 88 TEST_SUBDIRS=$TEST_SUBDIRS" "$opt 89 ;; 90 esac 91done 92 93if [ "$HELP" ]; then 94 echo "Usage: $PROGNAME [options] [testname+]" 95 echo "" 96 echo "Run a set of unit tests to check that a given Android NDK toolchain works" 97 echo "as expected. Useful to catch regressions when generating new toolchain" 98 echo "binaries." 99 echo "" 100 echo "You can pass the full path to the toolchain either with the --prefix" 101 echo "option, or by defining PREFIX in your environment before calling this script." 102 echo "For example:" 103 echo "" 104 echo " $PROGNAME --prefix=\$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86/bin/arm-linux-androideabi" 105 echo "" 106 echo "The prefix can also be the full-path to the \$TARGET-gcc or \$TARGET-g++ program " 107 echo "" 108 echo "The script will automatically use an NDK-provided sysroot, but you can specify an" 109 echo "alternate one with the --sysroot=<path> option. You can also use --no-sysroot if" 110 echo "the toolchain already provides its own sysroot (e.g. if it is a standalone toolchain" 111 echo "generated with make-standalone-toolchain.sh)." 112 echo "" 113 echo "The target ABI is normally auto-detected from the toolchain, but you can specify an" 114 echo "alternative one with the --abi=<name> option. This is only useful on ARM, where the" 115 echo "default ABI is 'armeabi' targetting the ARMv5TE instruction set. If you want to check" 116 echo "the generation of ARMv7-A machine code, use the following:" 117 echo "" 118 echo " --abi=armeabi-v7a" 119 echo "" 120 echo "When called without any arguments, the script will run all known toolchain tests." 121 echo "You can restrict the list of tests by passing them on the command-line. Use --list" 122 echo "to display the list of all tests that are relevant for your current ABI." 123 echo "" 124 echo "More information about each test can be displayed by using --verbose." 125 echo "" 126 echo "Valid options:" 127 echo "" 128 echo " --help|-h|-? Print this message." 129 echo " --verbose|-v Increase verbosity." 130 echo " --quiet|-q Decrease verbosity." 131 echo " --list List all available tests for current ABI." 132 echo " --prefix=<prefix> Specify full toolchain binary prefix." 133 echo " --sysroot=<path> Specify alternate sysroot." 134 echo " --no-sysroot Do not use a sysroot." 135 echo " --abi=<name> Specify target ABI name." 136 echo "" 137 exit 0 138fi 139 140TMPDIR=/tmp/ndk-$USER/tests/standalone 141mkdir -p "$TMPDIR" && rm -rf "$TMPDIR/*" 142 143BUILD_DIR=$TMPDIR/build 144mkdir -p "$BUILD_DIR" 145 146LOGFILE=$TMPDIR/log.txt 147echo -n "" > $LOGFILE 148 149if [ $VERBOSE -ge 3 ]; then 150 run () { 151 echo "# COMMAND: $@" 152 "$@" 153 } 154elif [ $VERBOSE -ge 2 ]; then 155 run () { 156 echo "# COMMAND: $@" >> $LOGFILE 157 "$@" 158 } 159else 160 run () { 161 echo "# COMMAND[$@]" >> $LOGFILE 162 "$@" >> $LOGFILE 2>&1 163 } 164fi 165 166if [ $VERBOSE -ge 2 ]; then 167 run_script () { 168 $SHELL "$@" 169 } 170else 171 run_script () { 172 $SHELL "$@" >> $LOGFILE 2>&1 173 } 174fi 175 176if [ $VERBOSE -ge 1 ]; then 177 dump () { 178 echo "$@" 179 } 180else 181 dump () { 182 : # nothing 183 } 184fi 185 186 187# Probe a given sub-directory and see if it contains valid test files. 188# $1: sub-directory path 189# Return: 0 on success, 1 otherwise 190# 191# This can also sets the following global variables: 192# TEST_TYPE 193# SCRIPT 194# SOURCES 195# 196probe_test_subdir () 197{ 198 local DIR="$1" 199 200 TEST_TYPE= 201 SCRIPT= 202 SOURCES= 203 204 if [ -f "$DIR/run.sh" ]; then 205 TEST_TYPE=script 206 SCRIPT=run.sh 207 208 elif [ -f "$DIR/run-$ABI.sh" ]; then 209 TEST_TYPE=script 210 SCRIPT=run-$ABI.sh 211 212 elif [ -f "$DIR/main.c" ]; then 213 TEST_TYPE=c_executable 214 SOURCES=main.c 215 216 elif [ -f "$DIR/main.cpp" ]; then 217 TEST_TYPE=cxx_executable 218 SOURCES=main.cpp 219 220 else 221 return 1 222 fi 223 224 return 0 225} 226 227 228# Handle --list option now, then exit 229if [ -n "$LIST_TESTS" ]; then 230 echo "List of available toolchain tests:" 231 if [ -z "$ABI" ]; then 232 ABI=armeabi 233 fi 234 for TEST_SUBDIR in $(cd $PROGDIR && ls -d *); do 235 SUBDIR=$PROGDIR/$TEST_SUBDIR 236 if probe_test_subdir "$SUBDIR"; then 237 echo " $TEST_SUBDIR" 238 fi 239 done 240 exit 0 241fi 242 243if [ -z "$PREFIX" ]; then 244 panic "Please define PREFIX in your environment, or use --prefix=<prefix> option." 245fi 246 247# Remove -gcc or -g++ from prefix if any 248PREFIX=${PREFIX%-gcc} 249PREFIX=${PREFIX%-g++} 250 251# Add a trailing dash to the prefix, if there isn't any 252PREFIX=${PREFIX%-}- 253 254GCC=${PREFIX}gcc 255if [ ! -f "$GCC" ]; then 256 panic "Missing compiler, please fix your prefix definition: $GCC" 257fi 258 259GCC=$(which $GCC 2>/dev/null) 260if [ -z "$GCC" -o ! -f "$GCC" ]; then 261 panic "Bad compiler path: ${PREFIX}gcc" 262fi 263 264if [ -z "$ABI" ]; then 265 # Auto-detect target CPU architecture 266 GCC_TARGET=$($GCC -v 2>&1 | tr ' ' '\n' | grep -e --target=) 267 GCC_TARGET=${GCC_TARGET##--target=} 268 269 dump "Auto-detected GCC target configuration: $GCC_TARGET" 270 case $GCC_TARGET in 271 arm-linux-androideabi) 272 ABI=armeabi 273 ARCH=arm 274 ;; 275 i686-linux-android) 276 ABI=x86 277 ARCH=x86 278 ;; 279 i686-android-linux) # This one is deprecated, remove later. 280 ABI=x86 281 ARCH=x86 282 ;; 283 mipsel-linux-android) 284 ABI=mips 285 ARCH=mips 286 ;; 287 *) 288 panic "Unknown GCC target architecture '$GCC_TARGET', please use --abi=<name> to manually specify ABI." 289 esac 290 dump "Auto-config: --abi=$ABI" 291fi 292 293GCCDIR=$(dirname "$GCC") 294GCCBASE=$(basename "$GCC") 295 296GCCDIR=$(cd "$GCCDIR" && pwd) 297GCC=$GCCDIR/$GCCBASE 298 299PREFIX=${GCC%%gcc} 300#echo "PREFIX=$PREFIX" 301 302COMMON_FLAGS= 303 304# Ensure ABI_<abi> is defined as a compiler macro when building test programs. 305# as a compiler macro when building all test programs. 306ABI_MACRO=ABI_$(echo "$ABI" | tr '-' '_') 307COMMON_FLAGS=$COMMON_FLAGS" -D$ABI_MACRO=1" 308 309if [ -n "$NO_SYSROOT" ]; then 310 SYSROOT= 311elif [ -n "$SYSROOT" ]; then 312 if [ ! -d "$SYSROOT" ]; then 313 panic "Sysroot directory does not exist: $SYSROOT" 314 fi 315 # Sysroot must be absolute path 316 SYSROOT=$(cd $SYSROOT && pwd) 317 COMMON_FLAGS=$COMMON_FLAGS" --sysroot=$SYSROOT" 318else 319 # Auto-detect sysroot 320 SYSROOT=$NDK_ROOT/platforms/android-9/arch-$ARCH 321 if [ ! -d "$SYSROOT" ]; then 322 panic "Can't find sysroot file, use --sysroot to point to valid one: $SYSROOT" 323 fi 324 if [ ! -f "$SYSROOT/usr/lib/libc.so" ]; then 325 panic "Incomplete sysroot, use --sysroot to point to valid one: $SYSROOT" 326 fi 327 if [ $HOST_OS = cygwin ]; then 328 SYSROOT=`cygpath -m $SYSROOT` 329 fi 330 dump "Auto-config: --sysroot=$SYSROOT" 331 COMMON_FLAGS=$COMMON_FLAGS" --sysroot=$SYSROOT" 332fi 333 334if [ -z "$CXXFLAGS" ]; then 335 CXXFLAGS=$CFLAGS 336fi 337 338# NOTE: We need to add -fno-exceptions, otherwise some toolchains compile 339# with exception support by default, and the test programs fail to 340# link due to an undefined reference to __gxx_personality_v0. 341# 342# This symbol is normally part of libsupc++ which is not available 343# if you don't have the GNU libstdc++ installed into your toolchain 344# directory. 345# 346# Affects the x86 and mips toolchains, but not the ARM one. 347# Not sure if we want exceptions enabled by default or not. 348# 349CXXFLAGS=$CXXFLAGS" -fno-exceptions" 350 351CFLAGS=$COMMON_FLAGS" "$CFLAGS 352CXXFLAGS=$COMMON_FLAGS" "$CXXFLAGS 353 354if [ -z "$TEST_SUBDIRS" ]; then 355 TEST_SUBDIRS=$(cd $PROGDIR && ls -d *) 356fi 357 358COUNT=0 359FAILURES=0 360for TEST_SUBDIR in $TEST_SUBDIRS; do 361 SUBDIR=$PROGDIR/$TEST_SUBDIR 362 363 if ! probe_test_subdir "$SUBDIR"; then 364 continue 365 fi 366 367 rm -rf "$BUILD_DIR"/* && 368 cp -RL "$SUBDIR"/* "$BUILD_DIR/" 369 fail_panic "Could not copy test files to $BUILD_DIR !?" 370 371 dump_n "Running $TEST_SUBDIR test... " 372 373 case $TEST_TYPE in 374 script) 375 ( 376 export PREFIX CFLAGS CXXFLAGS LDFLAGS VERBOSE ABI 377 run cd "$BUILD_DIR" && run_script $SCRIPT 378 ) 379 RET=$? 380 ;; 381 382 c_executable) 383 ( 384 run cd "$BUILD_DIR" && run ${PREFIX}gcc $LDFLAGS $CFLAGS -o /dev/null $SOURCES 385 ) 386 RET=$? 387 ;; 388 389 cxx_executable) 390 ( 391 run cd "$BUILD_DIR" && run ${PREFIX}g++ $LDFLAGS $CXXFLAGS -o /dev/null $SOURCES 392 ) 393 RET=$? 394 ;; 395 esac 396 397 if [ "$RET" != 0 ]; then 398 dump "KO" 399 FAILURES=$(( $FAILURES + 1 )) 400 else 401 dump "ok" 402 fi 403 COUNT=$(( $COUNT + 1 )) 404done 405 406if [ "$FAILURES" -eq 0 ]; then 407 dump "$COUNT/$COUNT tests passed. Success." 408 exit 0 409else 410 dump "$FAILURES tests failed out of $COUNT." 411 exit 1 412fi 413