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