Home | History | Annotate | Download | only in host
      1 /*
      2  * Copyright 2013, The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *     http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <sstream>
     18 #include "Abcc_host.h"
     19 using namespace abcc;
     20 
     21 bool kVerbose = false;
     22 
     23 HostBitcodeCompiler::HostBitcodeCompiler(const std::string &abi, const std::string &sysroot, const std::string &toolchain_bin,
     24                                          const std::string &input, const std::string &output, const std::string &working_dir,
     25                                          const std::string &platform, const bool savetemps, bool bit32)
     26   : BitcodeCompiler(abi, sysroot, working_dir, savetemps), mIn(input), mOut(output),
     27     mNDKDir(""), mPlatform(platform), mToolchainBinPath(toolchain_bin) {
     28   initRuntimePath();
     29 }
     30 
     31 HostBitcodeCompiler::HostBitcodeCompiler(const std::string &abi, const std::string &sysroot, const std::string &ndk_dir, const std::string &toolchain_bin,
     32                                          const std::string &input, const std::string &output, const std::string &working_dir,
     33                                          const std::string &platform, const bool savetemps, bool bit32)
     34   : BitcodeCompiler(abi, sysroot, working_dir, savetemps), mIn(input), mOut(output),
     35     mNDKDir(ndk_dir), mPlatform(platform), mToolchainBinPath(toolchain_bin) {
     36   initRuntimePath();
     37 }
     38 
     39 void HostBitcodeCompiler::initRuntimePath() {
     40   mRuntimePath.clear();
     41 
     42   mRuntimePath.insert(std::make_pair("gabi++_static", getGAbixxPath() + "/libgabi++_static.a"));
     43   mRuntimePath.insert(std::make_pair("gabi++_shared", getGAbixxPath() + "/libgabi++_shared.so"));
     44   mRuntimePath.insert(std::make_pair("compiler_rt_static", getCompilerRTPath() + "/libcompiler_rt_static.a"));
     45   mRuntimePath.insert(std::make_pair("portable", getLibPortablePath() + "/libportable.a"));
     46   mRuntimePath.insert(std::make_pair("portable.wrap", getLibPortablePath() + "/libportable.wrap"));
     47   mRuntimePath.insert(std::make_pair("gccunwind", getGCCUnwindPath() + "/libgccunwind.a"));
     48 }
     49 
     50 const std::string HostBitcodeCompiler::getRuntimePath(const std::string &libname) {
     51   if (mRuntimePath.count(libname)) {
     52     return mRuntimePath.find(libname)->second;
     53   }
     54   return "";
     55 }
     56 
     57 int HostBitcodeCompiler::parseLDFlags(BitcodeInfo &info, const std::string &orig_str) {
     58   // Follow traditional clang/gcc use, add -lgccunwind (-lgcc) before local libs
     59   info.mLDLocalLibsStr += " " + getRuntimePath("gccunwind");
     60 
     61   std::stringstream ss(orig_str);
     62   std::string str;
     63   while (ss >> str) {
     64     if (str.find("--sysroot") != std::string::npos) {
     65       continue;
     66     }
     67     if (str == "-o") {
     68       ss >> str;
     69       continue;
     70     }
     71     if (str == "-soname") {
     72       ss >> str;
     73       info.mSOName = str;
     74       continue;
     75     }
     76     if (str == "-shared") {
     77       info.mShared = true;
     78       info.mOutPath += ".so";
     79       continue;
     80     }
     81 
     82     if (str.size() > 2 &&
     83         str.substr(str.size() - 2) == ".a") {
     84       if (str.size() > 6 &&
     85           str.substr(0, /*leng*/6) == "./obj/") {
     86         info.mLDLocalLibsStr += " " + str;
     87       } else {
     88         info.mLDLibs.push_back(str);
     89         info.mLDLibsStr += " " + str;
     90       }
     91       continue;
     92     }
     93     if (str.size() > 3 &&
     94         str.substr(str.size() - 3) == ".so") {
     95       if (str.size() > 6 &&
     96           str.substr(0, /*leng*/6) == "./obj/") {
     97         info.mLDLocalLibsStr += " " + str;
     98       } else {
     99         info.mLDLibs.push_back(str);
    100         info.mLDLibsStr += " " + str;
    101       }
    102       continue;
    103     }
    104 
    105     // Parse -lxxx
    106     if (str.size() > 2 &&
    107         str.substr(0, 2) == "-l") {
    108       std::string runtime_path = getRuntimePath(str.substr(2));
    109       if (!runtime_path.empty()) {
    110         info.mLDLibsStr += " " + runtime_path;
    111       }
    112       else {
    113         info.mLDLibs.push_back(str.substr(2));
    114         info.mLDLibsStr += " " + str;
    115       }
    116       continue;
    117     }
    118 
    119     // Some other flags, like --no-undefined, -z now, -z noexecstack, ...
    120     info.mLDFlags += str + " ";
    121   } // while
    122 
    123   size_t first_dash_l = info.mLDLibsStr.find(" -l");
    124   if (first_dash_l == 0u) {
    125     info.mLDLibsStr += " " + getRuntimePath("gccunwind");
    126   } else if (first_dash_l == std::string::npos) {
    127     info.mLDLibsStr = getRuntimePath("gccunwind") + info.mLDLibsStr;
    128   } else {
    129     info.mLDLibsStr = info.mLDLibsStr.substr(0, first_dash_l)
    130                       + " " + getRuntimePath("gccunwind")
    131                       + info.mLDLibsStr.substr(first_dash_l,
    132                                                info.mLDLibsStr.size() - first_dash_l);
    133   }
    134   return 0;
    135 }
    136 
    137 void HostBitcodeCompiler::getBitcodeFiles() {
    138   BitcodeInfo bcinfo(mIn);
    139   if (bcinfo.readWrapper(*this) != 0) {
    140     LOGE("Cannot read wrapper for bitcode %s", mIn.c_str());
    141     mRet = RET_FAIL_PREPARE_BITCODE;
    142     return;
    143   }
    144 
    145   bcinfo.mOutPath = mOut;
    146   mBitcodeFiles.push_back(bcinfo);
    147 }
    148 
    149 void HostBitcodeCompiler::prepareToolchain() {
    150   std::string cmd;
    151   // le32-none-ndk-translate
    152   if (mAbi == TargetAbi::ARM64_V8A || mAbi == TargetAbi::X86_64 ||
    153       mAbi == TargetAbi::MIPS64)
    154     cmd = getToolchainBinPath() + "/le64-none-ndk-translate";
    155   else
    156     cmd = getToolchainBinPath() + "/le32-none-ndk-translate";
    157   mExecutableToolsPath[(unsigned)CMD_TRANSLATE] = cmd;
    158 
    159   // llc
    160   cmd = getToolchainBinPath() + "/llc";
    161   mExecutableToolsPath[(unsigned)CMD_COMPILE] = cmd;
    162 
    163   // ld.mcld
    164   cmd = getToolchainBinPath() + "/ld.mcld";
    165   if (mAbi == TargetAbi::MIPS64) {
    166     cmd = getToolchainBinPath() + "/../../../../mips64el-linux-android-4.8/prebuilt/linux-x86/bin/mips64el-linux-android-ld";
    167   }
    168 
    169   if (mAbi == TargetAbi::X86_64) {
    170     cmd += " -L" + mSysroot + "/usr/lib64";
    171   } else {
    172     cmd += " -L" + mSysroot + "/usr/lib";
    173   }
    174   mExecutableToolsPath[(unsigned)CMD_LINK] = cmd;
    175 
    176   cmd = " @" + getRuntimePath("portable.wrap") + " " + getRuntimePath("portable");
    177   cmd += " " + getRuntimePath("compiler_rt_static");
    178   cmd += " " + getRuntimePath("gccunwind");
    179   cmd += " -ldl";
    180   mExecutableToolsPath[(unsigned)CMD_LINK_RUNTIME] = cmd;
    181 }
    182 
    183 void HostBitcodeCompiler::copyRuntime(const BitcodeInfo &info) {
    184 }
    185 
    186 void HostBitcodeCompiler::removeIntermediateFile(const std::string &path) {
    187   if (!kVerbose)
    188     runCmd(std::string("rm -f ") + path);
    189 }
    190 
    191 const std::string HostBitcodeCompiler::getToolchainBinPath() const {
    192   return mToolchainBinPath;
    193 }
    194 
    195 const std::string HostBitcodeCompiler::getCompilerRTPath() const {
    196   if (!mNDKDir.empty())
    197     return std::string(mNDKDir) + "/sources/android/compiler-rt/libs/" + (const char*)mAbi;
    198   else
    199     return mSysroot + "/usr/lib";
    200 }
    201 
    202 const std::string HostBitcodeCompiler::getGAbixxPath() const {
    203   if (!mNDKDir.empty())
    204     return std::string(mNDKDir) + "/sources/cxx-stl/gabi++/libs/" + (const char*)mAbi;
    205   else
    206     return mSysroot + "/usr/lib";
    207 }
    208 
    209 const std::string HostBitcodeCompiler::getLibPortablePath() const {
    210   if (!mNDKDir.empty())
    211     return std::string(mNDKDir) + "/sources/android/libportable/libs/" + (const char*)mAbi;
    212   else
    213     return mSysroot + "/usr/lib";
    214 }
    215 
    216 const std::string HostBitcodeCompiler::getGCCUnwindPath() const {
    217   if (!mNDKDir.empty())
    218     return std::string(mNDKDir) + "/sources/android/gccunwind/libs/" + (const char*)mAbi;
    219   else
    220     return mSysroot + "/usr/lib";
    221 }
    222