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