MinGWToolChain.cpp 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. //===--- MinGWToolChain.cpp - MinGWToolChain Implementation ---------------===//
  2. //
  3. // The LLVM Compiler Infrastructure
  4. //
  5. // This file is distributed under the University of Illinois Open Source
  6. // License. See LICENSE.TXT for details.
  7. //
  8. //===----------------------------------------------------------------------===//
  9. #include "ToolChains.h"
  10. #include "clang/Driver/Driver.h"
  11. #include "clang/Driver/Options.h"
  12. #include "llvm/Option/ArgList.h"
  13. #include "llvm/Support/FileSystem.h"
  14. #include "llvm/Support/Path.h"
  15. using namespace clang::diag;
  16. using namespace clang::driver;
  17. using namespace clang::driver::toolchains;
  18. using namespace clang;
  19. using namespace llvm::opt;
  20. namespace {
  21. // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple.
  22. bool findGccVersion(StringRef LibDir, std::string &GccLibDir,
  23. std::string &Ver) {
  24. Generic_GCC::GCCVersion Version = Generic_GCC::GCCVersion::Parse("0.0.0");
  25. std::error_code EC;
  26. for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE;
  27. LI = LI.increment(EC)) {
  28. StringRef VersionText = llvm::sys::path::filename(LI->path());
  29. Generic_GCC::GCCVersion CandidateVersion =
  30. Generic_GCC::GCCVersion::Parse(VersionText);
  31. if (CandidateVersion.Major == -1)
  32. continue;
  33. if (CandidateVersion <= Version)
  34. continue;
  35. Ver = VersionText;
  36. GccLibDir = LI->path();
  37. }
  38. return Ver.size();
  39. }
  40. }
  41. void MinGW::findGccLibDir() {
  42. llvm::SmallVector<llvm::SmallString<32>, 2> Archs;
  43. Archs.emplace_back(getTriple().getArchName());
  44. Archs[0] += "-w64-mingw32";
  45. Archs.emplace_back("mingw32");
  46. Arch = Archs[0].str();
  47. // lib: Arch Linux, Ubuntu, Windows
  48. // lib64: openSUSE Linux
  49. for (StringRef CandidateLib : {"lib", "lib64"}) {
  50. for (StringRef CandidateArch : Archs) {
  51. llvm::SmallString<1024> LibDir(Base);
  52. llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateArch);
  53. if (findGccVersion(LibDir, GccLibDir, Ver)) {
  54. Arch = CandidateArch;
  55. return;
  56. }
  57. }
  58. }
  59. }
  60. MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
  61. : ToolChain(D, Triple, Args) {
  62. getProgramPaths().push_back(getDriver().getInstalledDir());
  63. // In Windows there aren't any standard install locations, we search
  64. // for gcc on the PATH. In Linux the base is always /usr.
  65. #ifdef LLVM_ON_WIN32
  66. if (getDriver().SysRoot.size())
  67. Base = getDriver().SysRoot;
  68. else if (llvm::ErrorOr<std::string> GPPName =
  69. llvm::sys::findProgramByName("gcc"))
  70. Base = llvm::sys::path::parent_path(
  71. llvm::sys::path::parent_path(GPPName.get()));
  72. else
  73. Base = llvm::sys::path::parent_path(getDriver().getInstalledDir());
  74. #else
  75. if (getDriver().SysRoot.size())
  76. Base = getDriver().SysRoot;
  77. else
  78. Base = "/usr";
  79. #endif
  80. Base += llvm::sys::path::get_separator();
  81. findGccLibDir();
  82. // GccLibDir must precede Base/lib so that the
  83. // correct crtbegin.o ,cetend.o would be found.
  84. getFilePaths().push_back(GccLibDir);
  85. getFilePaths().push_back(
  86. (Base + Arch + llvm::sys::path::get_separator() + "lib").str());
  87. getFilePaths().push_back(Base + "lib");
  88. // openSUSE
  89. getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib");
  90. }
  91. bool MinGW::IsIntegratedAssemblerDefault() const { return true; }
  92. Tool *MinGW::getTool(Action::ActionClass AC) const {
  93. switch (AC) {
  94. case Action::PreprocessJobClass:
  95. if (!Preprocessor)
  96. Preprocessor.reset(new tools::gcc::Preprocessor(*this));
  97. return Preprocessor.get();
  98. case Action::CompileJobClass:
  99. if (!Compiler)
  100. Compiler.reset(new tools::gcc::Compiler(*this));
  101. return Compiler.get();
  102. default:
  103. return ToolChain::getTool(AC);
  104. }
  105. }
  106. Tool *MinGW::buildAssembler() const {
  107. return new tools::MinGW::Assembler(*this);
  108. }
  109. Tool *MinGW::buildLinker() const { return new tools::MinGW::Linker(*this); }
  110. bool MinGW::IsUnwindTablesDefault() const {
  111. return getArch() == llvm::Triple::x86_64;
  112. }
  113. bool MinGW::isPICDefault() const { return getArch() == llvm::Triple::x86_64; }
  114. bool MinGW::isPIEDefault() const { return false; }
  115. bool MinGW::isPICDefaultForced() const {
  116. return getArch() == llvm::Triple::x86_64;
  117. }
  118. bool MinGW::UseSEHExceptions() const {
  119. return getArch() == llvm::Triple::x86_64;
  120. }
  121. // Include directories for various hosts:
  122. // Windows, mingw.org
  123. // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++
  124. // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32
  125. // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward
  126. // c:\mingw\lib\gcc\mingw32\4.8.1\include
  127. // c:\mingw\include
  128. // c:\mingw\lib\gcc\mingw32\4.8.1\include-fixed
  129. // c:\mingw\mingw32\include
  130. // Windows, mingw-w64 mingw-builds
  131. // c:\mingw32\lib\gcc\i686-w64-mingw32\4.9.1\include
  132. // c:\mingw32\lib\gcc\i686-w64-mingw32\4.9.1\include-fixed
  133. // c:\mingw32\i686-w64-mingw32\include
  134. // c:\mingw32\i686-w64-mingw32\include\c++
  135. // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32
  136. // c:\mingw32\i686-w64-mingw32\include\c++\backward
  137. // Windows, mingw-w64 msys2
  138. // c:\msys64\mingw32\lib\gcc\i686-w64-mingw32\4.9.2\include
  139. // c:\msys64\mingw32\include
  140. // c:\msys64\mingw32\lib\gcc\i686-w64-mingw32\4.9.2\include-fixed
  141. // c:\msys64\mingw32\i686-w64-mingw32\include
  142. // c:\msys64\mingw32\include\c++\4.9.2
  143. // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32
  144. // c:\msys64\mingw32\include\c++\4.9.2\backward
  145. // openSUSE
  146. // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++
  147. // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32
  148. // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward
  149. // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include
  150. // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include-fixed
  151. // /usr/x86_64-w64-mingw32/sys-root/mingw/include
  152. // Arch Linux
  153. // /usr/i686-w64-mingw32/include/c++/5.1.0
  154. // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32
  155. // /usr/i686-w64-mingw32/include/c++/5.1.0/backward
  156. // /usr/lib/gcc/i686-w64-mingw32/5.1.0/include
  157. // /usr/lib/gcc/i686-w64-mingw32/5.1.0/include-fixed
  158. // /usr/i686-w64-mingw32/include
  159. // Ubuntu
  160. // /usr/include/c++/4.8
  161. // /usr/include/c++/4.8/x86_64-w64-mingw32
  162. // /usr/include/c++/4.8/backward
  163. // /usr/lib/gcc/x86_64-w64-mingw32/4.8/include
  164. // /usr/lib/gcc/x86_64-w64-mingw32/4.8/include-fixed
  165. // /usr/x86_64-w64-mingw32/include
  166. void MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
  167. ArgStringList &CC1Args) const {
  168. if (DriverArgs.hasArg(options::OPT_nostdinc))
  169. return;
  170. if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
  171. SmallString<1024> P(getDriver().ResourceDir);
  172. llvm::sys::path::append(P, "include");
  173. addSystemInclude(DriverArgs, CC1Args, P.str());
  174. }
  175. if (DriverArgs.hasArg(options::OPT_nostdlibinc))
  176. return;
  177. if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) {
  178. llvm::SmallString<1024> IncludeDir(GccLibDir);
  179. llvm::sys::path::append(IncludeDir, "include");
  180. addSystemInclude(DriverArgs, CC1Args, IncludeDir.c_str());
  181. IncludeDir += "-fixed";
  182. // openSUSE
  183. addSystemInclude(DriverArgs, CC1Args,
  184. Base + Arch + "/sys-root/mingw/include");
  185. addSystemInclude(DriverArgs, CC1Args, IncludeDir.c_str());
  186. }
  187. addSystemInclude(DriverArgs, CC1Args,
  188. Base + Arch + llvm::sys::path::get_separator() + "include");
  189. addSystemInclude(DriverArgs, CC1Args, Base + "include");
  190. }
  191. void MinGW::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
  192. ArgStringList &CC1Args) const {
  193. if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
  194. DriverArgs.hasArg(options::OPT_nostdincxx))
  195. return;
  196. switch (GetCXXStdlibType(DriverArgs)) {
  197. case ToolChain::CST_Libcxx:
  198. addSystemInclude(DriverArgs, CC1Args,
  199. Base + "include" + llvm::sys::path::get_separator() +
  200. "c++" + llvm::sys::path::get_separator() + "v1");
  201. break;
  202. case ToolChain::CST_Libstdcxx:
  203. llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases;
  204. CppIncludeBases.emplace_back(Base);
  205. llvm::sys::path::append(CppIncludeBases[0], Arch, "include", "c++");
  206. CppIncludeBases.emplace_back(Base);
  207. llvm::sys::path::append(CppIncludeBases[1], Arch, "include", "c++", Ver);
  208. CppIncludeBases.emplace_back(Base);
  209. llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver);
  210. CppIncludeBases.emplace_back(GccLibDir);
  211. llvm::sys::path::append(CppIncludeBases[3], "include", "c++");
  212. for (auto &CppIncludeBase : CppIncludeBases) {
  213. addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
  214. CppIncludeBase += llvm::sys::path::get_separator();
  215. addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch);
  216. addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward");
  217. }
  218. break;
  219. }
  220. }