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