1 //===--- MinGW.cpp - MinGWToolChain Implementation ------------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #include "CommonArgs.h"
11 #include "clang/Config/config.h"
12 #include "clang/Driver/Compilation.h"
13 #include "clang/Driver/Driver.h"
14 #include "clang/Driver/DriverDiagnostic.h"
15 #include "clang/Driver/InputInfo.h"
16 #include "clang/Driver/Options.h"
17 #include "clang/Driver/SanitizerArgs.h"
18 #include "llvm/Option/ArgList.h"
19 #include "llvm/Support/FileSystem.h"
20 #include "llvm/Support/Path.h"
21 #include "llvm/Support/VirtualFileSystem.h"
22 #include <system_error>
24 using namespace clang::diag
;
25 using namespace clang::driver
;
26 using namespace clang
;
27 using namespace llvm::opt
;
30 void tools::MinGW::Assembler::ConstructJob(Compilation
&C
, const JobAction
&JA
,
31 const InputInfo
&Output
,
32 const InputInfoList
&Inputs
,
34 const char *LinkingOutput
) const {
35 claimNoWarnArgs(Args
);
36 ArgStringList CmdArgs
;
38 if (getToolChain().getArch() == llvm::Triple::x86
) {
39 CmdArgs
.push_back("--32");
40 } else if (getToolChain().getArch() == llvm::Triple::x86_64
) {
41 CmdArgs
.push_back("--64");
44 Args
.AddAllArgValues(CmdArgs
, options::OPT_Wa_COMMA
, options::OPT_Xassembler
);
46 CmdArgs
.push_back("-o");
47 CmdArgs
.push_back(Output
.getFilename());
49 for (const auto &II
: Inputs
)
50 CmdArgs
.push_back(II
.getFilename());
52 const char *Exec
= Args
.MakeArgString(getToolChain().GetProgramPath("as"));
53 C
.addCommand(std::make_unique
<Command
>(JA
, *this, ResponseFileSupport::None(),
54 Exec
, CmdArgs
, Inputs
, Output
));
56 if (Args
.hasArg(options::OPT_gsplit_dwarf
))
57 SplitDebugInfo(getToolChain(), C
, *this, JA
, Args
, Output
,
58 SplitDebugName(JA
, Args
, Inputs
[0], Output
));
61 void tools::MinGW::Linker::AddLibGCC(const ArgList
&Args
,
62 ArgStringList
&CmdArgs
) const {
63 if (Args
.hasArg(options::OPT_mthreads
))
64 CmdArgs
.push_back("-lmingwthrd");
65 CmdArgs
.push_back("-lmingw32");
67 // Make use of compiler-rt if --rtlib option is used
68 ToolChain::RuntimeLibType RLT
= getToolChain().GetRuntimeLibType(Args
);
69 if (RLT
== ToolChain::RLT_Libgcc
) {
70 bool Static
= Args
.hasArg(options::OPT_static_libgcc
) ||
71 Args
.hasArg(options::OPT_static
);
72 bool Shared
= Args
.hasArg(options::OPT_shared
);
73 bool CXX
= getToolChain().getDriver().CCCIsCXX();
75 if (Static
|| (!CXX
&& !Shared
)) {
76 CmdArgs
.push_back("-lgcc");
77 CmdArgs
.push_back("-lgcc_eh");
79 CmdArgs
.push_back("-lgcc_s");
80 CmdArgs
.push_back("-lgcc");
83 AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs
, Args
);
86 CmdArgs
.push_back("-lmoldname");
87 CmdArgs
.push_back("-lmingwex");
88 for (auto Lib
: Args
.getAllArgValues(options::OPT_l
))
89 if (StringRef(Lib
).startswith("msvcr") ||
90 StringRef(Lib
).startswith("ucrt") ||
91 StringRef(Lib
).startswith("crtdll"))
93 CmdArgs
.push_back("-lmsvcrt");
96 void tools::MinGW::Linker::ConstructJob(Compilation
&C
, const JobAction
&JA
,
97 const InputInfo
&Output
,
98 const InputInfoList
&Inputs
,
100 const char *LinkingOutput
) const {
101 const ToolChain
&TC
= getToolChain();
102 const Driver
&D
= TC
.getDriver();
103 const SanitizerArgs
&Sanitize
= TC
.getSanitizerArgs(Args
);
105 ArgStringList CmdArgs
;
107 // Silence warning for "clang -g foo.o -o foo"
108 Args
.ClaimAllArgs(options::OPT_g_Group
);
109 // and "clang -emit-llvm foo.o -o foo"
110 Args
.ClaimAllArgs(options::OPT_emit_llvm
);
111 // and for "clang -w foo.o -o foo". Other warning options are already
112 // handled somewhere else.
113 Args
.ClaimAllArgs(options::OPT_w
);
115 if (!D
.SysRoot
.empty())
116 CmdArgs
.push_back(Args
.MakeArgString("--sysroot=" + D
.SysRoot
));
118 if (Args
.hasArg(options::OPT_s
))
119 CmdArgs
.push_back("-s");
121 CmdArgs
.push_back("-m");
122 switch (TC
.getArch()) {
123 case llvm::Triple::x86
:
124 CmdArgs
.push_back("i386pe");
126 case llvm::Triple::x86_64
:
127 CmdArgs
.push_back("i386pep");
129 case llvm::Triple::arm
:
130 case llvm::Triple::thumb
:
131 // FIXME: this is incorrect for WinCE
132 CmdArgs
.push_back("thumb2pe");
134 case llvm::Triple::aarch64
:
135 CmdArgs
.push_back("arm64pe");
138 llvm_unreachable("Unsupported target architecture.");
142 Args
.getLastArg(options::OPT_mwindows
, options::OPT_mconsole
);
143 if (SubsysArg
&& SubsysArg
->getOption().matches(options::OPT_mwindows
)) {
144 CmdArgs
.push_back("--subsystem");
145 CmdArgs
.push_back("windows");
146 } else if (SubsysArg
&&
147 SubsysArg
->getOption().matches(options::OPT_mconsole
)) {
148 CmdArgs
.push_back("--subsystem");
149 CmdArgs
.push_back("console");
152 if (Args
.hasArg(options::OPT_mdll
))
153 CmdArgs
.push_back("--dll");
154 else if (Args
.hasArg(options::OPT_shared
))
155 CmdArgs
.push_back("--shared");
156 if (Args
.hasArg(options::OPT_static
))
157 CmdArgs
.push_back("-Bstatic");
159 CmdArgs
.push_back("-Bdynamic");
160 if (Args
.hasArg(options::OPT_mdll
) || Args
.hasArg(options::OPT_shared
)) {
161 CmdArgs
.push_back("-e");
162 if (TC
.getArch() == llvm::Triple::x86
)
163 CmdArgs
.push_back("_DllMainCRTStartup@12");
165 CmdArgs
.push_back("DllMainCRTStartup");
166 CmdArgs
.push_back("--enable-auto-image-base");
169 if (Args
.hasArg(options::OPT_Z_Xlinker__no_demangle
))
170 CmdArgs
.push_back("--no-demangle");
172 if (Arg
*A
= Args
.getLastArg(options::OPT_mguard_EQ
)) {
173 StringRef GuardArgs
= A
->getValue();
174 if (GuardArgs
== "none")
175 CmdArgs
.push_back("--no-guard-cf");
176 else if (GuardArgs
== "cf" || GuardArgs
== "cf-nochecks")
177 CmdArgs
.push_back("--guard-cf");
179 D
.Diag(diag::err_drv_unsupported_option_argument
)
180 << A
->getSpelling() << GuardArgs
;
183 CmdArgs
.push_back("-o");
184 const char *OutputFile
= Output
.getFilename();
185 // GCC implicitly adds an .exe extension if it is given an output file name
186 // that lacks an extension.
187 // GCC used to do this only when the compiler itself runs on windows, but
188 // since GCC 8 it does the same when cross compiling as well.
189 if (!llvm::sys::path::has_extension(OutputFile
)) {
190 CmdArgs
.push_back(Args
.MakeArgString(Twine(OutputFile
) + ".exe"));
191 OutputFile
= CmdArgs
.back();
193 CmdArgs
.push_back(OutputFile
);
195 Args
.AddAllArgs(CmdArgs
, options::OPT_e
);
196 // FIXME: add -N, -n flags
197 Args
.AddLastArg(CmdArgs
, options::OPT_r
);
198 Args
.AddLastArg(CmdArgs
, options::OPT_s
);
199 Args
.AddLastArg(CmdArgs
, options::OPT_t
);
200 Args
.AddAllArgs(CmdArgs
, options::OPT_u_Group
);
201 Args
.AddLastArg(CmdArgs
, options::OPT_Z_Flag
);
203 if (!Args
.hasArg(options::OPT_nostdlib
, options::OPT_nostartfiles
)) {
204 if (Args
.hasArg(options::OPT_shared
) || Args
.hasArg(options::OPT_mdll
)) {
205 CmdArgs
.push_back(Args
.MakeArgString(TC
.GetFilePath("dllcrt2.o")));
207 if (Args
.hasArg(options::OPT_municode
))
208 CmdArgs
.push_back(Args
.MakeArgString(TC
.GetFilePath("crt2u.o")));
210 CmdArgs
.push_back(Args
.MakeArgString(TC
.GetFilePath("crt2.o")));
212 if (Args
.hasArg(options::OPT_pg
))
213 CmdArgs
.push_back(Args
.MakeArgString(TC
.GetFilePath("gcrt2.o")));
214 CmdArgs
.push_back(Args
.MakeArgString(TC
.GetFilePath("crtbegin.o")));
217 Args
.AddAllArgs(CmdArgs
, options::OPT_L
);
218 TC
.AddFilePathLibArgs(Args
, CmdArgs
);
220 // Add the compiler-rt library directories if they exist to help
221 // the linker find the various sanitizer, builtin, and profiling runtimes.
222 for (const auto &LibPath
: TC
.getLibraryPaths()) {
223 if (TC
.getVFS().exists(LibPath
))
224 CmdArgs
.push_back(Args
.MakeArgString("-L" + LibPath
));
226 auto CRTPath
= TC
.getCompilerRTPath();
227 if (TC
.getVFS().exists(CRTPath
))
228 CmdArgs
.push_back(Args
.MakeArgString("-L" + CRTPath
));
230 AddLinkerInputs(TC
, Inputs
, Args
, CmdArgs
, JA
);
232 if (C
.getDriver().IsFlangMode()) {
233 addFortranRuntimeLibraryPath(TC
, Args
, CmdArgs
);
234 addFortranRuntimeLibs(TC
, CmdArgs
);
237 // TODO: Add profile stuff here
239 if (TC
.ShouldLinkCXXStdlib(Args
)) {
240 bool OnlyLibstdcxxStatic
= Args
.hasArg(options::OPT_static_libstdcxx
) &&
241 !Args
.hasArg(options::OPT_static
);
242 if (OnlyLibstdcxxStatic
)
243 CmdArgs
.push_back("-Bstatic");
244 TC
.AddCXXStdlibLibArgs(Args
, CmdArgs
);
245 if (OnlyLibstdcxxStatic
)
246 CmdArgs
.push_back("-Bdynamic");
249 bool HasWindowsApp
= false;
250 for (auto Lib
: Args
.getAllArgValues(options::OPT_l
)) {
251 if (Lib
== "windowsapp") {
252 HasWindowsApp
= true;
257 if (!Args
.hasArg(options::OPT_nostdlib
)) {
258 if (!Args
.hasArg(options::OPT_nodefaultlibs
)) {
259 if (Args
.hasArg(options::OPT_static
))
260 CmdArgs
.push_back("--start-group");
262 if (Args
.hasArg(options::OPT_fstack_protector
) ||
263 Args
.hasArg(options::OPT_fstack_protector_strong
) ||
264 Args
.hasArg(options::OPT_fstack_protector_all
)) {
265 CmdArgs
.push_back("-lssp_nonshared");
266 CmdArgs
.push_back("-lssp");
269 if (Args
.hasFlag(options::OPT_fopenmp
, options::OPT_fopenmp_EQ
,
270 options::OPT_fno_openmp
, false)) {
271 switch (TC
.getDriver().getOpenMPRuntime(Args
)) {
272 case Driver::OMPRT_OMP
:
273 CmdArgs
.push_back("-lomp");
275 case Driver::OMPRT_IOMP5
:
276 CmdArgs
.push_back("-liomp5md");
278 case Driver::OMPRT_GOMP
:
279 CmdArgs
.push_back("-lgomp");
281 case Driver::OMPRT_Unknown
:
282 // Already diagnosed.
287 AddLibGCC(Args
, CmdArgs
);
289 if (Args
.hasArg(options::OPT_pg
))
290 CmdArgs
.push_back("-lgmon");
292 if (Args
.hasArg(options::OPT_pthread
))
293 CmdArgs
.push_back("-lpthread");
295 if (Sanitize
.needsAsanRt()) {
296 // MinGW always links against a shared MSVCRT.
297 CmdArgs
.push_back(TC
.getCompilerRTArgString(Args
, "asan_dynamic",
298 ToolChain::FT_Shared
));
300 TC
.getCompilerRTArgString(Args
, "asan_dynamic_runtime_thunk"));
301 CmdArgs
.push_back("--require-defined");
302 CmdArgs
.push_back(TC
.getArch() == llvm::Triple::x86
303 ? "___asan_seh_interceptor"
304 : "__asan_seh_interceptor");
305 // Make sure the linker consider all object files from the dynamic
307 CmdArgs
.push_back("--whole-archive");
309 TC
.getCompilerRTArgString(Args
, "asan_dynamic_runtime_thunk"));
310 CmdArgs
.push_back("--no-whole-archive");
313 TC
.addProfileRTLibs(Args
, CmdArgs
);
315 if (!HasWindowsApp
) {
316 // Add system libraries. If linking to libwindowsapp.a, that import
317 // library replaces all these and we shouldn't accidentally try to
318 // link to the normal desktop mode dlls.
319 if (Args
.hasArg(options::OPT_mwindows
)) {
320 CmdArgs
.push_back("-lgdi32");
321 CmdArgs
.push_back("-lcomdlg32");
323 CmdArgs
.push_back("-ladvapi32");
324 CmdArgs
.push_back("-lshell32");
325 CmdArgs
.push_back("-luser32");
326 CmdArgs
.push_back("-lkernel32");
329 if (Args
.hasArg(options::OPT_static
)) {
330 CmdArgs
.push_back("--end-group");
332 AddLibGCC(Args
, CmdArgs
);
334 CmdArgs
.push_back("-lkernel32");
338 if (!Args
.hasArg(options::OPT_nostartfiles
)) {
339 // Add crtfastmath.o if available and fast math is enabled.
340 TC
.addFastMathRuntimeIfAvailable(Args
, CmdArgs
);
342 CmdArgs
.push_back(Args
.MakeArgString(TC
.GetFilePath("crtend.o")));
345 const char *Exec
= Args
.MakeArgString(TC
.GetLinkerPath());
346 C
.addCommand(std::make_unique
<Command
>(JA
, *this,
347 ResponseFileSupport::AtFileUTF8(),
348 Exec
, CmdArgs
, Inputs
, Output
));
351 // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple.
352 static bool findGccVersion(StringRef LibDir
, std::string
&GccLibDir
,
354 toolchains::Generic_GCC::GCCVersion
&Version
) {
355 Version
= toolchains::Generic_GCC::GCCVersion::Parse("0.0.0");
357 for (llvm::sys::fs::directory_iterator
LI(LibDir
, EC
), LE
; !EC
&& LI
!= LE
;
358 LI
= LI
.increment(EC
)) {
359 StringRef VersionText
= llvm::sys::path::filename(LI
->path());
360 auto CandidateVersion
=
361 toolchains::Generic_GCC::GCCVersion::Parse(VersionText
);
362 if (CandidateVersion
.Major
== -1)
364 if (CandidateVersion
<= Version
)
366 Version
= CandidateVersion
;
367 Ver
= std::string(VersionText
);
368 GccLibDir
= LI
->path();
373 void toolchains::MinGW::findGccLibDir() {
374 llvm::SmallVector
<llvm::SmallString
<32>, 2> SubdirNames
;
375 SubdirNames
.emplace_back(getTriple().getArchName());
376 SubdirNames
[0] += "-w64-mingw32";
377 SubdirNames
.emplace_back("mingw32");
378 if (SubdirName
.empty())
379 SubdirName
= std::string(SubdirNames
[0].str());
380 // lib: Arch Linux, Ubuntu, Windows
381 // lib64: openSUSE Linux
382 for (StringRef CandidateLib
: {"lib", "lib64"}) {
383 for (StringRef CandidateSysroot
: SubdirNames
) {
384 llvm::SmallString
<1024> LibDir(Base
);
385 llvm::sys::path::append(LibDir
, CandidateLib
, "gcc", CandidateSysroot
);
386 if (findGccVersion(LibDir
, GccLibDir
, Ver
, GccVer
)) {
387 SubdirName
= std::string(CandidateSysroot
);
394 static llvm::ErrorOr
<std::string
> findGcc(const llvm::Triple
&T
) {
395 llvm::SmallVector
<llvm::SmallString
<32>, 2> Gccs
;
396 Gccs
.emplace_back(T
.getArchName());
397 Gccs
[0] += "-w64-mingw32-gcc";
398 Gccs
.emplace_back("mingw32-gcc");
399 // Please do not add "gcc" here
400 for (StringRef CandidateGcc
: Gccs
)
401 if (llvm::ErrorOr
<std::string
> GPPName
= llvm::sys::findProgramByName(CandidateGcc
))
403 return make_error_code(std::errc::no_such_file_or_directory
);
406 static llvm::ErrorOr
<std::string
>
407 findClangRelativeSysroot(const Driver
&D
, const llvm::Triple
&T
,
408 std::string
&SubdirName
) {
409 llvm::SmallVector
<llvm::SmallString
<32>, 2> Subdirs
;
410 Subdirs
.emplace_back(T
.str());
411 Subdirs
.emplace_back(T
.getArchName());
412 Subdirs
[1] += "-w64-mingw32";
413 StringRef ClangRoot
= llvm::sys::path::parent_path(D
.getInstalledDir());
414 StringRef Sep
= llvm::sys::path::get_separator();
415 for (StringRef CandidateSubdir
: Subdirs
) {
416 if (llvm::sys::fs::is_directory(ClangRoot
+ Sep
+ CandidateSubdir
)) {
417 SubdirName
= std::string(CandidateSubdir
);
418 return (ClangRoot
+ Sep
+ CandidateSubdir
).str();
421 return make_error_code(std::errc::no_such_file_or_directory
);
424 toolchains::MinGW::MinGW(const Driver
&D
, const llvm::Triple
&Triple
,
426 : ToolChain(D
, Triple
, Args
), CudaInstallation(D
, Triple
, Args
),
427 RocmInstallation(D
, Triple
, Args
) {
428 getProgramPaths().push_back(getDriver().getInstalledDir());
430 // The sequence for detecting a sysroot here should be kept in sync with
431 // the testTriple function below.
432 if (getDriver().SysRoot
.size())
433 Base
= getDriver().SysRoot
;
434 // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the
435 // base as it could still be a base for a gcc setup with libgcc.
436 else if (llvm::ErrorOr
<std::string
> TargetSubdir
=
437 findClangRelativeSysroot(getDriver(), getTriple(), SubdirName
))
438 Base
= std::string(llvm::sys::path::parent_path(TargetSubdir
.get()));
439 else if (llvm::ErrorOr
<std::string
> GPPName
= findGcc(getTriple()))
440 Base
= std::string(llvm::sys::path::parent_path(
441 llvm::sys::path::parent_path(GPPName
.get())));
444 llvm::sys::path::parent_path(getDriver().getInstalledDir()));
446 Base
+= llvm::sys::path::get_separator();
448 // GccLibDir must precede Base/lib so that the
449 // correct crtbegin.o ,cetend.o would be found.
450 getFilePaths().push_back(GccLibDir
);
451 getFilePaths().push_back(
452 (Base
+ SubdirName
+ llvm::sys::path::get_separator() + "lib").str());
455 getFilePaths().push_back(
456 (Base
+ SubdirName
+ llvm::sys::path::get_separator() + "mingw/lib").str());
458 getFilePaths().push_back(Base
+ "lib");
460 getFilePaths().push_back(Base
+ SubdirName
+ "/sys-root/mingw/lib");
463 Args
.getLastArgValue(options::OPT_fuse_ld_EQ
, CLANG_DEFAULT_LINKER
)
464 .equals_insensitive("lld");
467 bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; }
469 Tool
*toolchains::MinGW::getTool(Action::ActionClass AC
) const {
471 case Action::PreprocessJobClass
:
473 Preprocessor
.reset(new tools::gcc::Preprocessor(*this));
474 return Preprocessor
.get();
475 case Action::CompileJobClass
:
477 Compiler
.reset(new tools::gcc::Compiler(*this));
478 return Compiler
.get();
480 return ToolChain::getTool(AC
);
484 Tool
*toolchains::MinGW::buildAssembler() const {
485 return new tools::MinGW::Assembler(*this);
488 Tool
*toolchains::MinGW::buildLinker() const {
489 return new tools::MinGW::Linker(*this);
492 bool toolchains::MinGW::HasNativeLLVMSupport() const {
493 return NativeLLVMSupport
;
496 bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList
&Args
) const {
497 Arg
*ExceptionArg
= Args
.getLastArg(options::OPT_fsjlj_exceptions
,
498 options::OPT_fseh_exceptions
,
499 options::OPT_fdwarf_exceptions
);
501 ExceptionArg
->getOption().matches(options::OPT_fseh_exceptions
))
503 return getArch() == llvm::Triple::x86_64
|| getArch() == llvm::Triple::arm
||
504 getArch() == llvm::Triple::thumb
|| getArch() == llvm::Triple::aarch64
;
507 bool toolchains::MinGW::isPICDefault() const {
508 return getArch() == llvm::Triple::x86_64
||
509 getArch() == llvm::Triple::aarch64
;
512 bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList
&Args
) const {
516 bool toolchains::MinGW::isPICDefaultForced() const { return true; }
518 llvm::ExceptionHandling
519 toolchains::MinGW::GetExceptionModel(const ArgList
&Args
) const {
520 if (getArch() == llvm::Triple::x86_64
|| getArch() == llvm::Triple::aarch64
||
521 getArch() == llvm::Triple::arm
|| getArch() == llvm::Triple::thumb
)
522 return llvm::ExceptionHandling::WinEH
;
523 return llvm::ExceptionHandling::DwarfCFI
;
526 SanitizerMask
toolchains::MinGW::getSupportedSanitizers() const {
527 SanitizerMask Res
= ToolChain::getSupportedSanitizers();
528 Res
|= SanitizerKind::Address
;
529 Res
|= SanitizerKind::PointerCompare
;
530 Res
|= SanitizerKind::PointerSubtract
;
531 Res
|= SanitizerKind::Vptr
;
535 void toolchains::MinGW::AddCudaIncludeArgs(const ArgList
&DriverArgs
,
536 ArgStringList
&CC1Args
) const {
537 CudaInstallation
.AddCudaIncludeArgs(DriverArgs
, CC1Args
);
540 void toolchains::MinGW::AddHIPIncludeArgs(const ArgList
&DriverArgs
,
541 ArgStringList
&CC1Args
) const {
542 RocmInstallation
.AddHIPIncludeArgs(DriverArgs
, CC1Args
);
545 void toolchains::MinGW::printVerboseInfo(raw_ostream
&OS
) const {
546 CudaInstallation
.print(OS
);
547 RocmInstallation
.print(OS
);
550 // Include directories for various hosts:
552 // Windows, mingw.org
553 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++
554 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32
555 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward
557 // c:\mingw\mingw32\include
559 // Windows, mingw-w64 mingw-builds
560 // c:\mingw32\i686-w64-mingw32\include
561 // c:\mingw32\i686-w64-mingw32\include\c++
562 // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32
563 // c:\mingw32\i686-w64-mingw32\include\c++\backward
565 // Windows, mingw-w64 msys2
566 // c:\msys64\mingw32\include
567 // c:\msys64\mingw32\i686-w64-mingw32\include
568 // c:\msys64\mingw32\include\c++\4.9.2
569 // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32
570 // c:\msys64\mingw32\include\c++\4.9.2\backward
573 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++
574 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32
575 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward
576 // /usr/x86_64-w64-mingw32/sys-root/mingw/include
579 // /usr/i686-w64-mingw32/include/c++/5.1.0
580 // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32
581 // /usr/i686-w64-mingw32/include/c++/5.1.0/backward
582 // /usr/i686-w64-mingw32/include
585 // /usr/include/c++/4.8
586 // /usr/include/c++/4.8/x86_64-w64-mingw32
587 // /usr/include/c++/4.8/backward
588 // /usr/x86_64-w64-mingw32/include
590 void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList
&DriverArgs
,
591 ArgStringList
&CC1Args
) const {
592 if (DriverArgs
.hasArg(options::OPT_nostdinc
))
595 if (!DriverArgs
.hasArg(options::OPT_nobuiltininc
)) {
596 SmallString
<1024> P(getDriver().ResourceDir
);
597 llvm::sys::path::append(P
, "include");
598 addSystemInclude(DriverArgs
, CC1Args
, P
.str());
601 if (DriverArgs
.hasArg(options::OPT_nostdlibinc
))
604 if (GetRuntimeLibType(DriverArgs
) == ToolChain::RLT_Libgcc
) {
606 addSystemInclude(DriverArgs
, CC1Args
,
607 Base
+ SubdirName
+ "/sys-root/mingw/include");
610 addSystemInclude(DriverArgs
, CC1Args
,
611 Base
+ SubdirName
+ llvm::sys::path::get_separator() +
615 addSystemInclude(DriverArgs
, CC1Args
,
616 Base
+ SubdirName
+ llvm::sys::path::get_separator() + "usr/include");
618 addSystemInclude(DriverArgs
, CC1Args
, Base
+ "include");
621 void toolchains::MinGW::addClangTargetOptions(
622 const llvm::opt::ArgList
&DriverArgs
, llvm::opt::ArgStringList
&CC1Args
,
623 Action::OffloadKind DeviceOffloadKind
) const {
624 if (Arg
*A
= DriverArgs
.getLastArg(options::OPT_mguard_EQ
)) {
625 StringRef GuardArgs
= A
->getValue();
626 if (GuardArgs
== "none") {
628 } else if (GuardArgs
== "cf") {
629 // Emit CFG instrumentation and the table of address-taken functions.
630 CC1Args
.push_back("-cfguard");
631 } else if (GuardArgs
== "cf-nochecks") {
632 // Emit only the table of address-taken functions.
633 CC1Args
.push_back("-cfguard-no-checks");
635 getDriver().Diag(diag::err_drv_unsupported_option_argument
)
636 << A
->getSpelling() << GuardArgs
;
641 void toolchains::MinGW::AddClangCXXStdlibIncludeArgs(
642 const ArgList
&DriverArgs
, ArgStringList
&CC1Args
) const {
643 if (DriverArgs
.hasArg(options::OPT_nostdlibinc
) ||
644 DriverArgs
.hasArg(options::OPT_nostdincxx
))
647 StringRef Slash
= llvm::sys::path::get_separator();
649 switch (GetCXXStdlibType(DriverArgs
)) {
650 case ToolChain::CST_Libcxx
: {
651 std::string TargetDir
= (Base
+ "include" + Slash
+ getTripleString() +
652 Slash
+ "c++" + Slash
+ "v1")
654 if (getDriver().getVFS().exists(TargetDir
))
655 addSystemInclude(DriverArgs
, CC1Args
, TargetDir
);
656 addSystemInclude(DriverArgs
, CC1Args
,
657 Base
+ SubdirName
+ Slash
+ "include" + Slash
+ "c++" +
659 addSystemInclude(DriverArgs
, CC1Args
,
660 Base
+ "include" + Slash
+ "c++" + Slash
+ "v1");
664 case ToolChain::CST_Libstdcxx
:
665 llvm::SmallVector
<llvm::SmallString
<1024>, 7> CppIncludeBases
;
666 CppIncludeBases
.emplace_back(Base
);
667 llvm::sys::path::append(CppIncludeBases
[0], SubdirName
, "include", "c++");
668 CppIncludeBases
.emplace_back(Base
);
669 llvm::sys::path::append(CppIncludeBases
[1], SubdirName
, "include", "c++",
671 CppIncludeBases
.emplace_back(Base
);
672 llvm::sys::path::append(CppIncludeBases
[2], "include", "c++", Ver
);
673 CppIncludeBases
.emplace_back(GccLibDir
);
674 llvm::sys::path::append(CppIncludeBases
[3], "include", "c++");
675 CppIncludeBases
.emplace_back(GccLibDir
);
676 llvm::sys::path::append(CppIncludeBases
[4], "include",
677 "g++-v" + GccVer
.Text
);
678 CppIncludeBases
.emplace_back(GccLibDir
);
679 llvm::sys::path::append(CppIncludeBases
[5], "include",
680 "g++-v" + GccVer
.MajorStr
+ "." + GccVer
.MinorStr
);
681 CppIncludeBases
.emplace_back(GccLibDir
);
682 llvm::sys::path::append(CppIncludeBases
[6], "include",
683 "g++-v" + GccVer
.MajorStr
);
684 for (auto &CppIncludeBase
: CppIncludeBases
) {
685 addSystemInclude(DriverArgs
, CC1Args
, CppIncludeBase
);
686 CppIncludeBase
+= Slash
;
687 addSystemInclude(DriverArgs
, CC1Args
, CppIncludeBase
+ SubdirName
);
688 addSystemInclude(DriverArgs
, CC1Args
, CppIncludeBase
+ "backward");
694 static bool testTriple(const Driver
&D
, const llvm::Triple
&Triple
,
695 const ArgList
&Args
) {
696 // If an explicit sysroot is set, that will be used and we shouldn't try to
697 // detect anything else.
698 std::string SubdirName
;
699 if (D
.SysRoot
.size())
701 if (llvm::ErrorOr
<std::string
> TargetSubdir
=
702 findClangRelativeSysroot(D
, Triple
, SubdirName
))
704 if (llvm::ErrorOr
<std::string
> GPPName
= findGcc(Triple
))
706 // If we neither found a colocated sysroot or a matching gcc executable,
707 // conclude that we can't know if this is the correct spelling of the triple.
711 static llvm::Triple
adjustTriple(const Driver
&D
, const llvm::Triple
&Triple
,
712 const ArgList
&Args
) {
713 // First test if the original triple can find a sysroot with the triple
715 if (testTriple(D
, Triple
, Args
))
717 llvm::SmallVector
<llvm::StringRef
, 3> Archs
;
718 // If not, test a couple other possible arch names that might be what was
720 if (Triple
.getArch() == llvm::Triple::x86
) {
721 Archs
.emplace_back("i386");
722 Archs
.emplace_back("i586");
723 Archs
.emplace_back("i686");
724 } else if (Triple
.getArch() == llvm::Triple::arm
||
725 Triple
.getArch() == llvm::Triple::thumb
) {
726 Archs
.emplace_back("armv7");
728 for (auto A
: Archs
) {
729 llvm::Triple
TestTriple(Triple
);
730 TestTriple
.setArchName(A
);
731 if (testTriple(D
, TestTriple
, Args
))
734 // If none was found, just proceed with the original value.
738 void toolchains::MinGW::fixTripleArch(const Driver
&D
, llvm::Triple
&Triple
,
739 const ArgList
&Args
) {
740 if (Triple
.getArch() == llvm::Triple::x86
||
741 Triple
.getArch() == llvm::Triple::arm
||
742 Triple
.getArch() == llvm::Triple::thumb
)
743 Triple
= adjustTriple(D
, Triple
, Args
);