/* * 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 #include #include #include #include #if ENABLE_PARALLEL_LLVM_CG #include #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, false/*!savetemps*/) {} 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 bc_files,lib_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. Add to deletion list. lib_files.push_back(full_path); 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); int magic = BitcodeInfo::transferBytesToNumLe(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()); bc_files.push_back(full_path); } // while closedir(dp); if (bc_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; } // Reomve lib file for (std::vector::const_iterator i = lib_files.begin(), e = lib_files.end(); i != e; ++i) { std::string cmd = "rm -f " + *i; runCmd(cmd.c_str()); } for (std::vector::const_iterator i = bc_files.begin(), e = bc_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/libgccunwind.a"; cmd += " -ldl"; mExecutableToolsPath[(unsigned)CMD_LINK_RUNTIME] = cmd; } void DeviceBitcodeCompiler::copyRuntime(const BitcodeInfo &info) { 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); }