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