Merge "Fix build-*llvm.sh to build either mclinker 2.4.0 or the coming 2.5.0"
diff --git a/build/tools/ndk-common.sh b/build/tools/ndk-common.sh
index da529b9..05115ac 100644
--- a/build/tools/ndk-common.sh
+++ b/build/tools/ndk-common.sh
@@ -794,7 +794,7 @@
     fi
     # Ensure symlinks are stored as is in zip files. for toolchains
     # this can save up to 7 MB in the size of the final archive
-    ZIPFLAGS="$ZIPFLAGS --symlinks"
+    #ZIPFLAGS="$ZIPFLAGS --symlinks"
     case "$ARCHIVE" in
         *.zip)
             (cd $SRCDIR && run zip $ZIPFLAGS "$ARCHIVE" $SRCFILES)
diff --git a/sources/cxx-stl/gabi++/src/cxxabi_defines.h b/sources/cxx-stl/gabi++/src/cxxabi_defines.h
index 623a14c..a48c7c0 100644
--- a/sources/cxx-stl/gabi++/src/cxxabi_defines.h
+++ b/sources/cxx-stl/gabi++/src/cxxabi_defines.h
@@ -26,7 +26,7 @@
 // SUCH DAMAGE.
 
 #ifndef _GABIXX_CXXABI_DEFINES_H
-#define _GABIXX_CXXABI_DEIFNES_H
+#define _GABIXX_CXXABI_DEFINES_H
 
 #include <cxxabi.h>
 #include <stdint.h>
diff --git a/tests/abcc/build-abcc.sh b/tests/abcc/build-abcc.sh
index bfddf53..4809833 100755
--- a/tests/abcc/build-abcc.sh
+++ b/tests/abcc/build-abcc.sh
@@ -77,6 +77,7 @@
 test "$VERBOSE" = "yes" && FLAGS=$FLAGS" --verbose"
 test "$VERBOSE2" = "yes" && FLAGS=$FLAGS" --verbose"
 FLAGS="$FLAGS -j$NUM_JOBS"
+test "$DEBUG" = "yes" && FLAGS=$FLAGS" --testing"
 
 #
 # First: Build toolchain assets
diff --git a/tests/abcc/jni/main.cpp b/tests/abcc/jni/main.cpp
index d7b2751..37b3afb 100644
--- a/tests/abcc/jni/main.cpp
+++ b/tests/abcc/jni/main.cpp
@@ -83,6 +83,8 @@
 const unsigned NUM_THREADS = 1;
 const char *lib_dir;
 const char *sysroot;
+bool for_testing;
+std::string complement_ldlibs;  // Used when for_testing == true
 
 // Use std::list to easily keep validity while erase
 typedef std::vector<std::string> LDFlagsTy;
@@ -326,6 +328,7 @@
   return handleTask(cmd, err_msg);
 }
 
+
 int getFilesFromDir(const char *dir, std::vector<std::string> &files) {
   files.clear();
   DIR *dp = opendir(dir);
@@ -348,6 +351,14 @@
     close(fd);
     swapEndian(buffer, 4);
     int magic = transferBytesToNum(buffer, 4);
+    if (for_testing && magic == 0xdec04342) {
+      if (filename == "libgnustl_shared.bc") {
+        complement_ldlibs = std::string(" ") + sysroot + "/usr/lib/libsupc++.a -lgnustl_shared -ldl";
+        LOGI("Manually add %s for testing, and ignore the file %s", complement_ldlibs.c_str(), full_path.c_str());
+        continue;
+      }
+    }
+
     if (magic != 0x0b17c0de) {
       LOGI("Found file %s magic: %x, but we need: %x (Ignored)", full_path.c_str(), magic, 0x0b17c0de);
       continue;
@@ -509,6 +520,8 @@
        i != e; ++i) {
     cmd += std::string(" ") + *i;
   }
+  if (for_testing)
+      cmd += complement_ldlibs;
   // TODO: If this module needs libfoo.so, but since libfoo.so is not a real bitcode under
   //       our trick, it won't be included at module.info. How did we workaround this?
   cmd += info.mLDLibsStr;
@@ -524,6 +537,11 @@
 
   std::string err_msg;
   int ret = handleTask(cmd, err_msg);
+  if (ret != 0 && for_testing) {
+    // Bail out if it uses gnustl_static but we don't know. Try to use -lgnustl_shared
+    cmd += std::string(" ") + sysroot + "/usr/lib/libsupc++.a -lgnustl_shared -ldl";
+    ret = handleTask(cmd, err_msg);
+  }
   if (ret != 0) {
     LOGE("Cannot link bitcode (%s): %s", info.mBitcode.c_str(), cmd.c_str());
     std::fstream fout;
@@ -654,26 +672,29 @@
 
 JNIEXPORT jint JNICALL
 Java_compiler_abcc_AbccService_genLibs(JNIEnv *env, jobject thiz,
-                                       jstring j_lib_dir, jstring j_sysroot) {
+                                       jstring j_lib_dir, jstring j_sysroot, jboolean j_for_testing) {
   lib_dir = env->GetStringUTFChars(j_lib_dir, 0);
   LOGI("Working directory: %s", lib_dir);
 
   sysroot = env->GetStringUTFChars(j_sysroot, 0);
   LOGI("Sysroot: %s", sysroot);
 
+  for_testing = (bool) j_for_testing;
+  LOGI("For testing: %d", for_testing);
+
   handleTask(std::string("rm -f ") + lib_dir + "/compile_error");
   genLibs(lib_dir, sysroot);
   handleTask(std::string("cd ") + lib_dir + " && ln -s " + sysroot + "/usr/lib/libgabi++_shared.so libgabi++_shared.so");
+  if (for_testing)
+    handleTask(std::string("cd ") + lib_dir + " && ln -s " + sysroot + "/usr/lib/libgnustl_shared.so libgnustl_shared.so");
   if (handleTask(std::string("ls ") + lib_dir + "/compile_error") != 0) {
     handleTask(std::string("echo 0 > ") + lib_dir + "/compile_result");
     handleTask(std::string("chmod 0644 ") + lib_dir + "/compile_result");
-    handleTask(std::string("rm -f ") + lib_dir + "/compile_result");
     return 0;
   } else {
     handleTask(std::string("echo 56 > ") + lib_dir + "/compile_result");
     handleTask(std::string("chmod 0644 ") + lib_dir + "/compile_result");
     handleTask(std::string("chmod 0644 ") + lib_dir + "/compile_error");
-    handleTask(std::string("rm -f ") + lib_dir + "/compile_result");
     return 56;
   }
 }
diff --git a/tests/abcc/src/compiler/abcc/AbccService.java b/tests/abcc/src/compiler/abcc/AbccService.java
index 59e8dd0..631a43f 100644
--- a/tests/abcc/src/compiler/abcc/AbccService.java
+++ b/tests/abcc/src/compiler/abcc/AbccService.java
@@ -7,6 +7,7 @@
 import android.content.pm.ApplicationInfo;
 import android.content.pm.PackageManager;
 import android.os.Binder;
+import android.os.Bundle;
 import android.os.IBinder;
 import android.os.Parcel;
 import android.os.ResultReceiver;
@@ -24,6 +25,7 @@
 
   String mWorkingDir = null;
   String mSysroot = null;
+  boolean mForTesting = false;
 
   // For onBind()
   private IBinder mBinder = new LocalBinder();
@@ -50,7 +52,7 @@
       }
 
       Log.i(TAG, "mWorkingDir for genLibs: " + mWorkingDir);
-      if (genLibs(mWorkingDir, mSysroot) != 0) {
+      if (genLibs(mWorkingDir, mSysroot, mForTesting) != 0) {
         synchronized (mStatusLock) {
           mCurrentStatus = AbccService.STATUS_ERROR;
           mStatusLock.notifyAll();
@@ -76,24 +78,22 @@
         throw new RemoteException("AbccLocalBinder pingBinder return false!");
       }
 
-      switch (code) {
-        // Use magic number instead of meaningful string since PackageManager is not integrated yet
-        // PackageManager.BITCODE_ACTION_START_COMPILE
-        case 10: {
-          String path = data.readString();
-          if (path == null)
-            Log.e(TAG, "onTransact but no working_dir provided!?");
-          else
-            mWorkingDir = path;
-          return compileForBinder();
-        }
-        // PackageManager.BITCODE_ACTION_QUERY_STATUS
-        case 11:
-          return queryStatusForBinder();
-        default:
-          Log.e(TAG, "Unreconizable onTransact code.");
-          return false;
+      // The code is not important now. This is just a communication way
+      // and what we really need is the information from @data
+      Bundle real_data = data.readBundle();
+      if (real_data == null) {
+        Log.e(TAG, "Should get some information from the Parcel.");
+        return false;
       }
+      String path = real_data.getString("working_dir");
+      if (path == null ) {
+        Log.e(TAG, "onTransact but no working_dir provided?");
+        return false;
+      }
+
+      mWorkingDir = path;
+      compileForBinder();
+      return queryStatusForBinder();
     }
   }
 
@@ -227,6 +227,7 @@
 
     extractIntentInfo(intent);
     installToolchain();
+    mForTesting = true;
     new WorkingThread().start();
   }
 
@@ -262,7 +263,7 @@
 
   // If succeess, it will be 0 in file working_dir/compile_result.
   // Otherwise, there will be error message in file working_dir/compile_error.
-  private native int genLibs(String working_dir, String sysroot);
+  private native int genLibs(String working_dir, String sysroot, boolean for_test);
 
   static {
     // Distinguish whether this is a system prebuilt apk or an updated apk
diff --git a/tests/build/import-install/build.sh b/tests/build/import-install/build.sh
index 6c111b7..7d8036e 100755
--- a/tests/build/import-install/build.sh
+++ b/tests/build/import-install/build.sh
@@ -19,10 +19,14 @@
 fi
 
 # Now ensure that all files were installed to all supported ABIs
+ANDROID_NDK_ROOT=$NDK
+NDK_BUILDTOOLS_PATH=$NDK/build/tools
+source $NDK_BUILDTOOLS_PATH/prebuilt-common.sh
 MISSING=
 for ABI in $ABIS; do
     DIR=$PWD/libs/$ABI
-    for FILENAME in libfoo.so libpath1.so libpath2.so; do
+    SUFFIX=$(get_lib_suffix_for_abi $ABI)
+    for FILENAME in libfoo$SUFFIX libpath1$SUFFIX libpath2$SUFFIX; do
         FILE=$DIR/$FILENAME
         if [ ! -f "$FILE" ]; then
             MISSING="$MISSING $FILE"
diff --git a/tests/run-tests.sh b/tests/run-tests.sh
index 2a1a625..9accfd2 100755
--- a/tests/run-tests.sh
+++ b/tests/run-tests.sh
@@ -393,6 +393,14 @@
     fail_panic "Can't locate $WINE"
 fi
 
+# $1: output bitcode path
+gen_empty_bitcode() {
+    TEMP_FILE=`mktemp`
+    mv $TEMP_FILE ${TEMP_FILE}.c
+    run $(get_llvm_toolchain_binprefix $DEFAULT_LLVM_VERSION)/clang -target le32-none-ndk -emit-llvm -c -o $1 ${TEMP_FILE}.c
+    rm -f ${TEMP_FILE}.c
+}
+
 case $ABI in
     default)  # Let the APP_ABI in jni/Application.mk decide what to build
         ;;
@@ -400,8 +408,26 @@
         NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS APP_ABI=$ABI"
         ;;
     *)
-        echo "ERROR: Unsupported abi value: $ABI"
-        exit 1
+        if [ -n "$(filter_out "$PREBUILT_ABIS" "$ABI")" ] && [ -n "$(find_ndk_unknown_archs)" ]; then
+            ABI=$(find_ndk_unknown_archs)
+            NDK_BUILD_FLAGS="$NDK_BUILD_FLAGS APP_ABI=$ABI"
+
+            # Create those temporarily files to make testing happy
+            GCC_TOOLCHAIN_VERSION=`cat $NDK/toolchains/llvm-$DEFAULT_LLVM_VERSION/setup.mk | grep '^TOOLCHAIN_VERSION' | awk '{print $3'}`
+            run mkdir -p $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI
+            run mkdir -p $NDK/$GABIXX_SUBDIR/libs/$ABI
+            run mkdir -p $NDK/$LIBPORTABLE_SUBDIR/libs/$ABI
+            run gen_empty_bitcode $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI/libsupc++.a
+            run gen_empty_bitcode $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI/libgnustl_static.a
+            run gen_empty_bitcode $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI/libgnustl_shared.bc
+            run gen_empty_bitcode $NDK/$GABIXX_SUBDIR/libs/$ABI/libgabi++_static.a
+            run gen_empty_bitcode $NDK/$GABIXX_SUBDIR/libs/$ABI/libgabi++_shared.bc
+            run cp -a $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$(get_default_abi_for_arch arm)/include $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI
+            run cp -a $NDK/$LIBPORTABLE_SUBDIR/libs/$(get_default_abi_for_arch arm)/libportable.a $NDK/$LIBPORTABLE_SUBDIR/libs/$ABI
+        else
+            echo "ERROR: Unsupported abi value: $ABI"
+            exit 1
+        fi
         ;;
 esac
 
@@ -500,8 +526,8 @@
 is_incompatible_abi ()
 {
     local PROJECT="$1"
-
-    if [ "$ABI" != "default" ] ; then
+    # Basically accept all for unknown arch, even some cases may not be suitable for this way
+    if [ "$ABI" != "default" -a "$ABI" != "$(find_ndk_unknown_archs)" ] ; then
         # check APP_ABI
         local APP_ABIS=`get_build_var $PROJECT APP_ABI`
         APP_ABIS=$APP_ABIS" "
@@ -520,6 +546,54 @@
     return 1
 }
 
+compile_on_the_fly()
+{
+    local DSTDIR="$1"
+    local COMPILER_PKGNAME="compiler.abcc"
+    if [ -z "`$ADB_CMD -s "$DEVICE" shell pm path $COMPILER_PKGNAME`" ]; then
+        dump "ERROR: No abcc found for unknown arch testing"
+        return 1
+    fi
+    run $ADB_CMD -s "$DEVICE" shell am force-stop $COMPILER_PKGNAME
+    run $ADB_CMD -s "$DEVICE" shell am startservice --user 0 -a ${COMPILER_PKGNAME}.BITCODE_COMPILE_TEST -n $COMPILER_PKGNAME/.AbccService -e working_dir $DSTDIR
+
+    old_pid="`$ADB_CMD -s "$DEVICE" shell top -n 1 | grep $COMPILER_PKGNAME | awk '{print $1}'`"
+    threshold=`echo $((60*10))` # Wait at most 10 minutes for large testcases
+    sleep_seconds=0
+    while [ 2 -eq 2 ]; do
+      if [ $sleep_seconds -gt $threshold ]; then
+        pid="`$ADB_CMD -s "$DEVICE" shell top -n 1 | grep $COMPILER_PKGNAME | awk '{print $1}'`"
+        if [ "$pid" = "$old_pid" ]; then
+          # Too much time
+          break
+        fi
+        old_pid="$pid"
+        sleep_seconds=0
+      fi
+      if [ -n "`$ADB_CMD -s "$DEVICE" shell ls $DSTDIR | grep compile_result`" ]; then
+        # Compile done
+        break
+      fi
+      sleep 3
+      sleep_seconds="`echo $sleep_seconds + 3 | bc`"
+    done
+    ret="`$ADB_CMD -s "$DEVICE" shell cat $DSTDIR/compile_result`"
+    ret=`echo $ret | tr -d "\r\n"`
+    if [ $sleep_seconds -gt $threshold ] || [ "$ret" != "0" ]; then
+      dump "ERROR: Could not compile bitcodes for $TEST_NAME on device"
+      if [ $sleep_seconds -gt $threshold ]; then
+        dump "- Reason: Compile time too long"
+      elif [ -n "`$ADB_CMD -s "$DEVICE" shell ls $DSTDIR | grep compile_error`" ]; then
+        dump "- Reason: `$ADB_CMD -s "$DEVICE" shell cat $DSTDIR/compile_error`"
+      fi
+      run $ADB_CMD -s "$DEVICE" shell am force-stop $COMPILER_PKGNAME
+      return 1
+    fi
+    run $ADB_CMD -s "$DEVICE" shell am force-stop $COMPILER_PKGNAME
+    return 0
+}
+
+
 build_project ()
 {
     local NAME=`basename $1`
@@ -702,8 +776,11 @@
                 fi
             fi
         fi
+        if [ "$ABI" = "$(find_ndk_unknown_archs)" ] && [ -d "$BUILD_DIR/`basename $TEST`/libs" ]; then
+            cd $BUILD_DIR/`basename $TEST`/libs && ln -s $ABI $CPU_ABI
+        fi
         SRCDIR="$BUILD_DIR/`basename $TEST`/libs/$CPU_ABI"
-        if [ ! -d "$SRCDIR" ]; then
+        if [ ! -d "$SRCDIR" ] || [ -z "`ls $SRCDIR`" ]; then
             dump "Skipping NDK device test run (no $CPU_ABI binaries): $TEST_NAME"
             return 0
         fi
@@ -711,6 +788,27 @@
         # those declared in $TEST/BROKEN_RUN
         adb_shell_mkdir "$DEVICE" $DSTDIR
 
+        if [ "$ABI" = "$(find_ndk_unknown_archs)" ]; then # on-the-fly on-device compilation
+            run $ADB_CMD -s "$DEVICE" shell rm -rf $DSTDIR/abcc_tmp
+            adb_shell_mkdir "$DEVICE" $DSTDIR/abcc_tmp
+            run $ADB_CMD -s "$DEVICE" shell chmod 0777 $DSTDIR/abcc_tmp
+            for SRCFILE in `ls $SRCDIR`; do
+                run $ADB_CMD -s "$DEVICE" push "$SRCDIR/$SRCFILE" $DSTDIR/abcc_tmp
+                run $ADB_CMD -s "$DEVICE" shell chmod 0644 $DSTDIR/abcc_tmp/$SRCFILE
+            done
+            compile_on_the_fly $DSTDIR/abcc_tmp
+            if [ $? -ne 0 ]; then
+                test "$CONTINUE_ON_BUILD_FAIL" != "yes" && exit 1
+                return 1
+            fi
+            run rm -f $SRCDIR/*
+            run $ADB_CMD -s "$DEVICE" pull $DSTDIR/abcc_tmp $SRCDIR
+            run rm -f $SRCDIR/compile_result
+            run rm -f $SRCDIR/compile_error
+            run rm -f $SRCDIR/*$(get_lib_suffix_for_abi $ABI)
+            run $ADB_CMD -s "$DEVICE" shell rm -rf $DSTDIR/abcc_tmp
+        fi
+
         # Prepare gabi++ runtime
         if [ ! -z "$NDK_ABI_FILTER" ]; then
             SRCFILE="$NDK/sources/cxx-stl/gabi++/libs/$CPU_ABI/libgabi++_shared.so"
@@ -831,7 +929,7 @@
               CPU_ABIS=armeabi
             fi
             for CPU_ABI in $CPU_ABIS; do
-                if [ "$ABI" = "default" -o "$ABI" = "$CPU_ABI" ] ; then
+                if [ "$ABI" = "default" -o "$ABI" = "$CPU_ABI" -o "$ABI" = "$(find_ndk_unknown_archs)" ] ; then
                     AT_LEAST_CPU_ABI_MATCH="yes"
                     for DIR in `ls -d $ROOTDIR/tests/device/*`; do
                         if is_buildable $DIR; then
@@ -849,5 +947,11 @@
 fi
 
 dump "Cleaning up..."
+if [ "$ABI" = "$(find_ndk_unknown_archs)" ]; then
+  # Cleanup some intermediate files for testing
+  run rm -rf $NDK/$GNUSTL_SUBDIR/$GCC_TOOLCHAIN_VERSION/libs/$ABI
+  run rm -rf $NDK/$GABIXX_SUBDIR/libs/$ABI
+  run rm -rf $NDK/$LIBPORTABLE_SUBDIR/libs/$ABI
+fi
 rm -rf $BUILD_DIR
 dump "Done."