blob: ee19bb242286edb2f93bcd6f91d7b72230795d88 [file] [log] [blame]
Yaron Kerenbfc481b2015-07-07 15:10:47 +00001//===--- MinGWToolChain.cpp - MinGWToolChain Implementation ---------------===//
Yaron Keren1c0070c2015-07-02 04:45:27 +00002//
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
17using namespace clang::diag;
18using namespace clang::driver;
19using namespace clang::driver::toolchains;
20using namespace clang;
21using namespace llvm::opt;
22
23MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, const ArgList &Args)
24 : ToolChain(D, Triple, Args) {
25 getProgramPaths().push_back(getDriver().getInstalledDir());
26
Yaron Keren88e69e42015-07-14 15:02:09 +000027 llvm::SmallString<1024> LibDir;
28
Yaron Keren658df8b2015-07-20 06:38:39 +000029 // In Windows there aren't any standard install locations, we search
Yaron Keren7d4db6b2015-07-20 10:20:57 +000030 // for gcc on the PATH. In Linux the base is always /usr.
Yaron Keren88e69e42015-07-14 15:02:09 +000031#ifdef LLVM_ON_WIN32
Yaron Keren1c0070c2015-07-02 04:45:27 +000032 if (getDriver().SysRoot.size())
33 Base = getDriver().SysRoot;
34 else if (llvm::ErrorOr<std::string> GPPName =
35 llvm::sys::findProgramByName("gcc"))
36 Base = llvm::sys::path::parent_path(
37 llvm::sys::path::parent_path(GPPName.get()));
38 else
39 Base = llvm::sys::path::parent_path(getDriver().getInstalledDir());
40 Base += llvm::sys::path::get_separator();
Yaron Keren88e69e42015-07-14 15:02:09 +000041#else
42 if (getDriver().SysRoot.size())
43 Base = getDriver().SysRoot;
44 else
45 Base = "/usr/";
Yaron Keren88e69e42015-07-14 15:02:09 +000046#endif
47
Yaron Keren658df8b2015-07-20 06:38:39 +000048 // By default Arch is for mingw-w64.
49 Arch = (getTriple().getArchName() + "-w64-mingw32").str();
50 // lib: Arch Linux, Ubuntu, Windows
51 // lib64: openSUSE Linux
Yaron Keren0050b482015-07-20 12:40:25 +000052 for (StringRef Lib : {"lib", "lib64"}) {
Yaron Keren658df8b2015-07-20 06:38:39 +000053 LibDir = Base;
54 llvm::sys::path::append(LibDir, Lib, "gcc");
55 LibDir += llvm::sys::path::get_separator();
56 std::error_code EC;
57 // First look for mingw-w64.
58 llvm::sys::fs::directory_iterator MingW64Entry(LibDir + Arch, EC);
59 if (!EC) {
60 GccLibDir = MingW64Entry->path();
61 Ver = llvm::sys::path::filename(GccLibDir);
62 break;
63 }
Yaron Keren1c0070c2015-07-02 04:45:27 +000064 // If mingw-w64 not found, try looking for mingw.org.
Yaron Keren658df8b2015-07-20 06:38:39 +000065 llvm::sys::fs::directory_iterator MingwOrgEntry(LibDir + "mingw32", EC);
66 if (!EC) {
Yaron Keren1c0070c2015-07-02 04:45:27 +000067 GccLibDir = MingwOrgEntry->path();
Yaron Keren658df8b2015-07-20 06:38:39 +000068 // Replace Arch with mingw32 arch.
69 Arch = "mingw32";
70 break;
71 }
Yaron Keren1c0070c2015-07-02 04:45:27 +000072 }
Yaron Keren658df8b2015-07-20 06:38:39 +000073
Yaron Keren1c0070c2015-07-02 04:45:27 +000074 Arch += llvm::sys::path::get_separator();
75 // GccLibDir must precede Base/lib so that the
76 // correct crtbegin.o ,cetend.o would be found.
77 getFilePaths().push_back(GccLibDir);
Yaron Keren1c0070c2015-07-02 04:45:27 +000078 getFilePaths().push_back(Base + Arch + "lib");
Yaron Keren658df8b2015-07-20 06:38:39 +000079#ifdef LLVM_ON_WIN32
80 getFilePaths().push_back(Base + "lib");
81#else
82 // openSUSE
Yaron Keren88e69e42015-07-14 15:02:09 +000083 getFilePaths().push_back(Base + Arch + "sys-root/mingw/lib");
84#endif
Yaron Keren1c0070c2015-07-02 04:45:27 +000085}
86
87bool MinGW::IsIntegratedAssemblerDefault() const { return true; }
88
89Tool *MinGW::getTool(Action::ActionClass AC) const {
90 switch (AC) {
91 case Action::PreprocessJobClass:
92 if (!Preprocessor)
93 Preprocessor.reset(new tools::gcc::Preprocessor(*this));
94 return Preprocessor.get();
95 case Action::CompileJobClass:
96 if (!Compiler)
97 Compiler.reset(new tools::gcc::Compiler(*this));
98 return Compiler.get();
99 default:
100 return ToolChain::getTool(AC);
101 }
102}
103
104Tool *MinGW::buildAssembler() const {
105 return new tools::MinGW::Assembler(*this);
106}
107
108Tool *MinGW::buildLinker() const { return new tools::MinGW::Linker(*this); }
109
110bool MinGW::IsUnwindTablesDefault() const {
111 return getArch() == llvm::Triple::x86_64;
112}
113
114bool MinGW::isPICDefault() const { return getArch() == llvm::Triple::x86_64; }
115
116bool MinGW::isPIEDefault() const { return false; }
117
118bool MinGW::isPICDefaultForced() const {
119 return getArch() == llvm::Triple::x86_64;
120}
121
122bool MinGW::UseSEHExceptions() const {
123 return getArch() == llvm::Triple::x86_64;
124}
125
126void MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs,
127 ArgStringList &CC1Args) const {
128 if (DriverArgs.hasArg(options::OPT_nostdinc))
129 return;
130
131 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) {
132 SmallString<1024> P(getDriver().ResourceDir);
133 llvm::sys::path::append(P, "include");
134 addSystemInclude(DriverArgs, CC1Args, P.str());
135 }
136
137 if (DriverArgs.hasArg(options::OPT_nostdlibinc))
138 return;
139
140 llvm::SmallString<1024> IncludeDir(GccLibDir);
141 llvm::sys::path::append(IncludeDir, "include");
142 addSystemInclude(DriverArgs, CC1Args, IncludeDir.c_str());
143 IncludeDir += "-fixed";
Yaron Keren88e69e42015-07-14 15:02:09 +0000144#ifdef LLVM_ON_UNIX
Yaron Keren658df8b2015-07-20 06:38:39 +0000145 // openSUSE
Yaron Keren88e69e42015-07-14 15:02:09 +0000146 addSystemInclude(DriverArgs, CC1Args,
147 "/usr/x86_64-w64-mingw32/sys-root/mingw/include");
148#endif
Yaron Keren1c0070c2015-07-02 04:45:27 +0000149 addSystemInclude(DriverArgs, CC1Args, IncludeDir.c_str());
150 addSystemInclude(DriverArgs, CC1Args, Base + Arch + "include");
151 addSystemInclude(DriverArgs, CC1Args, Base + "include");
152}
153
154void MinGW::AddClangCXXStdlibIncludeArgs(const ArgList &DriverArgs,
155 ArgStringList &CC1Args) const {
156 if (DriverArgs.hasArg(options::OPT_nostdlibinc) ||
157 DriverArgs.hasArg(options::OPT_nostdincxx))
158 return;
159
Yaron Keren658df8b2015-07-20 06:38:39 +0000160 // C++ includes locations are different with almost every mingw distribution.
161 //
Yaron Keren88e69e42015-07-14 15:02:09 +0000162 // Windows
163 // -------
Yaron Keren658df8b2015-07-20 06:38:39 +0000164 // mingw-w64 mingw-builds: $sysroot/i686-w64-mingw32/include/c++
Yaron Keren763a38a2015-07-06 07:40:10 +0000165 // mingw-w64 msys2: $sysroot/include/c++/4.9.2
166 // mingw.org: GccLibDir/include/c++
Yaron Keren88e69e42015-07-14 15:02:09 +0000167 //
168 // Linux
169 // -----
170 // openSUSE: GccLibDir/include/c++
Yaron Keren658df8b2015-07-20 06:38:39 +0000171 // Arch: $sysroot/i686-w64-mingw32/include/c++/5.1.0
172 //
173 llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases;
Yaron Keren763a38a2015-07-06 07:40:10 +0000174 CppIncludeBases.emplace_back(Base);
175 llvm::sys::path::append(CppIncludeBases[0], Arch, "include", "c++");
176 CppIncludeBases.emplace_back(Base);
Yaron Keren658df8b2015-07-20 06:38:39 +0000177 llvm::sys::path::append(CppIncludeBases[1], Arch, "include", "c++", Ver);
178 CppIncludeBases.emplace_back(Base);
179 llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver);
Yaron Keren763a38a2015-07-06 07:40:10 +0000180 CppIncludeBases.emplace_back(GccLibDir);
Yaron Keren658df8b2015-07-20 06:38:39 +0000181 llvm::sys::path::append(CppIncludeBases[3], "include", "c++");
Yaron Keren763a38a2015-07-06 07:40:10 +0000182 for (auto &CppIncludeBase : CppIncludeBases) {
183 CppIncludeBase += llvm::sys::path::get_separator();
184 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase);
185 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch);
186 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward");
Yaron Keren1c0070c2015-07-02 04:45:27 +0000187 }
188}