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