1 //===--- MinGW.cpp - MinGWToolChain Implementation ------------------------===// 2 // 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 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "MinGW.h" 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> 23 24 using namespace clang::diag; 25 using namespace clang::driver; 26 using namespace clang; 27 using namespace llvm::opt; 28 29 /// MinGW Tools 30 void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 31 const InputInfo &Output, 32 const InputInfoList &Inputs, 33 const ArgList &Args, 34 const char *LinkingOutput) const { 35 claimNoWarnArgs(Args); 36 ArgStringList CmdArgs; 37 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"); 42 } 43 44 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 45 46 CmdArgs.push_back("-o"); 47 CmdArgs.push_back(Output.getFilename()); 48 49 for (const auto &II : Inputs) 50 CmdArgs.push_back(II.getFilename()); 51 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)); 55 56 if (Args.hasArg(options::OPT_gsplit_dwarf)) 57 SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, 58 SplitDebugName(JA, Args, Inputs[0], Output)); 59 } 60 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"); 66 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(); 74 75 if (Static || (!CXX && !Shared)) { 76 CmdArgs.push_back("-lgcc"); 77 CmdArgs.push_back("-lgcc_eh"); 78 } else { 79 CmdArgs.push_back("-lgcc_s"); 80 CmdArgs.push_back("-lgcc"); 81 } 82 } else { 83 AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args); 84 } 85 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")) 92 return; 93 CmdArgs.push_back("-lmsvcrt"); 94 } 95 96 void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, 97 const InputInfo &Output, 98 const InputInfoList &Inputs, 99 const ArgList &Args, 100 const char *LinkingOutput) const { 101 const ToolChain &TC = getToolChain(); 102 const Driver &D = TC.getDriver(); 103 const SanitizerArgs &Sanitize = TC.getSanitizerArgs(Args); 104 105 ArgStringList CmdArgs; 106 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); 114 115 if (!D.SysRoot.empty()) 116 CmdArgs.push_back(Args.MakeArgString("--sysroot=" + D.SysRoot)); 117 118 if (Args.hasArg(options::OPT_s)) 119 CmdArgs.push_back("-s"); 120 121 CmdArgs.push_back("-m"); 122 switch (TC.getArch()) { 123 case llvm::Triple::x86: 124 CmdArgs.push_back("i386pe"); 125 break; 126 case llvm::Triple::x86_64: 127 CmdArgs.push_back("i386pep"); 128 break; 129 case llvm::Triple::arm: 130 case llvm::Triple::thumb: 131 // FIXME: this is incorrect for WinCE 132 CmdArgs.push_back("thumb2pe"); 133 break; 134 case llvm::Triple::aarch64: 135 CmdArgs.push_back("arm64pe"); 136 break; 137 default: 138 llvm_unreachable("Unsupported target architecture."); 139 } 140 141 Arg *SubsysArg = 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"); 150 } 151 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"); 158 else 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"); 164 else 165 CmdArgs.push_back("DllMainCRTStartup"); 166 CmdArgs.push_back("--enable-auto-image-base"); 167 } 168 169 if (Args.hasArg(options::OPT_Z_Xlinker__no_demangle)) 170 CmdArgs.push_back("--no-demangle"); 171 172 CmdArgs.push_back("-o"); 173 const char *OutputFile = Output.getFilename(); 174 // GCC implicitly adds an .exe extension if it is given an output file name 175 // that lacks an extension. 176 // GCC used to do this only when the compiler itself runs on windows, but 177 // since GCC 8 it does the same when cross compiling as well. 178 if (!llvm::sys::path::has_extension(OutputFile)) { 179 CmdArgs.push_back(Args.MakeArgString(Twine(OutputFile) + ".exe")); 180 OutputFile = CmdArgs.back(); 181 } else 182 CmdArgs.push_back(OutputFile); 183 184 Args.AddAllArgs(CmdArgs, options::OPT_e); 185 // FIXME: add -N, -n flags 186 Args.AddLastArg(CmdArgs, options::OPT_r); 187 Args.AddLastArg(CmdArgs, options::OPT_s); 188 Args.AddLastArg(CmdArgs, options::OPT_t); 189 Args.AddAllArgs(CmdArgs, options::OPT_u_Group); 190 Args.AddLastArg(CmdArgs, options::OPT_Z_Flag); 191 192 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 193 if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { 194 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o"))); 195 } else { 196 if (Args.hasArg(options::OPT_municode)) 197 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o"))); 198 else 199 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o"))); 200 } 201 if (Args.hasArg(options::OPT_pg)) 202 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o"))); 203 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o"))); 204 } 205 206 Args.AddAllArgs(CmdArgs, options::OPT_L); 207 TC.AddFilePathLibArgs(Args, CmdArgs); 208 209 // Add the compiler-rt library directories if they exist to help 210 // the linker find the various sanitizer, builtin, and profiling runtimes. 211 for (const auto &LibPath : TC.getLibraryPaths()) { 212 if (TC.getVFS().exists(LibPath)) 213 CmdArgs.push_back(Args.MakeArgString("-L" + LibPath)); 214 } 215 auto CRTPath = TC.getCompilerRTPath(); 216 if (TC.getVFS().exists(CRTPath)) 217 CmdArgs.push_back(Args.MakeArgString("-L" + CRTPath)); 218 219 AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); 220 221 if (C.getDriver().IsFlangMode()) { 222 addFortranRuntimeLibraryPath(TC, Args, CmdArgs); 223 addFortranRuntimeLibs(TC, CmdArgs); 224 } 225 226 // TODO: Add profile stuff here 227 228 if (TC.ShouldLinkCXXStdlib(Args)) { 229 bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && 230 !Args.hasArg(options::OPT_static); 231 if (OnlyLibstdcxxStatic) 232 CmdArgs.push_back("-Bstatic"); 233 TC.AddCXXStdlibLibArgs(Args, CmdArgs); 234 if (OnlyLibstdcxxStatic) 235 CmdArgs.push_back("-Bdynamic"); 236 } 237 238 bool HasWindowsApp = false; 239 for (auto Lib : Args.getAllArgValues(options::OPT_l)) { 240 if (Lib == "windowsapp") { 241 HasWindowsApp = true; 242 break; 243 } 244 } 245 246 if (!Args.hasArg(options::OPT_nostdlib)) { 247 if (!Args.hasArg(options::OPT_nodefaultlibs)) { 248 if (Args.hasArg(options::OPT_static)) 249 CmdArgs.push_back("--start-group"); 250 251 if (Args.hasArg(options::OPT_fstack_protector) || 252 Args.hasArg(options::OPT_fstack_protector_strong) || 253 Args.hasArg(options::OPT_fstack_protector_all)) { 254 CmdArgs.push_back("-lssp_nonshared"); 255 CmdArgs.push_back("-lssp"); 256 } 257 258 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 259 options::OPT_fno_openmp, false)) { 260 switch (TC.getDriver().getOpenMPRuntime(Args)) { 261 case Driver::OMPRT_OMP: 262 CmdArgs.push_back("-lomp"); 263 break; 264 case Driver::OMPRT_IOMP5: 265 CmdArgs.push_back("-liomp5md"); 266 break; 267 case Driver::OMPRT_GOMP: 268 CmdArgs.push_back("-lgomp"); 269 break; 270 case Driver::OMPRT_Unknown: 271 // Already diagnosed. 272 break; 273 } 274 } 275 276 AddLibGCC(Args, CmdArgs); 277 278 if (Args.hasArg(options::OPT_pg)) 279 CmdArgs.push_back("-lgmon"); 280 281 if (Args.hasArg(options::OPT_pthread)) 282 CmdArgs.push_back("-lpthread"); 283 284 if (Sanitize.needsAsanRt()) { 285 // MinGW always links against a shared MSVCRT. 286 CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic", 287 ToolChain::FT_Shared)); 288 CmdArgs.push_back( 289 TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); 290 CmdArgs.push_back("--require-defined"); 291 CmdArgs.push_back(TC.getArch() == llvm::Triple::x86 292 ? "___asan_seh_interceptor" 293 : "__asan_seh_interceptor"); 294 // Make sure the linker consider all object files from the dynamic 295 // runtime thunk. 296 CmdArgs.push_back("--whole-archive"); 297 CmdArgs.push_back( 298 TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); 299 CmdArgs.push_back("--no-whole-archive"); 300 } 301 302 TC.addProfileRTLibs(Args, CmdArgs); 303 304 if (!HasWindowsApp) { 305 // Add system libraries. If linking to libwindowsapp.a, that import 306 // library replaces all these and we shouldn't accidentally try to 307 // link to the normal desktop mode dlls. 308 if (Args.hasArg(options::OPT_mwindows)) { 309 CmdArgs.push_back("-lgdi32"); 310 CmdArgs.push_back("-lcomdlg32"); 311 } 312 CmdArgs.push_back("-ladvapi32"); 313 CmdArgs.push_back("-lshell32"); 314 CmdArgs.push_back("-luser32"); 315 CmdArgs.push_back("-lkernel32"); 316 } 317 318 if (Args.hasArg(options::OPT_static)) { 319 CmdArgs.push_back("--end-group"); 320 } else { 321 AddLibGCC(Args, CmdArgs); 322 if (!HasWindowsApp) 323 CmdArgs.push_back("-lkernel32"); 324 } 325 } 326 327 if (!Args.hasArg(options::OPT_nostartfiles)) { 328 // Add crtfastmath.o if available and fast math is enabled. 329 TC.addFastMathRuntimeIfAvailable(Args, CmdArgs); 330 331 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); 332 } 333 } 334 const char *Exec = Args.MakeArgString(TC.GetLinkerPath()); 335 C.addCommand(std::make_unique<Command>(JA, *this, 336 ResponseFileSupport::AtFileUTF8(), 337 Exec, CmdArgs, Inputs, Output)); 338 } 339 340 // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. 341 static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, 342 std::string &Ver, 343 toolchains::Generic_GCC::GCCVersion &Version) { 344 Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); 345 std::error_code EC; 346 for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE; 347 LI = LI.increment(EC)) { 348 StringRef VersionText = llvm::sys::path::filename(LI->path()); 349 auto CandidateVersion = 350 toolchains::Generic_GCC::GCCVersion::Parse(VersionText); 351 if (CandidateVersion.Major == -1) 352 continue; 353 if (CandidateVersion <= Version) 354 continue; 355 Version = CandidateVersion; 356 Ver = std::string(VersionText); 357 GccLibDir = LI->path(); 358 } 359 return Ver.size(); 360 } 361 362 void toolchains::MinGW::findGccLibDir() { 363 llvm::SmallVector<llvm::SmallString<32>, 2> SubdirNames; 364 SubdirNames.emplace_back(getTriple().getArchName()); 365 SubdirNames[0] += "-w64-mingw32"; 366 SubdirNames.emplace_back("mingw32"); 367 if (SubdirName.empty()) 368 SubdirName = std::string(SubdirNames[0].str()); 369 // lib: Arch Linux, Ubuntu, Windows 370 // lib64: openSUSE Linux 371 for (StringRef CandidateLib : {"lib", "lib64"}) { 372 for (StringRef CandidateSysroot : SubdirNames) { 373 llvm::SmallString<1024> LibDir(Base); 374 llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot); 375 if (findGccVersion(LibDir, GccLibDir, Ver, GccVer)) { 376 SubdirName = std::string(CandidateSysroot); 377 return; 378 } 379 } 380 } 381 } 382 383 static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &T) { 384 llvm::SmallVector<llvm::SmallString<32>, 2> Gccs; 385 Gccs.emplace_back(T.getArchName()); 386 Gccs[0] += "-w64-mingw32-gcc"; 387 Gccs.emplace_back("mingw32-gcc"); 388 // Please do not add "gcc" here 389 for (StringRef CandidateGcc : Gccs) 390 if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc)) 391 return GPPName; 392 return make_error_code(std::errc::no_such_file_or_directory); 393 } 394 395 static llvm::ErrorOr<std::string> 396 findClangRelativeSysroot(const Driver &D, const llvm::Triple &T, 397 std::string &SubdirName) { 398 llvm::SmallVector<llvm::SmallString<32>, 2> Subdirs; 399 Subdirs.emplace_back(T.str()); 400 Subdirs.emplace_back(T.getArchName()); 401 Subdirs[1] += "-w64-mingw32"; 402 StringRef ClangRoot = llvm::sys::path::parent_path(D.getInstalledDir()); 403 StringRef Sep = llvm::sys::path::get_separator(); 404 for (StringRef CandidateSubdir : Subdirs) { 405 if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) { 406 SubdirName = std::string(CandidateSubdir); 407 return (ClangRoot + Sep + CandidateSubdir).str(); 408 } 409 } 410 return make_error_code(std::errc::no_such_file_or_directory); 411 } 412 413 toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, 414 const ArgList &Args) 415 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), 416 RocmInstallation(D, Triple, Args) { 417 getProgramPaths().push_back(getDriver().getInstalledDir()); 418 419 // The sequence for detecting a sysroot here should be kept in sync with 420 // the testTriple function below. 421 if (getDriver().SysRoot.size()) 422 Base = getDriver().SysRoot; 423 // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the 424 // base as it could still be a base for a gcc setup with libgcc. 425 else if (llvm::ErrorOr<std::string> TargetSubdir = 426 findClangRelativeSysroot(getDriver(), getTriple(), SubdirName)) 427 Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get())); 428 else if (llvm::ErrorOr<std::string> GPPName = findGcc(getTriple())) 429 Base = std::string(llvm::sys::path::parent_path( 430 llvm::sys::path::parent_path(GPPName.get()))); 431 else 432 Base = std::string( 433 llvm::sys::path::parent_path(getDriver().getInstalledDir())); 434 435 Base += llvm::sys::path::get_separator(); 436 findGccLibDir(); 437 // GccLibDir must precede Base/lib so that the 438 // correct crtbegin.o ,cetend.o would be found. 439 getFilePaths().push_back(GccLibDir); 440 getFilePaths().push_back( 441 (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str()); 442 443 // Gentoo 444 getFilePaths().push_back( 445 (Base + SubdirName + llvm::sys::path::get_separator() + "mingw/lib").str()); 446 447 getFilePaths().push_back(Base + "lib"); 448 // openSUSE 449 getFilePaths().push_back(Base + SubdirName + "/sys-root/mingw/lib"); 450 451 NativeLLVMSupport = 452 Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER) 453 .equals_insensitive("lld"); 454 } 455 456 bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; } 457 458 Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const { 459 switch (AC) { 460 case Action::PreprocessJobClass: 461 if (!Preprocessor) 462 Preprocessor.reset(new tools::gcc::Preprocessor(*this)); 463 return Preprocessor.get(); 464 case Action::CompileJobClass: 465 if (!Compiler) 466 Compiler.reset(new tools::gcc::Compiler(*this)); 467 return Compiler.get(); 468 default: 469 return ToolChain::getTool(AC); 470 } 471 } 472 473 Tool *toolchains::MinGW::buildAssembler() const { 474 return new tools::MinGW::Assembler(*this); 475 } 476 477 Tool *toolchains::MinGW::buildLinker() const { 478 return new tools::MinGW::Linker(*this); 479 } 480 481 bool toolchains::MinGW::HasNativeLLVMSupport() const { 482 return NativeLLVMSupport; 483 } 484 485 bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const { 486 Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions, 487 options::OPT_fseh_exceptions, 488 options::OPT_fdwarf_exceptions); 489 if (ExceptionArg && 490 ExceptionArg->getOption().matches(options::OPT_fseh_exceptions)) 491 return true; 492 return getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::arm || 493 getArch() == llvm::Triple::thumb || getArch() == llvm::Triple::aarch64; 494 } 495 496 bool toolchains::MinGW::isPICDefault() const { 497 return getArch() == llvm::Triple::x86_64 || 498 getArch() == llvm::Triple::aarch64; 499 } 500 501 bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const { 502 return false; 503 } 504 505 bool toolchains::MinGW::isPICDefaultForced() const { return true; } 506 507 llvm::ExceptionHandling 508 toolchains::MinGW::GetExceptionModel(const ArgList &Args) const { 509 if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64 || 510 getArch() == llvm::Triple::arm || getArch() == llvm::Triple::thumb) 511 return llvm::ExceptionHandling::WinEH; 512 return llvm::ExceptionHandling::DwarfCFI; 513 } 514 515 SanitizerMask toolchains::MinGW::getSupportedSanitizers() const { 516 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 517 Res |= SanitizerKind::Address; 518 Res |= SanitizerKind::PointerCompare; 519 Res |= SanitizerKind::PointerSubtract; 520 Res |= SanitizerKind::Vptr; 521 return Res; 522 } 523 524 void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, 525 ArgStringList &CC1Args) const { 526 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); 527 } 528 529 void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs, 530 ArgStringList &CC1Args) const { 531 RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); 532 } 533 534 void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const { 535 CudaInstallation.print(OS); 536 RocmInstallation.print(OS); 537 } 538 539 // Include directories for various hosts: 540 541 // Windows, mingw.org 542 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++ 543 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32 544 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward 545 // c:\mingw\include 546 // c:\mingw\mingw32\include 547 548 // Windows, mingw-w64 mingw-builds 549 // c:\mingw32\i686-w64-mingw32\include 550 // c:\mingw32\i686-w64-mingw32\include\c++ 551 // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32 552 // c:\mingw32\i686-w64-mingw32\include\c++\backward 553 554 // Windows, mingw-w64 msys2 555 // c:\msys64\mingw32\include 556 // c:\msys64\mingw32\i686-w64-mingw32\include 557 // c:\msys64\mingw32\include\c++\4.9.2 558 // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32 559 // c:\msys64\mingw32\include\c++\4.9.2\backward 560 561 // openSUSE 562 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++ 563 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32 564 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward 565 // /usr/x86_64-w64-mingw32/sys-root/mingw/include 566 567 // Arch Linux 568 // /usr/i686-w64-mingw32/include/c++/5.1.0 569 // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32 570 // /usr/i686-w64-mingw32/include/c++/5.1.0/backward 571 // /usr/i686-w64-mingw32/include 572 573 // Ubuntu 574 // /usr/include/c++/4.8 575 // /usr/include/c++/4.8/x86_64-w64-mingw32 576 // /usr/include/c++/4.8/backward 577 // /usr/x86_64-w64-mingw32/include 578 579 void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 580 ArgStringList &CC1Args) const { 581 if (DriverArgs.hasArg(options::OPT_nostdinc)) 582 return; 583 584 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 585 SmallString<1024> P(getDriver().ResourceDir); 586 llvm::sys::path::append(P, "include"); 587 addSystemInclude(DriverArgs, CC1Args, P.str()); 588 } 589 590 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 591 return; 592 593 if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) { 594 // openSUSE 595 addSystemInclude(DriverArgs, CC1Args, 596 Base + SubdirName + "/sys-root/mingw/include"); 597 } 598 599 addSystemInclude(DriverArgs, CC1Args, 600 Base + SubdirName + llvm::sys::path::get_separator() + 601 "include"); 602 603 // Gentoo 604 addSystemInclude(DriverArgs, CC1Args, 605 Base + SubdirName + llvm::sys::path::get_separator() + "usr/include"); 606 607 addSystemInclude(DriverArgs, CC1Args, Base + "include"); 608 } 609 610 void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( 611 const ArgList &DriverArgs, ArgStringList &CC1Args) const { 612 if (DriverArgs.hasArg(options::OPT_nostdlibinc) || 613 DriverArgs.hasArg(options::OPT_nostdincxx)) 614 return; 615 616 StringRef Slash = llvm::sys::path::get_separator(); 617 618 switch (GetCXXStdlibType(DriverArgs)) { 619 case ToolChain::CST_Libcxx: { 620 std::string TargetDir = (Base + "include" + Slash + getTripleString() + 621 Slash + "c++" + Slash + "v1") 622 .str(); 623 if (getDriver().getVFS().exists(TargetDir)) 624 addSystemInclude(DriverArgs, CC1Args, TargetDir); 625 addSystemInclude(DriverArgs, CC1Args, 626 Base + SubdirName + Slash + "include" + Slash + "c++" + 627 Slash + "v1"); 628 addSystemInclude(DriverArgs, CC1Args, 629 Base + "include" + Slash + "c++" + Slash + "v1"); 630 break; 631 } 632 633 case ToolChain::CST_Libstdcxx: 634 llvm::SmallVector<llvm::SmallString<1024>, 7> CppIncludeBases; 635 CppIncludeBases.emplace_back(Base); 636 llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++"); 637 CppIncludeBases.emplace_back(Base); 638 llvm::sys::path::append(CppIncludeBases[1], SubdirName, "include", "c++", 639 Ver); 640 CppIncludeBases.emplace_back(Base); 641 llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver); 642 CppIncludeBases.emplace_back(GccLibDir); 643 llvm::sys::path::append(CppIncludeBases[3], "include", "c++"); 644 CppIncludeBases.emplace_back(GccLibDir); 645 llvm::sys::path::append(CppIncludeBases[4], "include", 646 "g++-v" + GccVer.Text); 647 CppIncludeBases.emplace_back(GccLibDir); 648 llvm::sys::path::append(CppIncludeBases[5], "include", 649 "g++-v" + GccVer.MajorStr + "." + GccVer.MinorStr); 650 CppIncludeBases.emplace_back(GccLibDir); 651 llvm::sys::path::append(CppIncludeBases[6], "include", 652 "g++-v" + GccVer.MajorStr); 653 for (auto &CppIncludeBase : CppIncludeBases) { 654 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase); 655 CppIncludeBase += Slash; 656 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + SubdirName); 657 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward"); 658 } 659 break; 660 } 661 } 662 663 static bool testTriple(const Driver &D, const llvm::Triple &Triple, 664 const ArgList &Args) { 665 // If an explicit sysroot is set, that will be used and we shouldn't try to 666 // detect anything else. 667 std::string SubdirName; 668 if (D.SysRoot.size()) 669 return true; 670 if (llvm::ErrorOr<std::string> TargetSubdir = 671 findClangRelativeSysroot(D, Triple, SubdirName)) 672 return true; 673 if (llvm::ErrorOr<std::string> GPPName = findGcc(Triple)) 674 return true; 675 // If we neither found a colocated sysroot or a matching gcc executable, 676 // conclude that we can't know if this is the correct spelling of the triple. 677 return false; 678 } 679 680 static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple, 681 const ArgList &Args) { 682 // First test if the original triple can find a sysroot with the triple 683 // name. 684 if (testTriple(D, Triple, Args)) 685 return Triple; 686 llvm::SmallVector<llvm::StringRef, 3> Archs; 687 // If not, test a couple other possible arch names that might be what was 688 // intended. 689 if (Triple.getArch() == llvm::Triple::x86) { 690 Archs.emplace_back("i386"); 691 Archs.emplace_back("i586"); 692 Archs.emplace_back("i686"); 693 } else if (Triple.getArch() == llvm::Triple::arm || 694 Triple.getArch() == llvm::Triple::thumb) { 695 Archs.emplace_back("armv7"); 696 } 697 for (auto A : Archs) { 698 llvm::Triple TestTriple(Triple); 699 TestTriple.setArchName(A); 700 if (testTriple(D, TestTriple, Args)) 701 return TestTriple; 702 } 703 // If none was found, just proceed with the original value. 704 return Triple; 705 } 706 707 void toolchains::MinGW::fixTripleArch(const Driver &D, llvm::Triple &Triple, 708 const ArgList &Args) { 709 if (Triple.getArch() == llvm::Triple::x86 || 710 Triple.getArch() == llvm::Triple::arm || 711 Triple.getArch() == llvm::Triple::thumb) 712 Triple = adjustTriple(D, Triple, Args); 713 } 714