Integrate abcc codebase.
This CL needs https://android-review.googlesource.com/#/c/66545/
Integrated abcc will be used after llvm 3.3 (included) by default.
If we want to build python version, we can add --use-python to build-llvm.sh.
Every host-related will be put under <abcc>/host/.
Every device-related will be put under <abcc>/device/.
Other common-based will be put under <abcc>.
The usage is just the same like before. No learning curve issue.
On host, we can dump information if we use --verbose.
On device, we can -DVERBOSE=1 to dump info to logcat.
Also, fix one bug on run-tests.sh. We need to copy instead of
soft link, otherwise the second abi won't be tested.
Change-Id: Ib95a3aabb40dc85bf73f8a35254108688ac654b7
diff --git a/build/tools/build-llvm.sh b/build/tools/build-llvm.sh
index 8503f1a..e679371 100755
--- a/build/tools/build-llvm.sh
+++ b/build/tools/build-llvm.sh
@@ -53,6 +53,10 @@
do_check_option () { CHECK=yes; }
register_option "--check" do_check_option "Check LLVM"
+USE_PYTHON=no
+do_use_python_option () { USE_PYTHON=yes; }
+register_option "--use-python" do_use_python_option "Use python bc2native instead of integrated one"
+
register_jobs_option
register_canadian_option
register_try64_option
@@ -236,6 +240,24 @@
mkdir -p $LLVM_BUILD_OUT && cd $LLVM_BUILD_OUT
fail_panic "Couldn't cd into llvm build path: $LLVM_BUILD_OUT"
+# Only start using integrated bc2native source >= 3.3 by default
+LLVM_VERSION="`echo $TOOLCHAIN | tr '-' '\n' | tail -n 1`"
+LLVM_VERSION_MAJOR=`echo $LLVM_VERSION | tr '.' '\n' | head -n 1`
+LLVM_VERSION_MINOR=`echo $LLVM_VERSION | tr '.' '\n' | tail -n 1`
+if [ $LLVM_VERSION_MAJOR -lt 3 ]; then
+ USE_PYTHON=yes
+elif [ $LLVM_VERSION_MAJOR -eq 3 ] && [ $LLVM_VERSION_MINOR -lt 3 ]; then
+ USE_PYTHON=yes
+fi
+
+if [ "$USE_PYTHON" != "yes" ]; then
+ run cp -a $NDK_DIR/tests/abcc/jni/*.cpp $SRC_DIR/$TOOLCHAIN/llvm/tools/ndk-bc2native
+ run cp -a $NDK_DIR/tests/abcc/jni/*.h $SRC_DIR/$TOOLCHAIN/llvm/tools/ndk-bc2native
+ run cp -a $NDK_DIR/tests/abcc/jni/host/*.cpp $SRC_DIR/$TOOLCHAIN/llvm/tools/ndk-bc2native
+ run cp -a $NDK_DIR/tests/abcc/jni/host/*.h $SRC_DIR/$TOOLCHAIN/llvm/tools/ndk-bc2native
+ export LLVM_TOOLS_FILTER="PARALLEL_DIRS:=\$\$(PARALLEL_DIRS:%=% ndk-bc2native)"
+fi
+
run $SRC_DIR/$TOOLCHAIN/llvm/configure \
--prefix=$TOOLCHAIN_BUILD_PREFIX \
--host=$ABI_CONFIGURE_HOST \
@@ -373,7 +395,13 @@
find $TOOLCHAIN_BUILD_PREFIX/lib -maxdepth 1 -type f \( -name "*.dll" -o -name "*.so" \) -exec $STRIP {} \;
# install script
-cp -p "$SRC_DIR/$TOOLCHAIN/llvm/tools/ndk-bc2native/ndk-bc2native.py" "$TOOLCHAIN_BUILD_PREFIX/bin/"
+if [ "$USE_PYTHON" != "yes" ]; then
+ # Remove those intermediate cpp
+ rm -f $SRC_DIR/$TOOLCHAIN/llvm/tools/ndk-bc2native/*.cpp
+ rm -f $SRC_DIR/$TOOLCHAIN/llvm/tools/ndk-bc2native/*.h
+else
+ cp -p "$SRC_DIR/$TOOLCHAIN/llvm/tools/ndk-bc2native/ndk-bc2native.py" "$TOOLCHAIN_BUILD_PREFIX/bin/"
+fi
# copy to toolchain path
run copy_directory "$TOOLCHAIN_BUILD_PREFIX" "$TOOLCHAIN_PATH"
diff --git a/build/tools/make-standalone-toolchain.sh b/build/tools/make-standalone-toolchain.sh
index 30d5439..eca5dd0 100755
--- a/build/tools/make-standalone-toolchain.sh
+++ b/build/tools/make-standalone-toolchain.sh
@@ -290,8 +290,12 @@
echo ' shift'
echo 'done'
echo 'test -z "$output" && output=a.out'
- echo 'export PYTHONPATH=`dirname $0`/../lib/python2.7/'
- echo '`dirname $0`/python `dirname $0`/ndk-bc2native.py --sysroot=`dirname $0`/../sysroot --abi='$TARGET_ABI' --platform='$PLATFORM' --file $output $output'
+ echo 'if [ -f "`dirname $0`/ndk-bc2native" ]; then'
+ echo ' `dirname $0`/ndk-bc2native --sysroot=`dirname $0`/../sysroot --abi='$TARGET_ABI' --platform='$PLATFORM' --file $output $output'
+ echo 'else'
+ echo ' export PYTHONPATH=`dirname $0`/../lib/python2.7/'
+ echo ' `dirname $0`/python `dirname $0`/ndk-bc2native.py --sysroot=`dirname $0`/../sysroot --abi='$TARGET_ABI' --platform='$PLATFORM' --file $output $output'
+ echo 'fi'
else
echo 'rem Call bc2native if needed'
echo ''
@@ -310,8 +314,12 @@
echo ' if not "%output%" == "" goto :check_done'
echo ' set output=a.out'
echo ':check_done'
- echo 'set PYTHONPATH=%~dp0\\..\\lib\\python2.7\\'
- echo '%~dp0\\python'$HOST_EXE' %~dp0\\ndk-bc2native.py --sysroot=%~dp0\\..\\sysroot --abi='$TARGET_ABI' --platform='$PLATFORM' --file %output% %output%'
+ echo 'if exist %~dp0\\ndk-bc2native'$HOST_EXE' ('
+ echo ' %~dp0\\ndk-bc2native'$HOST_EXE' --sysroot=%~dp0\\.\\sysroot --abi='$TARGET_ABI' --platform='$PLATFORM' --file %output% %output'
+ echo 'else ('
+ echo ' set PYTHONPATH=%~dp0\\..\\lib\\python2.7\\'
+ echo ' %~dp0\\python'$HOST_EXE' %~dp0\\ndk-bc2native.py --sysroot=%~dp0\\..\\sysroot --abi='$TARGET_ABI' --platform='$PLATFORM' --file %output% %output%'
+ echo ')'
fi
}
diff --git a/tests/abcc/build-abcc.sh b/tests/abcc/build-abcc.sh
index f96f9ae..01f909c 100755
--- a/tests/abcc/build-abcc.sh
+++ b/tests/abcc/build-abcc.sh
@@ -144,6 +144,7 @@
for ABI in $ABIS; do
run rm -rf obj libs
run $NDK_DIR/ndk-build -B APP_ABI=$ABI -C jni
+ fail_panic "Build ndk-build failed. Abort."
if [ "$DEBUG" = "yes" ]; then
run rm -f AndroidManifest.xml
run cp -a AndroidManifest.xml.debug AndroidManifest.xml
diff --git a/tests/abcc/jni/Abcc.cpp b/tests/abcc/jni/Abcc.cpp
new file mode 100644
index 0000000..e597e71
--- /dev/null
+++ b/tests/abcc/jni/Abcc.cpp
@@ -0,0 +1,287 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <cstdlib>
+#include <fcntl.h>
+#include <fstream>
+#include <sstream>
+#include <stdint.h>
+#include <unistd.h>
+#include "Abcc.h"
+using namespace abcc;
+
+TargetAbi::TargetAbi(const std::string &abi) {
+ if (abi == "armeabi")
+ mAbi = ARMEABI;
+ else if (abi == "x86")
+ mAbi = X86;
+ else if (abi == "mips")
+ mAbi = MIPS;
+ else
+ mAbi = ARMEABI_V7A; // Default
+}
+
+
+BitcodeInfo::BitcodeInfo(const std::string &bc)
+ : mShared(false), mBCPath(bc) {
+ std::string stem = mBCPath.substr(0, mBCPath.rfind("."));
+ mTargetBCPath = stem + "-target.bc";
+ mObjPath = stem + ".o";
+ mOutPath = stem; // If shared, we will add .so after readWrapper
+ mSOName = mBCPath.substr(mBCPath.rfind("/") + 1);
+}
+
+int BitcodeInfo::readWrapper(BitcodeCompiler &compiler) {
+ int fd = open(mBCPath.c_str(), O_RDONLY);
+ if (fd < 0) {
+ return -1;
+ }
+
+ unsigned char buffer[5] = {'\0', '\0', '\0', '\0', '\0'};
+ read(fd, buffer, 4); // Skip magic number, we have checked
+ read(fd, buffer, 4); // version
+ read(fd, buffer, 4); // offset
+ swapEndian(buffer, 4);
+ int offset = transferBytesToNum(buffer, 4);
+ lseek(fd, 4*7, SEEK_SET);
+ offset -= 4*7; // Useless, skip
+
+ while (offset > 0) {
+ read(fd, buffer, 4);
+ swapEndian(buffer, 4);
+ uint16_t length = transferBytesToNum(buffer, 2);
+ uint16_t tag = transferBytesToNum(buffer+2, 2);
+ LOGV("length: %d", length);
+ LOGV("tag: %d", tag);
+ length = (length + 3) & ~3;
+
+ unsigned char *large_buffer = (unsigned char*) malloc(length+1);
+ if (large_buffer == 0) {
+ LOGE("Cannot create buffer for wrapper field");
+ close(fd);
+ return -1;
+ }
+ large_buffer[length] = '\0';
+ int n = read(fd, large_buffer, length);
+ if (n != length) {
+ LOGE("Read wrapper field error");
+ close(fd);
+ return -1;
+ }
+
+ if (tag == 0x5002) {
+ const char* ldflags = reinterpret_cast<char*>(large_buffer);
+ LOGV("Wrapper field: %s", ldflags);
+ if (compiler.parseLDFlags(*this, ldflags) != 0) {
+ LOGE("Cannot parse ldflags from wrapper");
+ close(fd);
+ return -1;
+ }
+ } else {
+ // Some field maybe useful, but we use wrapper to encode command line,
+ // this is not necessary for now.
+ }
+ offset -= (length + 4);
+ free(large_buffer);
+ } // while
+ close(fd);
+ return 0;
+}
+
+void BitcodeInfo::dropExternalLDLibs(SONameMap &map) {
+ for (SONameMap::iterator i = map.begin(), e = map.end(); i != e; ++i) {
+ BitcodeInfo &info = i->second;
+ for (std::list<std::string>::iterator i_libs = info.mLDLibs.begin(),
+ e_libs = info.mLDLibs.end(); i_libs != e_libs; ) {
+ std::list<std::string>::iterator cur_libs = i_libs++;
+ std::string full_soname = std::string("lib") + *cur_libs + ".so";
+ if (map.find(full_soname) == map.end()) {
+ LOGV("Drop -l%s from %s for linking order decision", cur_libs->c_str(), info.mSOName.c_str());
+ info.mLDLibs.erase(cur_libs);
+ }
+ }
+ }
+}
+
+void BitcodeInfo::swapEndian(unsigned char *buffer, size_t n) {
+ // We uses le32, so it must be LITTLE ENDIAN
+ for (size_t i = 0; i < n/2; ++i) {
+ char tmp = buffer[i];
+ buffer[i] = buffer[n-i-1];
+ buffer[n-i-1] =tmp;
+ }
+}
+
+int BitcodeInfo::transferBytesToNum(const unsigned char *buffer, size_t n) {
+ int ret = 0;
+ for (size_t i = 0; i < n; ++i) {
+ ret = ret * 0x100 + buffer[i];
+ }
+ return ret;
+}
+
+
+BitcodeCompiler::BitcodeCompiler(const std::string &abi, const std::string &sysroot, const std::string &working_dir)
+ : mAbi(abi), mSysroot(sysroot), mWorkingDir(working_dir), mRet(RET_OK) {
+ // CFlags
+ mGlobalCFlags = kGlobalTargetAttrs[mAbi].mBaseCFlags;
+ mGlobalCFlags += std::string(" -mtriple=") + kGlobalTargetAttrs[mAbi].mTriple;
+ mGlobalCFlags += " -filetype=obj -relocation-model=pic -code-model=small";
+ mGlobalCFlags += " -use-init-array -mc-relax-all";
+
+#ifdef DEBUG
+ mGlobalCFlags += std::string(" ") + "-O0";
+#else
+ mGlobalCFlags += std::string(" ") + "-O2";
+#endif
+
+ if (mAbi == TargetAbi::ARMEABI || mAbi == TargetAbi::ARMEABI_V7A)
+ mGlobalCFlags += std::string(" ") + "-arm-enable-ehabi -arm-enable-ehabi-descriptors -float-abi=soft";
+
+ // LDFlags
+ mGlobalLDFlags = kGlobalTargetAttrs[mAbi].mBaseLDFlags;
+ mGlobalLDFlags += std::string(" -Bsymbolic -X -m ") + kGlobalTargetAttrs[mAbi].mLinkEmulation;
+ mGlobalLDFlags += std::string(" --sysroot=") + mSysroot;
+ mGlobalLDFlags += " -eh-frame-hdr -dynamic-linker /system/bin/linker";
+
+ // LDLibs
+ mGlobalLDLibs += "";
+}
+
+void BitcodeCompiler::translate() {
+ for (std::vector<BitcodeInfo>::const_iterator i = mBitcodeFiles.begin(),
+ e = mBitcodeFiles.end(); i != e; ++i) {
+ const BitcodeInfo &bc = *i;
+ std::string cmd = mExecutableToolsPath[(unsigned)CMD_TRANSLATE];
+ cmd += std::string(" -arch=") + kGlobalTargetAttrs[mAbi].mArch;
+ cmd += " " + bc.mBCPath + " -o " + bc.mTargetBCPath;
+ runCmd(cmd, /*dump=*/true);
+ if (returnCode() != RET_OK) {
+ mRet = RET_FAIL_TRANSLATE;
+ return;
+ }
+
+ removeIntermediateFile(bc.mBCPath);
+ }
+}
+
+void BitcodeCompiler::compile() {
+ for (std::vector<BitcodeInfo>::const_iterator i = mBitcodeFiles.begin(),
+ e = mBitcodeFiles.end(); i != e; ++i) {
+ const BitcodeInfo &bc = *i;
+ std::string cmd = mExecutableToolsPath[(unsigned)CMD_COMPILE];
+ cmd += " " + mGlobalCFlags;
+ cmd += " " + bc.mTargetBCPath + " -o " + bc.mObjPath;
+ runCmd(cmd, /*dump=*/true);
+ if (returnCode() != RET_OK) {
+ mRet = RET_FAIL_COMPILE;
+ return;
+ }
+
+ removeIntermediateFile(bc.mTargetBCPath);
+ }
+}
+
+void BitcodeCompiler::link() {
+ BitcodeInfo::dropExternalLDLibs(mSonameMap);
+
+ while (!mSonameMap.empty()) {
+ SONameMap::iterator i = mSonameMap.begin(), e = mSonameMap.end();
+ for (; i != e; ++i) {
+ const BitcodeInfo &bc = i->second;
+
+ if (bc.mLDLibs.empty()) {
+ // No internal dependency for this bitcode
+ LOGV("Process bitcode: %s -> %s", bc.mBCPath.c_str(), bc.mSOName.c_str());
+ std::string cmd = mExecutableToolsPath[(unsigned)CMD_LINK];
+ cmd += " " + mGlobalLDFlags;
+ cmd += " " + bc.mLDFlags;
+ if (bc.mShared) {
+ cmd += std::string(" ") + mSysroot + "/usr/lib/crtbegin_so.o";
+ cmd += " -shared " + bc.mObjPath + " -o " + bc.mOutPath;
+ cmd += " -soname " + bc.mSOName;
+ } else {
+ cmd += std::string(" ") + mSysroot + "/usr/lib/crtbegin_dynamic.o";
+ cmd += " " + bc.mObjPath + " -o " + bc.mOutPath;
+ }
+ // Add ldlibs
+ cmd += " " + mGlobalLDLibs;
+ cmd += " " + bc.mLDLibsStr;
+ cmd += " " + mExecutableToolsPath[(unsigned)CMD_LINK_RUNTIME];
+ if (bc.mShared)
+ cmd += std::string(" ") + mSysroot + "/usr/lib/crtend_so.o";
+ else
+ cmd += std::string(" ") + mSysroot + "/usr/lib/crtend_android.o";
+ runCmd(cmd, /*dump=*/true);
+ if (returnCode() != RET_OK)
+ return;
+
+ copyRuntime(bc);
+ removeIntermediateFile(bc.mObjPath);
+
+ mSonameMap.erase(i);
+ BitcodeInfo::dropExternalLDLibs(mSonameMap);
+ break; // Re-compute
+ }
+ } // for
+
+ if (i == e) {
+ LOGE("Failed to compute linking order: Internal cyclic dependency!");
+ mRet = RET_FAIL_LINK;
+ return;
+ }
+ } // while
+}
+
+void BitcodeCompiler::runCmd(std::string cmd, bool dump) {
+ LOGV("Command: %s", cmd.c_str());
+ std::string logfilename = mWorkingDir + "/compile_log";
+ if (dump) {
+ cmd += " 2>&1 > " + logfilename;
+ }
+ int ret = system(cmd.c_str());
+ if (ret != 0) {
+ mRet = RET_FAIL_RUN_CMD;
+ if (dump) {
+ std::ifstream ifs(logfilename.c_str());
+ std::stringstream sstr;
+ sstr << ifs.rdbuf();
+ LOGE("Error message: %s", sstr.str().c_str());
+ std::fstream fout;
+ std::string file = mWorkingDir + "/compile_error";
+ fout.open(file.c_str(), std::fstream::out | std::fstream::app);
+ fout << "Failed command: " << cmd << "\n";
+ fout << "Error message: " << sstr.str() << "\n";
+ fout.close();
+ }
+ return;
+ }
+ mRet = RET_OK;
+}
+
+void BitcodeCompiler::prepareBitcodes() {
+ getBitcodeFiles();
+ createSONameMapping();
+}
+
+void BitcodeCompiler::createSONameMapping() {
+ for (std::vector<BitcodeInfo>::const_iterator i = mBitcodeFiles.begin(),
+ e = mBitcodeFiles.end(); i != e; ++i) {
+ const BitcodeInfo &info = *i;
+ LOGV("Map soname %s -> %s", info.mSOName.c_str(), info.mBCPath.c_str());
+ mSonameMap[info.mSOName] = info;
+ }
+}
diff --git a/tests/abcc/jni/Abcc.h b/tests/abcc/jni/Abcc.h
new file mode 100644
index 0000000..6b6d1ba
--- /dev/null
+++ b/tests/abcc/jni/Abcc.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ABCC_ABCC_H
+#define ABCC_ABCC_H
+
+#include <list>
+#include <map>
+#include <string>
+#include <vector>
+
+namespace abcc {
+
+enum ReturnCode {
+ RET_OK,
+ RET_FAIL_RUN_CMD,
+ RET_FAIL_UNSUPPORT_ABI,
+ RET_FAIL_PREPARE_BITCODE,
+ RET_FAIL_PREPARE_TOOL,
+ RET_FAIL_CLEANUP,
+ RET_FAIL_TRANSLATE,
+ RET_FAIL_COMPILE,
+ RET_FAIL_LINK,
+};
+
+enum Command {
+ CMD_TRANSLATE = 0,
+ CMD_COMPILE,
+ CMD_LINK,
+ CMD_LINK_RUNTIME,
+};
+
+class TargetAbi {
+public:
+ enum Abi {
+ ARMEABI = 0,
+ ARMEABI_V7A,
+ X86,
+ MIPS,
+ };
+
+private:
+ Abi mAbi;
+
+public:
+ TargetAbi(const std::string &abi);
+ operator int() const { return (int)mAbi; }
+ operator const char*() const {
+ if (mAbi == ARMEABI) return "armeabi";
+ if (mAbi == ARMEABI_V7A) return "armeabi-v7a";
+ if (mAbi == X86) return "x86";
+ if (mAbi == MIPS) return "mips";
+ return 0;
+ }
+ const char* getArch() const {
+ if (mAbi == ARMEABI || mAbi == ARMEABI_V7A) return "arm";
+ if (mAbi == X86) return "x86";
+ if (mAbi == MIPS) return "mips";
+ return 0;
+ }
+};
+
+struct TargetAttributes {
+ const char *mArch;
+ const char *mTriple;
+ const char *mLinkEmulation;
+ const char *mBaseCFlags;
+ const char *mBaseLDFlags;
+};
+
+const TargetAttributes kGlobalTargetAttrs[] = {
+ {"arm", "armv5te-linux-androideabi", "armelf_linux_eabi", "", ""},
+#ifdef FORCE_ARM
+ {"arm", "armv7-linux-androideabi", "armelf_linux_eabi", "", ""},
+#else
+ {"arm", "thumbv7-linux-androideabi", "armelf_linux_eabi", "", ""},
+#endif
+ {"x86", "i686-linux-android", "elf_i386", "-disable-fp-elim -force-align-stack -mattr=-ssse3,-sse41,-sse42,-sse4a,-popcnt", ""},
+ {"mips", "mipsel-linux-android", "elf32ltsmip", "", ""},
+};
+
+// Used when computing mutual dependency
+class BitcodeCompiler;
+class BitcodeInfo;
+typedef std::map<std::string/*soname*/, BitcodeInfo> SONameMap;
+
+class BitcodeInfo {
+public:
+ BitcodeInfo() {} // Only for stl use
+ BitcodeInfo(const std::string &bc);
+ int readWrapper(BitcodeCompiler &);
+ static void dropExternalLDLibs(SONameMap &map);
+
+ bool mShared;
+ std::string mBCPath;
+ std::string mTargetBCPath;
+ std::string mObjPath;
+ std::string mOutPath;
+ std::string mSOName;
+ std::string mLDFlags; // --no-undefined, ...
+ std::list<std::string> mLDLibs; // -lxxx, will be removed one-by-one until empty
+ std::string mLDLibsStr; // Immutable once read in
+
+public:
+ static void swapEndian(unsigned char *buffer, size_t n);
+ static int transferBytesToNum(const unsigned char *buffer, size_t n);
+};
+
+
+class BitcodeCompiler {
+protected:
+ TargetAbi mAbi;
+ std::string mSysroot;
+ std::string mWorkingDir;
+
+ // Target-independent, but global
+ std::string mGlobalCFlags;
+ std::string mGlobalLDFlags;
+ std::string mGlobalLDLibs;
+
+ ReturnCode mRet;
+ std::vector<BitcodeInfo> mBitcodeFiles;
+ SONameMap mSonameMap;
+ std::string mExecutableToolsPath[(unsigned)CMD_LINK_RUNTIME+1];
+
+public:
+ BitcodeCompiler(const std::string &abi, const std::string &sysroot, const std::string &working_dir);
+ const ReturnCode returnCode() const { return mRet; }
+ virtual void cleanupPre() {}
+ virtual void cleanupPost() {}
+ void prepare() {
+ prepareBitcodes();
+ if (returnCode() != RET_OK)
+ return;
+
+ prepareToolchain();
+ if (returnCode() != RET_OK)
+ return;
+ }
+ void execute() {
+ translate();
+ if (returnCode() != RET_OK)
+ return;
+
+ compile();
+ if (returnCode() != RET_OK)
+ return;
+
+ link();
+ if (returnCode() != RET_OK)
+ return;
+ }
+
+private:
+ void prepareBitcodes();
+ void createSONameMapping();
+ virtual void getBitcodeFiles() = 0;
+ virtual void prepareToolchain() = 0;
+ virtual void copyRuntime(const BitcodeInfo &info) = 0;
+ virtual void removeIntermediateFile(const std::string &path) = 0;
+ void translate();
+ void compile();
+ void link();
+
+public:
+ virtual int parseLDFlags(BitcodeInfo &info, const std::string &str) = 0;
+
+protected:
+ void runCmd(std::string cmd, bool dump = false);
+};
+
+} // namespace abcc
+
+// FIXME: We use LOGV, LOGE in Abcc.cpp, how to prevent this anti dependency?
+#ifdef ON_DEVICE
+#include "Abcc_device.h"
+#else
+#include "Abcc_host.h"
+#endif
+
+#endif
diff --git a/tests/abcc/jni/Android.mk b/tests/abcc/jni/Android.mk
index 98ed993..c3b184a 100644
--- a/tests/abcc/jni/Android.mk
+++ b/tests/abcc/jni/Android.mk
@@ -20,7 +20,11 @@
LOCAL_MODULE := libjni_abcc
LOCAL_MODULE_CLASS := SHARED_LIBRARIES
-LOCAL_SRC_FILES := main.cpp
+LOCAL_C_INCLUDES := $(LOCAL_PATH)/device
+LOCAL_SRC_FILES := \
+ Abcc.cpp \
+ device/Abcc_device.cpp \
+ device/main.cpp
# Check in AOSP or NDK usage
ifeq ($(SYSTEM_PREBUILT_PACKAGE),true)
@@ -31,6 +35,7 @@
include $(BUILD_SHARED_LIBRARY)
else # SYSTEM_PREBUILT_PACKAGE
+LOCAL_CFLAGS += -DON_DEVICE=1
LOCAL_CFLAGS += -DENABLE_PARALLEL_LLVM_CG=1
LOCAL_CFLAGS += -DVERBOSE=0
LOCAL_LDLIBS := -llog
diff --git a/tests/abcc/jni/device/Abcc_device.cpp b/tests/abcc/jni/device/Abcc_device.cpp
new file mode 100644
index 0000000..62a8ea3
--- /dev/null
+++ b/tests/abcc/jni/device/Abcc_device.cpp
@@ -0,0 +1,220 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dirent.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sstream>
+#include <sys/stat.h>
+#if ENABLE_PARALLEL_LLVM_CG
+#include <cpu-features.h>
+#endif
+#include "Abcc_device.h"
+using namespace abcc;
+
+#if defined(__arm__) && defined(__ARM_ARCH_7A__)
+# define CURRENT_ABI "armeabi-v7a"
+#elif defined(__arm__)
+# define CURRENT_ABI "armeabi"
+#elif defined(__i386__)
+# define CURRENT_ABI "x86"
+#elif defined(__mips__)
+# define CURRENT_ABI "mips"
+#else
+# error "Unsupport target abi"
+#endif
+
+
+DeviceBitcodeCompiler::DeviceBitcodeCompiler(const std::string &working_dir, const std::string &sysroot)
+ : BitcodeCompiler(CURRENT_ABI, sysroot, working_dir) {}
+
+void DeviceBitcodeCompiler::cleanupPost() {
+ ReturnCode ret = mRet;
+ std::string cmd("echo ");
+ if (ret == RET_OK)
+ cmd += "0";
+ else
+ cmd += "255";
+ cmd += " > " + mWorkingDir + "/compile_result";
+ runCmd(cmd);
+
+ if (ret == RET_OK) {
+ cmd = "rm -f " + mWorkingDir + "/compile_log";
+ runCmd(cmd);
+ }
+ cmd = "chmod 0755 " + mWorkingDir + "/*";
+ runCmd(cmd);
+ mRet = ret; // Restore execution return code
+}
+
+int DeviceBitcodeCompiler::parseLDFlags(BitcodeInfo &info, const std::string &orig_str) {
+ std::stringstream ss(orig_str);
+ std::string str;
+ while (ss >> str) {
+ if (str.find("--sysroot") != std::string::npos) {
+ continue;
+ }
+ if (str == "-o") {
+ ss >> str;
+ continue;
+ }
+ if (str == "-soname") {
+ ss >> str;
+ info.mSOName = str;
+ continue;
+ }
+ if (str == "-shared") {
+ info.mShared = true;
+ info.mOutPath += ".so";
+ continue;
+ }
+
+ // Parse -lxxx
+ if (str.size() > 2 &&
+ str.substr(0, 2) == "-l") {
+ info.mLDLibs.push_back(str.substr(2));
+ info.mLDLibsStr += " " + str;
+ continue;
+ }
+
+ // Some other flags, like --no-undefined, -z now, -z noexecstack, ...
+ info.mLDFlags += str + " ";
+ } // while
+ return 0;
+}
+
+void DeviceBitcodeCompiler::getBitcodeFiles() {
+ std::vector<std::string> files;
+ DIR *dp = opendir(mWorkingDir.c_str());
+ if (!dp) {
+ mRet = RET_FAIL_PREPARE_BITCODE;
+ return;
+ }
+
+ struct dirent *entry = 0;
+ while ((entry = readdir(dp)) != 0) {
+ std::string filename(entry->d_name);
+ std::string full_path = mWorkingDir + "/" + filename;
+ if (filename == "." || filename == "..")
+ continue;
+
+ std::string libpath = mSysroot + "/usr/lib/" + filename.substr(0, filename.rfind('.')) + ".so";
+ struct stat buf;
+ if (stat(libpath.c_str(), &buf) == 0) {
+ // This file has the same name in our runtime library pool.
+ std::string cmd = "rm -f " + full_path;
+ runCmd(cmd.c_str());
+ continue;
+ }
+
+
+ int fd = open(full_path.c_str(), O_RDONLY);
+ if (fd < 0) {
+ LOGV("Error opening file: %s (Ignored)", full_path.c_str());
+ continue;
+ }
+
+ unsigned char buffer[4];
+ read(fd, buffer, 4);
+ close(fd);
+ BitcodeInfo::swapEndian(buffer, 4);
+ int magic = BitcodeInfo::transferBytesToNum(buffer, 4);
+
+ if (magic != 0x0b17c0de) {
+ LOGV("Found file %s magic: %x, but we need a wrapped bitcode.", full_path.c_str(), magic);
+ continue;
+ }
+
+ LOGV("Push_back a bitcode: %s", full_path.c_str());
+ files.push_back(full_path);
+ } // while
+ closedir(dp);
+
+ if (files.empty()) {
+ LOGV("No bitcodes needs to compile");
+ return;
+ }
+
+ if (returnCode() != RET_OK) {
+ LOGV("Cannot get bitcode files from directory: %s", mWorkingDir.c_str());
+ return;
+ }
+
+ for (std::vector<std::string>::const_iterator i = files.begin(),
+ e = files.end(); i != e; ++i) {
+ BitcodeInfo bcinfo(*i);
+ if (bcinfo.readWrapper(*this) != 0) {
+ LOGE("Cannot read wrapper for bitcode %s", i->c_str());
+ mRet = RET_FAIL_PREPARE_BITCODE;
+ return;
+ }
+ mBitcodeFiles.push_back(bcinfo);
+ }
+}
+
+void DeviceBitcodeCompiler::prepareToolchain() {
+ // le32-none-ndk-translate
+ std::string cmd = std::string("LD_LIBRARY_PATH=") + mSysroot + "/usr/lib";
+ cmd += " " + mSysroot + "/usr/bin/le32-none-ndk-translate";
+ mExecutableToolsPath[(unsigned)CMD_TRANSLATE] = cmd;
+
+ // llc
+ cmd = std::string("LD_LIBRARY_PATH=") + mSysroot + "/usr/lib";
+ cmd += " " + mSysroot + "/usr/bin/llc";
+#ifdef ENABLE_PARALLEL_LLVM_CG
+ std::ostringstream stream;
+ stream << android_getCpuCount();
+ cmd += " -thread=" + stream.str();
+#endif
+ mExecutableToolsPath[(unsigned)CMD_COMPILE] = cmd;
+
+ // ld.mcld
+ cmd = std::string("LD_LIBRARY_PATH=") + mSysroot + "/usr/lib";
+ cmd += " " + mSysroot + "/usr/bin/ld.mcld";
+ cmd += " -L" + mWorkingDir;
+ cmd += " -L" + mSysroot + "/usr/lib";
+ cmd += " -L/system/lib";
+ mExecutableToolsPath[(unsigned)CMD_LINK] = cmd;
+
+ cmd = " @" + mSysroot + "/usr/lib/libportable.wrap " + mSysroot + "/usr/lib/libportable.a";
+ cmd += " " + mSysroot + "/usr/lib/libcompiler_rt_static.a";
+ cmd += " " + mSysroot + "/usr/lib/libgabi++_shared.so";
+ cmd += " -ldl";
+ mExecutableToolsPath[(unsigned)CMD_LINK_RUNTIME] = cmd;
+}
+
+void DeviceBitcodeCompiler::copyRuntime(const BitcodeInfo &info) {
+ runCmd(std::string("cp -f ") + mSysroot + "/usr/lib/libgabi++_shared.so " + mWorkingDir + "/libgabi++_shared.so");
+
+ std::stringstream ss(info.mLDLibsStr);
+ std::string deplib;
+ while (ss >> deplib) {
+ if (deplib.substr(0, 2) == "-l") {
+ std::string libname = "lib" + deplib.substr(2) + ".so";
+ std::string libpath = mSysroot + "/usr/lib/" + libname;
+ struct stat buf;
+ if (stat(libpath.c_str(), &buf) == 0) {
+ // Found!
+ LOGV("Copy runtime library: %s", libname.c_str());
+ runCmd("cp -f " + libpath + " " + mWorkingDir + "/" + libname);
+ }
+ }
+ }
+}
+
+void DeviceBitcodeCompiler::removeIntermediateFile(const std::string &path) {
+ runCmd(std::string("rm -f ") + path);
+}
diff --git a/tests/abcc/jni/device/Abcc_device.h b/tests/abcc/jni/device/Abcc_device.h
new file mode 100644
index 0000000..50eda83
--- /dev/null
+++ b/tests/abcc/jni/device/Abcc_device.h
@@ -0,0 +1,76 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ABCC_ABCC_DEVICE_H
+#define ABCC_ABCC_DEVICE_H
+
+#include <android/log.h>
+#if VERBOSE
+#include <sys/time.h>
+#endif
+#include "Abcc.h"
+
+#define LOG_TAG "AbccNative"
+#define LOGE(format, ...) do {\
+ __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, format, ##__VA_ARGS__);\
+ } while(0)
+
+#if VERBOSE
+#define LOGV(format, ...) do {\
+ __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, format, ##__VA_ARGS__);\
+ } while(0)
+#else
+#define LOGV(format, ...)
+#endif // VERBOSE
+
+namespace abcc {
+
+#if VERBOSE
+class Timer {
+private:
+ struct timeval _t0;
+public:
+ Timer() {};
+ void start() { gettimeofday(&_t0, NULL); }
+ long long stop() {
+ struct timeval t;
+ gettimeofday(&t, NULL);
+ long long l0 = _t0.tv_sec * 1000000LL + _t0.tv_usec;
+ long long l = t.tv_sec * 1000000LL + t.tv_usec;
+ return l - l0;
+ }
+};
+#endif // VERBOSE
+
+
+class DeviceBitcodeCompiler : public BitcodeCompiler {
+public:
+ DeviceBitcodeCompiler(const std::string &working_dir, const std::string &sysroot);
+ virtual void cleanupPost();
+
+public:
+ virtual int parseLDFlags(BitcodeInfo &info, const std::string &str);
+
+private:
+ virtual void getBitcodeFiles();
+ virtual void prepareToolchain();
+ virtual void copyRuntime(const BitcodeInfo &info);
+ virtual void removeIntermediateFile(const std::string &path);
+};
+
+} // namespace abcc
+
+#endif
diff --git a/tests/abcc/jni/device/main.cpp b/tests/abcc/jni/device/main.cpp
new file mode 100644
index 0000000..ced2fc7
--- /dev/null
+++ b/tests/abcc/jni/device/main.cpp
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <jni.h>
+#include "Abcc_device.h"
+using namespace abcc;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+JNIEXPORT jint JNICALL
+Java_compiler_abcc_AbccService_genLibs(JNIEnv *env, jobject thiz,
+ jstring j_lib_dir, jstring j_sysroot) {
+ const char *lib_dir = env->GetStringUTFChars(j_lib_dir, 0);
+ LOGV("Working directory: %s", lib_dir);
+
+ const char *sysroot = env->GetStringUTFChars(j_sysroot, 0);
+ LOGV("Sysroot: %s", sysroot);
+
+
+ std::auto_ptr<BitcodeCompiler> compiler(new DeviceBitcodeCompiler(lib_dir, sysroot));
+ compiler->prepare();
+ if (compiler->returnCode() != RET_OK) {
+ LOGE("prepare failed");
+ return -1;
+ }
+
+ compiler->cleanupPre();
+ if (compiler->returnCode() != RET_OK) {
+ LOGE("cleanupPre failed");
+ return -1;
+ }
+
+#if VERBOSE
+ Timer t;
+ t.start();
+#endif
+
+ compiler->execute();
+
+#if VERBOSE
+ long long elapsed_msec = (t.stop() + 500) / 1000;
+ LOGV("Elapsed time: %lld.%03ds", elapsed_msec/1000, (int)elapsed_msec%1000);
+#endif
+
+ compiler->cleanupPost();
+
+ if (compiler->returnCode() != RET_OK) {
+ LOGE("execution failed");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+#ifdef __cplusplus
+} // extern "C"
+#endif
diff --git a/tests/abcc/jni/host/Abcc_host.cpp b/tests/abcc/jni/host/Abcc_host.cpp
new file mode 100644
index 0000000..57ca00c
--- /dev/null
+++ b/tests/abcc/jni/host/Abcc_host.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <sstream>
+#include "Abcc_host.h"
+using namespace abcc;
+
+bool kVerbose = false;
+
+HostBitcodeCompiler::HostBitcodeCompiler(const std::string &abi, const std::string &sysroot,
+ const std::string &input, const std::string &output, const std::string &working_dir,
+ const std::string &platform)
+ : BitcodeCompiler(abi, sysroot, working_dir), mIn(input), mOut(output),
+ mNDKDir(""), mPlatform(platform) {
+}
+
+HostBitcodeCompiler::HostBitcodeCompiler(const std::string &abi, const std::string &sysroot, const std::string &ndk_dir, const std::string &toolchain_bin,
+ const std::string &input, const std::string &output, const std::string &working_dir,
+ const std::string &platform)
+ : BitcodeCompiler(abi, sysroot, working_dir), mIn(input), mOut(output),
+ mNDKDir(ndk_dir), mPlatform(platform), mToolchainBinPath(toolchain_bin) {
+}
+
+int HostBitcodeCompiler::parseLDFlags(BitcodeInfo &info, const std::string &orig_str) {
+ std::stringstream ss(orig_str);
+ std::string str;
+ while (ss >> str) {
+ if (str.find("--sysroot") != std::string::npos) {
+ continue;
+ }
+ if (str == "-o") {
+ ss >> str;
+ continue;
+ }
+ if (str == "-soname") {
+ ss >> str;
+ info.mSOName = str;
+ continue;
+ }
+ if (str == "-shared") {
+ info.mShared = true;
+ info.mOutPath += ".so";
+ continue;
+ }
+
+ if (str.size() > 2 &&
+ str.substr(str.size() - 2) == ".a") {
+ info.mLDLibs.push_back(str);
+ info.mLDLibsStr += " " + str;
+ continue;
+ }
+ if (str.size() > 3 &&
+ str.substr(str.size() - 3) == ".so") {
+ info.mLDLibs.push_back(str);
+ info.mLDLibsStr += " " + str;
+ continue;
+ }
+
+ // Parse -lxxx
+ if (str.size() > 2 &&
+ str.substr(0, 2) == "-l") {
+ info.mLDLibs.push_back(str.substr(2));
+ info.mLDLibsStr += " " + str;
+ continue;
+ }
+
+ // Some other flags, like --no-undefined, -z now, -z noexecstack, ...
+ info.mLDFlags += str + " ";
+ } // while
+ return 0;
+}
+
+void HostBitcodeCompiler::getBitcodeFiles() {
+ BitcodeInfo bcinfo(mIn);
+ if (bcinfo.readWrapper(*this) != 0) {
+ LOGE("Cannot read wrapper for bitcode %s", mIn.c_str());
+ mRet = RET_FAIL_PREPARE_BITCODE;
+ return;
+ }
+
+ bcinfo.mOutPath = mOut;
+ mBitcodeFiles.push_back(bcinfo);
+}
+
+void HostBitcodeCompiler::prepareToolchain() {
+ // le32-none-ndk-translate
+ std::string cmd = getToolchainBinPath() + "/le32-none-ndk-translate";
+ mExecutableToolsPath[(unsigned)CMD_TRANSLATE] = cmd;
+
+ // llc
+ cmd = getToolchainBinPath() + "/llc";
+ mExecutableToolsPath[(unsigned)CMD_COMPILE] = cmd;
+
+ // ld.mcld
+ cmd = getToolchainBinPath() + "/ld.mcld";
+ cmd += " -L" + mSysroot + "/usr/lib";
+ mExecutableToolsPath[(unsigned)CMD_LINK] = cmd;
+
+ cmd = " @" + getLibPortablePath() + "/libportable.wrap " + getLibPortablePath() + "/libportable.a";
+ cmd += " " + getCompilerRTPath() + "/libcompiler_rt_static.a";
+ cmd += " " + getGAbixxPath() + "/libgabi++_shared.so";
+ cmd += " -ldl";
+ mExecutableToolsPath[(unsigned)CMD_LINK_RUNTIME] = cmd;
+}
+
+void HostBitcodeCompiler::copyRuntime(const BitcodeInfo &info) {
+}
+
+void HostBitcodeCompiler::removeIntermediateFile(const std::string &path) {
+ if (!kVerbose)
+ runCmd(std::string("rm -f ") + path);
+}
+
+const std::string HostBitcodeCompiler::getToolchainBinPath() const {
+ if (!mNDKDir.empty())
+ return mToolchainBinPath;
+ else
+ return mSysroot + "/usr/bin";
+}
+
+const std::string HostBitcodeCompiler::getCompilerRTPath() const {
+ if (!mNDKDir.empty())
+ return std::string(mNDKDir) + "/sources/android/compiler-rt/libs/" + (const char*)mAbi;
+ else
+ return mSysroot + "/usr/lib";
+}
+
+const std::string HostBitcodeCompiler::getGAbixxPath() const {
+ if (!mNDKDir.empty())
+ return std::string(mNDKDir) + "/sources/cxx-stl/gabi++/libs/" + (const char*)mAbi;
+ else
+ return mSysroot + "/usr/lib";
+}
+
+const std::string HostBitcodeCompiler::getLibPortablePath() const {
+ if (!mNDKDir.empty())
+ return std::string(mNDKDir) + "/sources/android/libportable/libs/" + (const char*)mAbi;
+ else
+ return mSysroot + "/usr/lib";
+}
diff --git a/tests/abcc/jni/host/Abcc_host.h b/tests/abcc/jni/host/Abcc_host.h
new file mode 100644
index 0000000..f0caf05
--- /dev/null
+++ b/tests/abcc/jni/host/Abcc_host.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ABCC_ABCC_HOST_H
+#define ABCC_ABCC_HOST_H
+
+#include <cstdio>
+#include "Abcc.h"
+
+#define LOG(format, ...) do { \
+ fprintf(stderr, format, ##__VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+} while(0)
+
+extern bool kVerbose;
+#define LOGE LOG
+#define LOGV(format, ...) do {\
+ if (kVerbose) LOG(format, ##__VA_ARGS__); \
+} while(0)
+
+namespace abcc {
+
+class HostBitcodeCompiler : public BitcodeCompiler {
+ std::string mIn;
+ std::string mOut;
+ std::string mNDKDir; // empty string if standalone mode
+ std::string mPlatform;
+ std::string mToolchainBinPath; // Used at ndk mode to prevent tedious path issue
+
+public:
+ HostBitcodeCompiler(const std::string &abi, const std::string &sysroot,
+ const std::string &input, const std::string &output, const std::string &working_dir,
+ const std::string &platform);
+ HostBitcodeCompiler(const std::string &abi, const std::string &sysroot, const std::string &ndk_dir, const std::string &toolchain_bin,
+ const std::string &input, const std::string &output, const std::string &working_dir,
+ const std::string &platform);
+
+public:
+ virtual int parseLDFlags(BitcodeInfo &info, const std::string &str);
+
+private:
+ virtual void getBitcodeFiles();
+ virtual void prepareToolchain();
+ virtual void copyRuntime(const BitcodeInfo &info);
+ virtual void removeIntermediateFile(const std::string &path);
+
+private:
+ const std::string getToolchainBinPath() const;
+ const std::string getCompilerRTPath() const;
+ const std::string getGAbixxPath() const;
+ const std::string getLibPortablePath() const;
+};
+
+} // namespace abcc
+
+#endif
diff --git a/tests/abcc/jni/host/main.cpp b/tests/abcc/jni/host/main.cpp
new file mode 100644
index 0000000..95a07c8
--- /dev/null
+++ b/tests/abcc/jni/host/main.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2013, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <memory>
+#include <unistd.h>
+#include "Abcc_host.h"
+using namespace abcc;
+
+static int parseArguments(char **argv,
+ std::string &abi, std::string &ndk_dir, std::string &sysroot,
+ std::string &input, std::string &output, std::string &platform) {
+ unsigned idx = 1;
+ while (argv[idx] != 0) {
+ std::string arg = argv[idx++];
+ if (arg.find("--abi=") != std::string::npos) {
+ abi = arg.substr(arg.rfind('=')+1);
+ continue;
+ }
+ if (arg.find("--ndk-dir=") != std::string::npos) {
+ ndk_dir = arg.substr(arg.rfind('=')+1);
+ continue;
+ }
+ if (arg.find("--sysroot=") != std::string::npos) {
+ sysroot = arg.substr(arg.rfind('=')+1);
+ continue;
+ }
+ if (arg.find("--platform=") != std::string::npos) {
+ platform = arg.substr(arg.rfind('=')+1);
+ continue;
+ }
+ if (arg.find("--file") != std::string::npos) {
+ input = argv[idx++];
+ output = argv[idx++];
+ continue;
+ }
+ if (arg == "--verbose") {
+ kVerbose = true;
+ continue;
+ }
+
+ LOGE("Unsupport argument: %s", arg.c_str());
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv) {
+ char buf[256] = {'\0'};
+ std::string this_bin = argv[0];
+ std::string cwd;
+ if (getcwd(buf, 256))
+ cwd = buf;
+ else {
+ LOGE("getcwd failed");
+ return -1;
+ }
+ std::string abi;
+ std::string ndk_dir;
+ std::string sysroot;
+ std::string input;
+ std::string output;
+ std::string platform;
+ std::string working_dir;
+ std::string toolchain_bin;
+
+ if (parseArguments(argv,
+ abi, ndk_dir, sysroot, input, output, platform) != 0)
+ return -1;
+
+ // Make sure they are absolute path
+ if (this_bin[0] != '/')
+ this_bin = cwd + "/" + this_bin;
+ if (input[0] != '/')
+ input = cwd + "/" + input;
+ if (output[0] != '/')
+ output = cwd + "/" + output;
+
+ toolchain_bin = this_bin.substr(0, this_bin.rfind('/'));
+ working_dir = input.substr(0, input.rfind('/'));
+ if (platform.empty()) // Folow ndk-bc2native.py usage
+ platform = "android-9";
+
+ if (abi.empty() || input.empty() || output.empty() || toolchain_bin.empty() || platform.empty()) {
+ LOGE("Argument out-of-expect.");
+ return -1;
+ }
+
+ if (sysroot.empty() && ndk_dir.empty()) {
+ LOGE("Must be either standalone or ndk mode");
+ return -1;
+ }
+
+ if (sysroot.empty()) {
+ // NDK mode
+ sysroot = ndk_dir + "/platforms/" + platform + "/arch-" + TargetAbi(abi).getArch();
+ }
+
+
+ std::auto_ptr<BitcodeCompiler> compiler;
+ if (ndk_dir.empty())
+ compiler.reset(new HostBitcodeCompiler(abi, sysroot,
+ input, output,
+ working_dir, platform));
+ else
+ compiler.reset(new HostBitcodeCompiler(abi, sysroot, ndk_dir, toolchain_bin,
+ input, output,
+ working_dir, platform));
+
+ compiler->prepare();
+ if (compiler->returnCode() != RET_OK) {
+ LOGE("prepare failed");
+ return -1;
+ }
+
+ compiler->cleanupPre();
+ if (compiler->returnCode() != RET_OK) {
+ LOGE("cleanupPre failed");
+ return -1;
+ }
+
+ compiler->execute();
+ compiler->cleanupPost();
+
+ if (compiler->returnCode() != RET_OK) {
+ LOGE("execution failed");
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/tests/abcc/jni/main.cpp b/tests/abcc/jni/main.cpp
deleted file mode 100644
index 69d200d..0000000
--- a/tests/abcc/jni/main.cpp
+++ /dev/null
@@ -1,690 +0,0 @@
-/*
- * Copyright 2013, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <jni.h>
-#include <android/log.h>
-#include <dirent.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <list>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-#include <fstream>
-#include <sstream>
-#include <pthread.h>
-#include <sys/stat.h>
-#if ENABLE_PARALLEL_LLVM_CG
-#include <cpu-features.h>
-#endif
-#if VERBOSE
-#include <sys/time.h>
-#endif
-
-#define LOG_TAG "AbccNative"
-#define LOGE(format, ...) do {\
- __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, format, ##__VA_ARGS__);\
- } while(0)
-#define LOGI(format, ...) do {\
- __android_log_print(ANDROID_LOG_INFO, LOG_TAG, format, ##__VA_ARGS__);\
- } while(0)
-#define LOGV(format, ...) do {\
- __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, format, ##__VA_ARGS__);\
- } while(0)
-
-
-enum TargetAbi {
- abi_armeabi = 0,
- abi_armeabi_v7a,
- abi_x86,
- abi_mips,
-};
-
-#if defined(__arm__) && defined(__ARM_ARCH_7A__)
-TargetAbi abi = abi_armeabi_v7a;
-#elif defined(__arm__)
-TargetAbi abi = abi_armeabi;
-#elif defined(__i386__)
-TargetAbi abi = abi_x86;
-#elif defined(__mips__)
-TargetAbi abi = abi_mips;
-#else
-# error "Unsupport target"
-#endif
-
-enum TargetFieldID {
- target_arch = 0,
- target_triple = 1,
- target_emulation = 2,
- target_extra_cflags = 3,
- target_extra_ldflags = 4,
-};
-
-const char* target_data[4][5] = {
- {"arm", "armv5te-linux-androideabi", "armelf_linux_eabi", "", ""},
- {"arm", "thumbv7-linux-androideabi", "armelf_linux_eabi", "", ""},
- {"x86", "i686-linux-android", "elf_i386", "-disable-fp-elim -force-align-stack -mattr=-ssse3,-sse41,-sse42,-sse4a,-popcnt", ""},
- {"mips", "mipsel-linux-android", "elf32ltsmip", "", ""},
-};
-
-enum ExecutableFieldID {
- exec_translate = 0,
- exec_llc = 1,
- exec_ld = 2,
-};
-
-const unsigned NUM_THREADS = 1;
-const char *lib_dir;
-const char *sysroot;
-
-// Use std::list to easily keep validity while erase
-typedef std::vector<std::string> LDFlagsTy;
-typedef std::list<std::string> LibsDependedTy;
-
-struct BitcodeInfoTy {
- BitcodeInfoTy() {}
- BitcodeInfoTy(const std::string &bitcode)
- : mBitcode(bitcode), mShared(false) {}
-
- std::string mBitcode;
- std::string mSOName;
- LDFlagsTy mLDFlags;
- LibsDependedTy mLDLibs; // Will be removed again and again until empty while removeExternalLDLibs
- std::string mLDLibsStr; // Immutable once read in
- bool mShared;
-};
-
-typedef std::map<std::string/*soname*/, BitcodeInfoTy> SONameMapTy;
-
-void swapEndian(unsigned char *buffer, size_t n) {
- for (size_t i = 0; i < n/2; ++i) {
- char tmp = buffer[i];
- buffer[i] = buffer[n-i-1];
- buffer[n-i-1] =tmp;
- }
-}
-
-int transferBytesToNum(const unsigned char *buffer, size_t n) {
- int ret = 0;
- for (size_t i = 0; i < n; ++i) {
- ret = ret * 0x100 + buffer[i];
- }
- return ret;
-}
-
-class Timer
-{
- private:
- struct timeval _t0;
- public:
- Timer() {};
- void start() { gettimeofday(&_t0, NULL); }
- long long stop() {
- struct timeval t;
- gettimeofday(&t, NULL);
- long long l0 = _t0.tv_sec * 1000000LL + _t0.tv_usec;
- long long l = t.tv_sec * 1000000LL + t.tv_usec;
- return l - l0;
- }
-};
-
-/*
- The bitcode wrapper definition:
-
- struct AndroidBitcodeWrapper {
- uint32_t Magic;
- uint32_t Version;
- uint32_t BitcodeOffset;
- uint32_t BitcodeSize;
- uint32_t HeaderVersion;
- uint32_t TargetAPI;
- uint32_t PNaClVersion;
- uint16_t CompilerVersionTag;
- uint16_t CompilerVersionLen;
- uint32_t CompilerVersion;
- uint16_t OptimizationLevelTag;
- uint16_t OptimizationLevelLen;
- uint32_t OptimizationLevel;
- };
-*/
-
-int parseLDFlags(BitcodeInfoTy &info, std::string& ldflags) {
-
- if (info.mBitcode.empty()) {
- LOGE("Must set bitcode name before parseLDFlags.");
- return 1;
- }
-
- info.mSOName = info.mBitcode.substr(info.mBitcode.rfind("/") + 1);
- info.mLDFlags.clear();
- info.mLDLibs.clear();
- info.mLDLibsStr.clear();
-
- std::stringstream ss(ldflags);
- std::string str;
-
- while (ss >> str) {
- if (str.find("--sysroot") != std::string::npos) {
- continue; // Ignore on-host sysroot
- }
- if (str == "-o") { // Ignore on-host output path
- ss >> str;
- continue;
- }
- if (str == "-soname") { // Ignore on-host output path
- ss >> str;
- info.mSOName = str;
- continue;
- }
- if (str.substr(0, 2) == "-l") {
- info.mLDLibs.push_back(str.substr(2));
- info.mLDLibsStr += std::string(" ") + str;
- continue;
- }
- if (str == "-shared") {
- info.mShared = true;
- continue;
- }
- if (str.size() > 2 &&
- str.substr(str.size()-2) == ".a") {
- str = str.substr(0, str.size()-2);
- str = str.substr(str.rfind("/") + 4);
- str = std::string("-l") + str;
- }
- if (str.size() > 3 &&
- str.substr(str.size()-3) == ".so") {
- str = str.substr(0, str.size()-3);
- str = str.substr(str.rfind("/") + 4);
- str = std::string("-l") + str;
- }
-
- info.mLDFlags.push_back(str);
- }
- return 0;
-}
-
-int readWrapper(BitcodeInfoTy &info) {
- if (info.mBitcode.empty()) {
- LOGE("Must set bitcode name before readWrapper.");
- return 1;
- }
- info.mSOName = info.mBitcode.substr(info.mBitcode.rfind("/") + 1);
- info.mLDFlags.clear();
- info.mLDLibs.clear();
- info.mLDLibsStr.clear();
-
- const char *bc = info.mBitcode.c_str();
- LOGI("Read wrapper for bitcode: %s", bc);
- int fd = open(bc, O_RDONLY);
- unsigned char buffer[5] = {'\0', '\0', '\0', '\0', '\0'};
- read(fd, buffer, 4); // magic
- swapEndian(buffer, 4);
- int magic = transferBytesToNum(buffer, 4);
- if (magic != 0x0b17c0de) {
- LOGE("Wrong bitcode wrapper");
- close(fd);
- return 1;
- }
- read(fd, buffer, 4); // version
- read(fd, buffer, 4); // offset
- swapEndian(buffer, 4);
- int offset = transferBytesToNum(buffer, 4);
- lseek(fd, 4*7, SEEK_SET);
- offset -= 4*7; // skip
- while (offset > 0) {
- read(fd, buffer, 4);
- swapEndian(buffer, 4);
- uint16_t length = transferBytesToNum(buffer, 2);
- uint16_t tag = transferBytesToNum(buffer+2, 2);
- LOGI("length: %d", length);
- LOGI("tag: %d", tag);
- length = (length + 3) & ~3;
-
- unsigned char *large_buffer = (unsigned char*) malloc(length+1);
- large_buffer[length] = '\0';
- int n = read(fd, large_buffer, length);
- if (n != length) {
- LOGE("Read bitcode data error");
- close(fd);
- return 1;
- }
- if (tag == 0x5001) {
- swapEndian(large_buffer, length);
- int type = transferBytesToNum(large_buffer, length);
- if (type == /*shared=*/1) {
- info.mShared = true;
- }
- } else if (tag == 0x5002) {
- std::string ldflags = reinterpret_cast<char*>(large_buffer);
- parseLDFlags(info,ldflags);
- } else {
- // Other field, just omit
- }
- offset -= (length + 4);
- free(large_buffer);
- }
- close(fd);
- return 0;
-}
-
-int handleTask(const std::string &cmd, bool write_err_msg = false) {
-#if VERBOSE
- LOGV("Command: %s", cmd.c_str());
-#endif
- int ret;
- std::string logfilename = std::string(lib_dir) + "/compile_log";
- if (write_err_msg) {
- std::string new_cmd = cmd + " > " + logfilename + " 2>&1";
- ret = system(new_cmd.c_str());
- } else {
- ret = system(cmd.c_str());
- }
- if (ret != 0) {
- LOGE("Failed command: %s", cmd.c_str());
- if (write_err_msg) {
- std::ifstream ifs(logfilename.c_str());
- std::stringstream sstr;
- sstr << ifs.rdbuf();
-
- LOGE("Error message: %s", sstr.str().c_str());
-
- std::fstream fout;
- std::string file = std::string(lib_dir) + "/compile_error";
- fout.open(file.c_str(), std::fstream::out | std::fstream::app);
- fout << "Failed command: " << cmd << "\n";
- fout << "Error message: " << sstr.str() << "\n";
- fout.close();
- }
- }
- return ret;
-}
-
-int getFilesFromDir(const char *dir, std::vector<std::string> &files) {
- files.clear();
- DIR *dp = opendir(dir);
- if (!dp) return 1;
-
- struct dirent *entry = 0;
- while ((entry = readdir(dp)) != 0) {
- std::string filename(entry->d_name);
- if (filename == "." || filename == "..")
- continue;
-
- std::string full_path = std::string(dir) + "/" + filename;
- int fd = open(full_path.c_str(), O_RDONLY);
- if (fd < 0) {
- LOGE("Error opening file: %s", full_path.c_str());
- continue;
- }
- unsigned char buffer[4];
- read(fd, buffer, 4); // magic
- close(fd);
- swapEndian(buffer, 4);
- int magic = transferBytesToNum(buffer, 4);
-
- if (magic != 0x0b17c0de) {
- LOGI("Found file %s magic: %x, but we need: %x (Ignored)", full_path.c_str(), magic, 0x0b17c0de);
- continue;
- }
-
- std::string stem = full_path.substr(0, full_path.rfind("."));
- std::string lib = stem;
- int lib_fd = open(lib.c_str(), O_RDONLY);
- if (lib_fd >= 0) {
- read(lib_fd, buffer, 4); // magic
- close(lib_fd);
- swapEndian(buffer, 4);
- int magic = transferBytesToNum(buffer, 4);
- if (magic == 0x7f454c46) {
- LOGI("Found file %s magic: %x, No compile for %s", lib.c_str(), magic, full_path.c_str());
- continue;
- }
- }
-
- lib = stem + ".so";
- lib_fd = open(lib.c_str(), O_RDONLY);
- if (lib_fd >= 0) {
- read(lib_fd, buffer, 4); // magic
- close(lib_fd);
- swapEndian(buffer, 4);
- int magic = transferBytesToNum(buffer, 4);
- if (magic == 0x7f454c46) {
- LOGI("Found file %s magic: %x, No compile for %s", lib.c_str(), magic, full_path.c_str());
- continue;
- }
- }
-
- LOGI("Push back a bitcode: %s", full_path.c_str());
- files.push_back(full_path);
- }
- closedir(dp);
- return 0;
-}
-
-void removeExternalLDLibs(SONameMapTy &soname_map) {
- for (SONameMapTy::iterator i = soname_map.begin(), e = soname_map.end();
- i != e; ++i) {
- BitcodeInfoTy &info = i->second;
- for (LibsDependedTy::iterator i_libs = info.mLDLibs.begin(),
- e_libs = info.mLDLibs.end(); i_libs != e_libs; ) {
- LibsDependedTy::iterator cur_it = i_libs;
- ++i_libs; // In case we remove this -l field
- std::string full_soname = std::string("lib") + *cur_it + ".so";
- if (soname_map.find(full_soname) == soname_map.end()) {
- LOGI("Drop -l%s from %s for linking order.", (*cur_it).c_str(), info.mBitcode.c_str());
- info.mLDLibs.erase(cur_it);
- }
- }
- }
-}
-
-void *translateBitcode(void *par) {
- std::string bc = (char*)par;
- std::string stem = bc.substr(0, bc.rfind("."));
- std::string target_bc = stem + "-target.bc";
-
- /*
- * le32-none-ndk-translate
- */
- std::string cmd;
- cmd = std::string("LD_LIBRARY_PATH=") + sysroot + "/usr/lib";
- cmd += std::string(" ") + sysroot + "/usr/bin/le32-none-ndk-translate";
- cmd += std::string(" -arch=") + target_data[abi][target_arch];
- cmd += std::string(" -o ") + target_bc;
- cmd += std::string(" ") + bc;
-
- int ret = handleTask(cmd, true/*write_err_msg*/);
- if (ret != 0) {
- LOGE("Cannot translate bitcode (%s): %s", bc.c_str(), cmd.c_str());
- } else {
-#ifdef NDEBUG
- handleTask(std::string("rm -f ") + bc);
-#endif
- }
- return (void*)ret;
-}
-
-void *compileBitcode(void *par) {
- std::string bc = (char*)par;
- std::string stem = bc.substr(0, bc.rfind("."));
- std::string target_bc = stem + "-target.bc";
- std::string obj = stem + ".o";
-
- /*
- * llc
- */
- std::string cmd;
- cmd = std::string("LD_LIBRARY_PATH=") + sysroot + "/usr/lib";
- cmd += std::string(" ") + sysroot + "/usr/bin/llc";
- cmd += std::string(" -mtriple=") + target_data[abi][target_triple];
-#if defined(__arm__)
- cmd += std::string(" -arm-enable-ehabi -arm-enable-ehabi-descriptors");
-#endif
- cmd += " -filetype=obj -relocation-model=pic -code-model=small";
- cmd += " -use-init-array -mc-relax-all -O2";
-#if defined(__arm__)
- cmd += " -float-abi=soft";
-#endif
-#if ENABLE_PARALLEL_LLVM_CG
- std::ostringstream stream;
- stream << android_getCpuCount();
- cmd += " -thread=" + stream.str();
-#endif
- cmd += std::string(" ") + target_data[abi][target_extra_cflags];
- cmd += std::string(" -o ") + obj;
- cmd += std::string(" ") + target_bc;
-
- int ret = handleTask(cmd, true/*write_err_msg*/);
- if (ret != 0) {
- LOGE("Cannot compile bitcode (%s): %s", bc.c_str(), cmd.c_str());
- } else {
-#ifdef NDEBUG
- handleTask(std::string("rm -f ") + target_bc);
-#endif
- }
- return (void*)ret;
-}
-
-int linkBitcode(const BitcodeInfoTy &info) {
- std::string stem(info.mBitcode);
- stem = stem.substr(0, stem.rfind("."));
- std::string obj = stem + ".o";
- std::string lib = stem;
- if (info.mShared) {
- lib += ".so";
- }
-
- /*
- * ld.mcld
- */
- handleTask(std::string("rm -f ") + lib);
- std::string cmd;
- cmd = std::string("LD_LIBRARY_PATH=") + sysroot + "/usr/lib";
- cmd += std::string(" ") + sysroot + "/usr/bin/ld.mcld";
- cmd += std::string(" --sysroot=") + sysroot;
- if (info.mShared) {
- cmd += " -shared";
- }
- cmd += " -eh-frame-hdr -dynamic-linker /system/bin/linker";
- cmd += std::string(" -X -m ") + target_data[abi][target_emulation];
- cmd += std::string(" ") + target_data[abi][target_extra_ldflags];
- if (info.mShared) {
- cmd += std::string(" ") + sysroot + "/usr/lib/crtbegin_so.o";
- } else {
- cmd += std::string(" ") + sysroot + "/usr/lib/crtbegin_dynamic.o";
- }
- if (info.mSOName != "") {
- cmd += std::string(" -soname ") + info.mSOName;
- }
- cmd += std::string(" ") + obj;
- cmd += std::string(" @") + sysroot + "/usr/lib/libportable.wrap " + sysroot + "/usr/lib/libportable.a";
- cmd += std::string(" -L/system/lib");
- cmd += std::string(" -L") + lib_dir;
- cmd += std::string(" -L") + sysroot + "/usr/lib";
- for (LDFlagsTy::const_iterator i = info.mLDFlags.begin(), e = info.mLDFlags.end();
- i != e; ++i) {
- cmd += std::string(" ") + *i;
- }
- // 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;
- // Replace libgcc by libcompiler-rt + libgabi++
- cmd += std::string(" ") + sysroot + "/usr/lib/libcompiler_rt_static.a";
- cmd += std::string(" ") + sysroot + "/usr/lib/libgabi++_shared.so";
- cmd += std::string(" -ldl");
-
- if (info.mShared) {
- cmd += std::string(" ") + sysroot + "/usr/lib/crtend_so.o";
- } else {
- cmd += std::string(" ") + sysroot + "/usr/lib/crtend_android.o";
- }
- cmd += std::string(" -o ") + lib;
-
- int ret = handleTask(cmd, true/*write_err_msg*/);
- if (ret != 0) {
- LOGE("Cannot link bitcode (%s): %s", info.mBitcode.c_str(), cmd.c_str());
- } else {
- handleTask(std::string("chmod 0755 ") + lib);
-#ifdef NDEBUG
- handleTask(std::string("rm -f ") + obj);
-#endif
- }
- return ret;
-}
-
-int prepareRuntime(const BitcodeInfoTy &info) {
- std::stringstream ss(info.mLDLibsStr);
- std::string deplibs;
-
- while (ss >> deplibs) {
- if (deplibs.substr(0,2) == "-l") {
- std::string libname = "lib" + deplibs.substr(2) + ".so";
- std::string full_lib_path = std::string(sysroot) + "/usr/lib/" + libname;
- struct stat buf;
- // runtime found
- if (stat(full_lib_path.c_str(),&buf) == 0) {
- handleTask("cp -p " + full_lib_path + " " + lib_dir + "/" + libname);
- }
- }
- }
- return 0;
-}
-
-int genLibs(const char *lib_dir, const char *sysroot) {
- jint ret = 0;
-
- std::vector<std::string/*bitcode*/> files;
- ret = getFilesFromDir(lib_dir, files);
- if (ret != 0 || files.empty()) {
- LOGE("Cannot get files from directory: %s", lib_dir);
- return ret;
- }
-
- // Read bitcode wrapper information
- std::vector<BitcodeInfoTy> bc_infos;
- for (std::vector<std::string>::const_iterator i = files.begin(),
- e = files.end(); i != e; ++i) {
- const std::string &bitcode = *i;
- BitcodeInfoTy bc_info(bitcode);
- ret = readWrapper(bc_info);
- if (ret != 0) {
- LOGE("Cannot read wrapper for bitcodes.");
- return ret;
- }
- bc_infos.push_back(bc_info);
- }
-
- // Create mapping from soname to info
- SONameMapTy soname_map;
- for (std::vector<BitcodeInfoTy>::const_iterator i = bc_infos.begin(),
- e = bc_infos.end(); i != e; ++i) {
- const BitcodeInfoTy &info = *i;
- LOGI("Link relationship: %s -> %s (BitcodeInfo)",
- info.mSOName.c_str(), info.mBitcode.c_str());
- soname_map[info.mSOName] = info;
- }
-
- // Run translate and compile in parallel
- pthread_t tid[NUM_THREADS];
-
- // Translate
- for (std::vector<BitcodeInfoTy>::const_iterator i = bc_infos.begin(),
- e = bc_infos.end(); i < e; i += NUM_THREADS) {
- unsigned thread_i;
- for (thread_i = 0; thread_i < NUM_THREADS; ++thread_i) {
- if (i + thread_i == e) {
- break;
- }
- const BitcodeInfoTy &info = *(i + thread_i);
- pthread_create(&tid[thread_i], 0, translateBitcode, (void*)info.mBitcode.c_str());
- }
-
- for (unsigned count = 0; count < thread_i; ++count) {
- pthread_join(tid[count], 0);
- }
- }
-
- // Compile
- for (std::vector<BitcodeInfoTy>::const_iterator i = bc_infos.begin(),
- e = bc_infos.end(); i < e; i += NUM_THREADS) {
- unsigned thread_i;
- for (thread_i = 0; thread_i < NUM_THREADS; ++thread_i) {
- if (i + thread_i == e) {
- break;
- }
- const BitcodeInfoTy &info = *(i + thread_i);
- pthread_create(&tid[thread_i], 0, compileBitcode, (void*)info.mBitcode.c_str());
- }
-
- for (unsigned count = 0; count < thread_i; ++count) {
- pthread_join(tid[count], 0);
- }
- }
-
- // Only linking needs sequential
- // Remove external ldlibs for topological traverse (linking order)
- removeExternalLDLibs(soname_map);
-
- while (!soname_map.empty()) {
- SONameMapTy::iterator i = soname_map.begin(), e = soname_map.end();
- for (; i != e; ++i) {
- BitcodeInfoTy &info = i->second;
-
- if (info.mLDLibs.empty()) {
- // No internal dependency for this bitcode
- LOGI("Process bitcode: %s -> %s", info.mBitcode.c_str(), info.mSOName.c_str());
- prepareRuntime(info);
- ret = linkBitcode(info);
- if (ret != 0) {
- LOGE("Process bitcode failed on %s!", info.mBitcode.c_str());
- }
-
- soname_map.erase(i);
- removeExternalLDLibs(soname_map);
- break;
- }
- }
-
- if (i == e) {
- LOGE("Failed to compute linking order: Internal cyclic dependency!");
- return 1;
- }
- }
-
- return ret; //unused
-}
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-JNIEXPORT jint JNICALL
-Java_compiler_abcc_AbccService_genLibs(JNIEnv *env, jobject thiz,
- jstring j_lib_dir, jstring j_sysroot) {
- lib_dir = env->GetStringUTFChars(j_lib_dir, 0);
- LOGI("Working directory: %s", lib_dir);
-
- sysroot = env->GetStringUTFChars(j_sysroot, 0);
- LOGI("Sysroot: %s", sysroot);
-
- handleTask(std::string("rm -f ") + lib_dir + "/compile_error");
-#if VERBOSE
- Timer t; t.start();
-#endif
- genLibs(lib_dir, sysroot);
-#if VERBOSE
- long long elapsed_msec = (t.stop() + 500) / 1000;
- LOGV("Elapsed time: %lld.%03ds", elapsed_msec/1000, (int)elapsed_msec%1000);
-#endif
- handleTask(std::string("cp -p ") + sysroot + "/usr/lib/libgabi++_shared.so " + lib_dir + "/libgabi++_shared.so");
-
- handleTask(std::string("rm -f ") + lib_dir + "/compile_log");
- 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");
- 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");
- return 56;
- }
-}
-
-#ifdef __cplusplus
-} // extern "C"
-#endif
diff --git a/tests/run-tests.sh b/tests/run-tests.sh
index 278ec21..67d97ae 100755
--- a/tests/run-tests.sh
+++ b/tests/run-tests.sh
@@ -792,7 +792,7 @@
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
+ cd $BUILD_DIR/`basename $TEST`/libs && cp -a $ABI $CPU_ABI
fi
SRCDIR="$BUILD_DIR/`basename $TEST`/libs/$CPU_ABI"
if [ ! -d "$SRCDIR" ] || [ -z "`ls $SRCDIR`" ]; then
diff --git a/toolchains/llvm-3.3/setup-common.mk b/toolchains/llvm-3.3/setup-common.mk
index 79c2ec1..6126d5f 100644
--- a/toolchains/llvm-3.3/setup-common.mk
+++ b/toolchains/llvm-3.3/setup-common.mk
@@ -28,7 +28,12 @@
# Compiler runtime is determined in bc2native
TARGET_LIBGCC :=
+# Only use integrated binary if existed. Otherwise, use python version
+ifeq (,$(wildcard $(TOOLCHAIN_PREBUILT_ROOT)/bin/ndk-bc2native))
BC2NATIVE := $(HOST_PYTHON) $(TOOLCHAIN_PREBUILT_ROOT)/bin/ndk-bc2native.py
+else
+BC2NATIVE := $(TOOLCHAIN_PREBUILT_ROOT)/bin/ndk-bc2native$(HOST_EXEEXT)
+endif
TARGET_CFLAGS := \
-target $(LLVM_TRIPLE) \