| #!/bin/bash |
| # |
| # this script is used to rebuild all QEMU binaries for the host |
| # platforms. |
| # |
| # assume that the device tree is in TOP |
| # |
| |
| set -e |
| export LANG=C |
| export LC_ALL=C |
| |
| PROGDIR=$(dirname "$0") |
| VERBOSE=1 |
| |
| BUILD_QEMU_ANDROID= |
| MINGW= |
| NO_TESTS= |
| OUT_DIR=objs |
| |
| for OPT; do |
| case $OPT in |
| --build-qemu-android) |
| BUILD_QEMU_ANDROID=true |
| ;; |
| --mingw) |
| MINGW=true |
| ;; |
| --verbose) |
| VERBOSE=$(( $VERBOSE + 1 )) |
| ;; |
| --verbosity=*) |
| VERBOSE=${OPT##--verbosity=} |
| ;; |
| --no-tests) |
| NO_TESTS=true |
| ;; |
| --out-dir=*) |
| OUT_DIR=${OPT##--out-dir=} |
| ;; |
| --help|-?) |
| VERBOSE=2 |
| ;; |
| esac |
| done |
| |
| panic () { |
| echo "ERROR: $@" |
| exit 1 |
| } |
| |
| run () { |
| if [ "$VERBOSE" -gt 1 ]; then |
| "$@" |
| else |
| "$@" >/dev/null 2>&1 |
| fi |
| } |
| |
| HOST_OS=$(uname -s) |
| case $HOST_OS in |
| Linux) |
| HOST_NUM_CPUS=`cat /proc/cpuinfo | grep processor | wc -l` |
| ;; |
| Darwin|FreeBSD) |
| HOST_NUM_CPUS=`sysctl -n hw.ncpu` |
| ;; |
| CYGWIN*|*_NT-*) |
| HOST_NUM_CPUS=$NUMBER_OF_PROCESSORS |
| ;; |
| *) # let's play safe here |
| HOST_NUM_CPUS=1 |
| esac |
| |
| case $HOST_OS in |
| Linux) |
| HOST_SYSTEM=linux |
| ;; |
| Darwin) |
| HOST_SYSTEM=darwin |
| ;; |
| FreeBSD) |
| HOST_SYSTEM=freebsd |
| ;; |
| CYGWIN*|*_NT-*) |
| HOST_SYSTEM=windows |
| ;; |
| *) |
| panic "Host system is not supported: $HOST_OS" |
| esac |
| |
| # Return the type of a given file, using the /usr/bin/file command. |
| # $1: executable path. |
| # Out: file type string, or empty if the path is wrong. |
| get_file_type () { |
| /usr/bin/file "$1" 2>/dev/null |
| } |
| |
| # Return true iff the file type string |$1| contains the expected |
| # substring |$2|. |
| # $1: executable file type |
| # $2: expected file type substring |
| check_file_type_substring () { |
| printf "%s\n" "$1" | grep -q -E -e "$2" |
| } |
| |
| # Define EXPECTED_32BIT_FILE_TYPE and EXPECTED_64BIT_FILE_TYPE depending |
| # on the current target platform. Then EXPECTED_EMULATOR_BITNESS and |
| # EXPECTED_EMULATOR_FILE_TYPE accordingly. |
| if [ "$MINGW" ]; then |
| EXPECTED_32BIT_FILE_TYPE="PE32 executable \(console\) Intel 80386" |
| EXPECTED_64BIT_FILE_TYPE="PE32\+ executable \(console\) x86-64" |
| EXPECTED_EMULATOR_BITNESS=32 |
| EXPECTED_EMULATOR_FILE_TYPE=$EXPECTED_32BIT_FILE_TYPE |
| TARGET_OS=windows |
| elif [ "$HOST_OS" = "Darwin" ]; then |
| EXPECTED_32BIT_FILE_TYPE="Mach-O executable i386" |
| EXPECTED_64BIT_FILE_TYPE="Mach-O 64-bit executable x86_64" |
| EXPECTED_EMULATOR_BITNESS=64 |
| EXPECTED_EMULATOR_FILE_TYPE=$EXPECTED_64BIT_FILE_TYPE |
| TARGET_OS=darwin |
| else |
| EXPECTED_32BIT_FILE_TYPE="ELF 32-bit LSB +executable, Intel 80386" |
| EXPECTED_64BIT_FILE_TYPE="ELF 32-bit LSB +executable, x86-64" |
| EXPECTED_EMULATOR_BITNESS=32 |
| EXPECTED_EMULATOR_FILE_TYPE=$EXPECTED_32BIT_FILE_TYPE |
| TARGET_OS=linux |
| fi |
| |
| # Build the binaries from sources. |
| cd "$PROGDIR" |
| rm -rf objs |
| echo "Configuring build." |
| export IN_ANDROID_REBUILD_SH=1 |
| run ./android-configure.sh --out-dir=$OUT_DIR "$@" || |
| panic "Configuration error, please run ./android-configure.sh to see why." |
| |
| echo "Building sources." |
| run make -j$HOST_NUM_CPUS OBJS_DIR="$OUT_DIR" || |
| panic "Could not build sources, please run 'make' to see why." |
| |
| if [ "$BUILD_QEMU_ANDROID" ]; then |
| # Rebuild qemu-android binaries. |
| echo "Building qemu-android binaries." |
| unset ANDROID_EMULATOR_DARWIN_SSH && |
| $PROGDIR/android/scripts/build-qemu-android.sh \ |
| --verbosity=$VERBOSE \ |
| --host=$HOST_SYSTEM-x86_64 \ |
| --force |
| fi |
| |
| # Copy qemu-android binaries, if any. |
| PREBUILTS_DIR=$ANDROID_EMULATOR_PREBUILTS_DIR |
| if [ -z "$PREBUILTS_DIR" ]; then |
| PREBUILTS_DIR=$PROGDIR/../../prebuilts/android-emulator-build |
| fi |
| QEMU_ANDROID_HOSTS= |
| QEMU_ANDROID_BINARIES= |
| if [ -d "$PREBUILTS_DIR/qemu-android" ]; then |
| HOST_PREFIX=$TARGET_OS |
| if [ "$HOST_PREFIX" ]; then |
| QEMU_ANDROID_BINARIES=$(cd "$PREBUILTS_DIR"/qemu-android && ls $HOST_PREFIX-*/qemu-system-* 2>/dev/null || true) |
| fi |
| fi |
| if [ -z "$QEMU_ANDROID_BINARIES" ]; then |
| echo "WARNING: Missing qemu-android prebuilts. Please run rebuild-qemu-android.sh!" |
| else |
| echo "Copying prebuilt $HOST_PREFIX qemu-android binaries to $OUT_DIR/qemu/" |
| for QEMU_ANDROID_BINARY in $QEMU_ANDROID_BINARIES; do |
| run mkdir -p "$OUT_DIR/qemu/$(dirname "$QEMU_ANDROID_BINARY")" && |
| run cp "$PREBUILTS_DIR"/qemu-android/$QEMU_ANDROID_BINARY \ |
| $OUT_DIR/qemu/$QEMU_ANDROID_BINARY || |
| panic "Could not copy $HOST_PREFIX/$QEMU_ANDROID_BINARY !?" |
| done |
| fi |
| |
| if [ -d "$PREBUILTS_DIR/mesa" ]; then |
| MESA_HOST=$HOST_SYSTEM |
| if [ "$MINGW" ]; then |
| MESA_HOST=windows |
| fi |
| case $MESA_HOST in |
| windows) |
| MESA_LIBNAME=opengl32.dll |
| OSMESA_LIBNAME=osmesa.dll |
| ;; |
| linux) |
| MESA_LIBNAME=libGL.so |
| OSMESA_LIBNAME=libosmesa.so |
| ;; |
| *) |
| MESA_LIBNAME= |
| OSMESA_LIBNAME= |
| esac |
| for LIBNAME in $MESA_LIBNAME $OSMESA_LIBNAME; do |
| for MESA_ARCH in x86 x86_64; do |
| if [ "$MESA_ARCH" = "x86" ]; then |
| MESA_LIBDIR=lib |
| else |
| MESA_LIBDIR=lib64 |
| fi |
| MESA_LIBRARY=$(ls "$PREBUILTS_DIR/mesa/$MESA_HOST-$MESA_ARCH/lib/$LIBNAME" 2>/dev/null || true) |
| if [ "$MESA_LIBRARY" ]; then |
| MESA_DSTDIR="$OUT_DIR/$MESA_LIBDIR/gles_mesa" |
| MESA_DSTLIB="$LIBNAME" |
| if [ "$LIBNAME" = "opengl32.dll" ]; then |
| MESA_DSTLIB="mesa_opengl32.dll" |
| fi |
| echo "Copying $MESA_HOST-$MESA_ARCH $LIBNAME library to $MESA_DSTDIR" |
| run mkdir -p "$MESA_DSTDIR" && |
| run cp -f "$MESA_LIBRARY" "$MESA_DSTDIR/$MESA_DSTLIB" |
| if [ "$MESA_HOST" = "linux" -a "$LIBNAME" = "libGL.so" ]; then |
| # Special handling for Linux, this is needed because SDL |
| # will actually try to load libGL.so.1 before GPU emulation |
| # is initialized. This is actually a link to the system's |
| # libGL.so, and will thus prevent the Mesa version from |
| # loading. By creating the symlink, Mesa will also be used |
| # by SDL. |
| run ln -sf libGL.so "$MESA_DSTDIR/libGL.so.1" |
| fi |
| fi |
| done |
| done |
| fi |
| |
| # Copy Qt shared libraries, if needed. |
| EMULATOR_USE_QT=$(awk '$1 == "EMULATOR_USE_QT" { print $3; }' \ |
| $OUT_DIR/config.make 2>/dev/null) |
| if [ "$EMULATOR_USE_QT" = "true" ]; then |
| QT_PREBUILTS_DIR=$(awk '$1 == "QT_PREBUILTS_DIR" { print $3; }' \ |
| $OUT_DIR/config.make 2>/dev/null) |
| if [ ! -d "$QT_PREBUILTS_DIR" ]; then |
| panic "Missing Qt prebuilts directory: $QT_PREBUILTS_DIR" |
| fi |
| echo "Copying Qt prebuilt libraries from $QT_PREBUILTS_DIR" |
| for QT_ARCH in x86 x86_64; do |
| QT_SRCDIR=$QT_PREBUILTS_DIR/$TARGET_OS-$QT_ARCH |
| case $QT_ARCH in |
| x86) QT_DSTDIR=$OUT_DIR/lib/qt;; |
| x86_64) QT_DSTDIR=$OUT_DIR/lib64/qt;; |
| *) panic "Invalid Qt host architecture: $QT_ARCH";; |
| esac |
| run mkdir -p "$QT_DSTDIR" || panic "Could not create Qt library sub-directory!" |
| if [ ! -d "$QT_SRCDIR" ]; then |
| continue |
| fi |
| case $TARGET_OS in |
| windows) QT_DLL_FILTER="*.dll";; |
| darwin) QT_DLL_FILTER="*.dylib";; |
| *) QT_DLL_FILTER="*.so*";; |
| esac |
| QT_LIBS=$(cd "$QT_SRCDIR" && find . -name "$QT_DLL_FILTER" 2>/dev/null) |
| #echo "QT_SRCDIR [$QT_SRCDIR] QT_LIBS [$QT_LIBS]" |
| if [ -z "$QT_LIBS" ]; then |
| panic "Cannot find Qt prebuilt libraries!?" |
| fi |
| for QT_LIB in $QT_LIBS; do |
| run cp -a "$QT_SRCDIR/$QT_LIB" "$QT_DSTDIR"/$(basename "$QT_LIB") || |
| panic "Could not copy $QT_LIB" |
| done |
| done |
| fi |
| |
| # Copy e2fsprogs binaries. |
| if true; then |
| E2FSPROGS_DIR=$PREBUILTS_DIR/e2fsprogs |
| if [ ! -d "$E2FSPROGS_DIR" ]; then |
| echo "Warning: Missing e2fsprogs prebuilts directory: $E2FSPROGS_DIR" |
| else |
| # NOTE: Bad indentation here is intentional, the echo/else above will |
| # be replaced by a panic/fi in a future patch. |
| echo "Copying e2fsprogs binaries." |
| for E2FS_ARCH in x86 x86_64; do |
| # NOTE: in windows only 32-bit binaries are available, so we'll copy the |
| # 32-bit executables to the bin64/ directory to cover all our bases |
| case $TARGET_OS in |
| windows) E2FS_SRCDIR=$E2FSPROGS_DIR/$TARGET_OS-x86;; |
| *) E2FS_SRCDIR=$E2FSPROGS_DIR/$TARGET_OS-$E2FS_ARCH;; |
| esac |
| |
| case $E2FS_ARCH in |
| x86) E2FS_DSTDIR=$OUT_DIR/bin;; |
| x86_64) E2FS_DSTDIR=$OUT_DIR/bin64;; |
| *) panic "Invalid e2fsprogs host architecture: $E2FS_ARCH" |
| esac |
| run mkdir -p "$E2FS_DSTDIR" || panic "Could not create sub-directory: $E2FS_DSTDIR" |
| if [ ! -d "$E2FS_SRCDIR" ]; then |
| continue |
| fi |
| run cp -a "$E2FS_SRCDIR"/sbin/* "$E2FS_DSTDIR" || "Could not copy e2fsprogs binaries!" |
| done |
| fi # Again, intentional, will disappear in a future patch. |
| fi |
| |
| RUN_32BIT_TESTS= |
| RUN_64BIT_TESTS=true |
| RUN_EMUGEN_TESTS=true |
| RUN_GEN_ENTRIES_TESTS=true |
| |
| TEST_SHELL= |
| EXE_SUFFIX= |
| if [ "$MINGW" ]; then |
| TEST_SHELL=wine |
| EXE_SUFFIX=.exe |
| |
| # Check for Wine on this machine. |
| WINE_CMD=$(which $TEST_SHELL 2>/dev/null || true) |
| if [ -z "$NO_TESTS" -a -z "$WINE_CMD" ]; then |
| echo "WARNING: Wine is not installed on this machine!! Unit tests will be ignored!!" |
| NO_TESTS=true |
| fi |
| |
| RUN_32BIT_TESTS=true |
| fi |
| |
| if [ "$HOST_OS" = "Linux" ]; then |
| # Linux 32-bit binaries are deprecated but not removed yet! |
| RUN_32BIT_TESTS=true |
| fi |
| |
| |
| if [ -z "$NO_TESTS" ]; then |
| FAILURES="" |
| |
| echo "Checking for 'emulator' launcher program." |
| EMULATOR=$OUT_DIR/emulator$EXE_SUFFIX |
| if [ ! -f "$EMULATOR" ]; then |
| echo " - FAIL: $EMULATOR is missing!" |
| FAILURES="$FAILURES emulator" |
| fi |
| |
| echo "Checking that 'emulator' is a $EXPECTED_EMULATOR_BITNESS-bit program." |
| EMULATOR_FILE_TYPE=$(get_file_type "$EMULATOR") |
| if ! check_file_type_substring "$EMULATOR_FILE_TYPE" "$EXPECTED_EMULATOR_FILE_TYPE"; then |
| echo " - FAIL: $EMULATOR is not a 32-bit executable!" |
| echo " File type: $EMULATOR_FILE_TYPE" |
| echo " Expected : $EXPECTED_EMULATOR_FILE_TYPE" |
| FAILURES="$FAILURES emulator-bitness-check" |
| fi |
| |
| if [ "$RUN_32BIT_TESTS" ]; then |
| echo "Running 32-bit unit test suite." |
| for UNIT_TEST in emulator_unittests emugl_common_host_unittests android_skin_unittests; do |
| echo " - $UNIT_TEST" |
| run $TEST_SHELL $OUT_DIR/$UNIT_TEST$EXE_SUFFIX || FAILURES="$FAILURES $UNIT_TEST" |
| done |
| fi |
| |
| if [ "$RUN_64BIT_TESTS" ]; then |
| echo "Running 64-bit unit test suite." |
| for UNIT_TEST in emulator64_unittests emugl64_common_host_unittests android64_skin_unittests; do |
| echo " - $UNIT_TEST" |
| run $TEST_SHELL $OUT_DIR/$UNIT_TEST$EXE_SUFFIX || FAILURES="$FAILURES $UNIT_TEST" |
| done |
| fi |
| |
| if [ "$RUN_EMUGEN_TESTS" ]; then |
| EMUGEN_UNITTESTS=$OUT_DIR/emugen_unittests |
| if [ ! -f "$EMUGEN_UNITTESTS" ]; then |
| echo "FAIL: Missing binary: $EMUGEN_UNITTESTS" |
| FAILURES="$FAILURES emugen_unittests-binary" |
| else |
| echo "Running emugen_unittests." |
| run $EMUGEN_UNITTESTS || |
| FAILURES="$FAILURES emugen_unittests" |
| fi |
| echo "Running emugen regression test suite." |
| # Note that the binary is always built for the 'build' machine type, |
| # I.e. if --mingw is used, it's still a Linux executable. |
| EMUGEN=$OUT_DIR/emugen |
| if [ ! -f "$EMUGEN" ]; then |
| echo "FAIL: Missing 'emugen' binary: $EMUGEN" |
| FAILURES="$FAILURES emugen-binary" |
| else |
| # The first case is for a remote build with package-release.sh |
| TEST_SCRIPT=$PROGDIR/../opengl/host/tools/emugen/tests/run-tests.sh |
| if [ ! -f "$TEST_SCRIPT" ]; then |
| # This is the usual location. |
| TEST_SCRIPT=$PROGDIR/distrib/android-emugl/host/tools/emugen/tests/run-tests.sh |
| fi |
| if [ ! -f "$TEST_SCRIPT" ]; then |
| echo " FAIL: Missing script: $TEST_SCRIPT" |
| FAILURES="$FAILURES emugen-test-script" |
| else |
| run $TEST_SCRIPT --emugen=$EMUGEN || |
| FAILURES="$FAILURES emugen-test-suite" |
| fi |
| fi |
| fi |
| |
| # Check the gen-entries.py script. |
| if [ "$RUN_GEN_ENTRIES_TESTS" ]; then |
| echo "Running gen-entries.py test suite." |
| run android/scripts/tests/gen-entries/run-tests.sh || |
| FAILURES="$FAILURES gen-entries_tests" |
| fi |
| |
| # Check that the windows executables all have icons. |
| # First need to locate the windres tool. |
| if [ "$MINGW" ]; then |
| echo "Checking windows executables icons." |
| if [ ! -f "$OUT_DIR/config.make" ]; then |
| echo "FAIL: Could not find \$OUT_DIR/config.make !?" |
| FAILURES="$FAILURES out-dir-config-make" |
| else |
| WINDRES=$(awk '/^HOST_WINDRES:=/ { print $2; } $1 == "HOST_WINDRES" { print $3; }' $OUT_DIR/config.make) || |
| if true; then |
| echo "FAIL: Could not find host 'windres' program" |
| FAILURES="$FAILURES host-windres" |
| fi |
| EXECUTABLES="emulator.exe emulator-arm.exe emulator-x86.exe emulator-mips.exe" |
| EXECUTABLES="$EXECUTABLES emulator64-arm.exe emulator64-x86.exe emulator64-mips.exe" |
| EXECUTABLES="$EXECUTABLES emulator-ranchu-arm64.exe emulator-ranchu-mips64.exe" |
| EXECUTABLES="$EXECUTABLES emulator64-ranchu-arm64.exe emulator64-ranchu-mips64.exe" |
| EXPECTED_ICONS=14 |
| for EXEC in $EXECUTABLES; do |
| if [ ! -f "$OUT_DIR"/$EXEC ]; then |
| echo "FAIL: Missing windows executable: $EXEC" |
| FAILURES="$FAILURES windows-$EXEC" |
| else |
| NUM_ICONS=$($WINDRES --input-format=coff --output-format=rc $OUT_DIR/$EXEC | grep RT_ICON | wc -l) |
| if [ "$NUM_ICONS" != "$EXPECTED_ICONS" ]; then |
| echo "FAIL: Invalid icon count in $EXEC ($NUM_ICONS, expected $EXPECTED_ICONS)" |
| FAILURES="$FAILURES windows-$EXEC-icons" |
| fi |
| fi |
| done |
| fi |
| fi |
| if [ "$FAILURES" ]; then |
| panic "Unit test failures: $FAILURES" |
| fi |
| else |
| echo "Ignoring unit tests suite." |
| fi |
| |
| echo "Done. !!" |