• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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