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 // TODO: Add profile stuff here 222 223 if (TC.ShouldLinkCXXStdlib(Args)) { 224 bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && 225 !Args.hasArg(options::OPT_static); 226 if (OnlyLibstdcxxStatic) 227 CmdArgs.push_back("-Bstatic"); 228 TC.AddCXXStdlibLibArgs(Args, CmdArgs); 229 if (OnlyLibstdcxxStatic) 230 CmdArgs.push_back("-Bdynamic"); 231 } 232 233 bool HasWindowsApp = false; 234 for (auto Lib : Args.getAllArgValues(options::OPT_l)) { 235 if (Lib == "windowsapp") { 236 HasWindowsApp = true; 237 break; 238 } 239 } 240 241 if (!Args.hasArg(options::OPT_nostdlib)) { 242 if (!Args.hasArg(options::OPT_nodefaultlibs)) { 243 if (Args.hasArg(options::OPT_static)) 244 CmdArgs.push_back("--start-group"); 245 246 if (Args.hasArg(options::OPT_fstack_protector) || 247 Args.hasArg(options::OPT_fstack_protector_strong) || 248 Args.hasArg(options::OPT_fstack_protector_all)) { 249 CmdArgs.push_back("-lssp_nonshared"); 250 CmdArgs.push_back("-lssp"); 251 } 252 253 if (Args.hasFlag(options::OPT_fopenmp, options::OPT_fopenmp_EQ, 254 options::OPT_fno_openmp, false)) { 255 switch (TC.getDriver().getOpenMPRuntime(Args)) { 256 case Driver::OMPRT_OMP: 257 CmdArgs.push_back("-lomp"); 258 break; 259 case Driver::OMPRT_IOMP5: 260 CmdArgs.push_back("-liomp5md"); 261 break; 262 case Driver::OMPRT_GOMP: 263 CmdArgs.push_back("-lgomp"); 264 break; 265 case Driver::OMPRT_Unknown: 266 // Already diagnosed. 267 break; 268 } 269 } 270 271 AddLibGCC(Args, CmdArgs); 272 273 if (Args.hasArg(options::OPT_pg)) 274 CmdArgs.push_back("-lgmon"); 275 276 if (Args.hasArg(options::OPT_pthread)) 277 CmdArgs.push_back("-lpthread"); 278 279 if (Sanitize.needsAsanRt()) { 280 // MinGW always links against a shared MSVCRT. 281 CmdArgs.push_back(TC.getCompilerRTArgString(Args, "asan_dynamic", 282 ToolChain::FT_Shared)); 283 CmdArgs.push_back( 284 TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); 285 CmdArgs.push_back("--require-defined"); 286 CmdArgs.push_back(TC.getArch() == llvm::Triple::x86 287 ? "___asan_seh_interceptor" 288 : "__asan_seh_interceptor"); 289 // Make sure the linker consider all object files from the dynamic 290 // runtime thunk. 291 CmdArgs.push_back("--whole-archive"); 292 CmdArgs.push_back( 293 TC.getCompilerRTArgString(Args, "asan_dynamic_runtime_thunk")); 294 CmdArgs.push_back("--no-whole-archive"); 295 } 296 297 TC.addProfileRTLibs(Args, CmdArgs); 298 299 if (!HasWindowsApp) { 300 // Add system libraries. If linking to libwindowsapp.a, that import 301 // library replaces all these and we shouldn't accidentally try to 302 // link to the normal desktop mode dlls. 303 if (Args.hasArg(options::OPT_mwindows)) { 304 CmdArgs.push_back("-lgdi32"); 305 CmdArgs.push_back("-lcomdlg32"); 306 } 307 CmdArgs.push_back("-ladvapi32"); 308 CmdArgs.push_back("-lshell32"); 309 CmdArgs.push_back("-luser32"); 310 CmdArgs.push_back("-lkernel32"); 311 } 312 313 if (Args.hasArg(options::OPT_static)) { 314 CmdArgs.push_back("--end-group"); 315 } else { 316 AddLibGCC(Args, CmdArgs); 317 if (!HasWindowsApp) 318 CmdArgs.push_back("-lkernel32"); 319 } 320 } 321 322 if (!Args.hasArg(options::OPT_nostartfiles)) { 323 // Add crtfastmath.o if available and fast math is enabled. 324 TC.addFastMathRuntimeIfAvailable(Args, CmdArgs); 325 326 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); 327 } 328 } 329 const char *Exec = Args.MakeArgString(TC.GetLinkerPath()); 330 C.addCommand(std::make_unique<Command>(JA, *this, 331 ResponseFileSupport::AtFileUTF8(), 332 Exec, CmdArgs, Inputs, Output)); 333 } 334 335 // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. 336 static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, 337 std::string &Ver) { 338 auto Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); 339 std::error_code EC; 340 for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE; 341 LI = LI.increment(EC)) { 342 StringRef VersionText = llvm::sys::path::filename(LI->path()); 343 auto CandidateVersion = 344 toolchains::Generic_GCC::GCCVersion::Parse(VersionText); 345 if (CandidateVersion.Major == -1) 346 continue; 347 if (CandidateVersion <= Version) 348 continue; 349 Version = CandidateVersion; 350 Ver = std::string(VersionText); 351 GccLibDir = LI->path(); 352 } 353 return Ver.size(); 354 } 355 356 void toolchains::MinGW::findGccLibDir() { 357 llvm::SmallVector<llvm::SmallString<32>, 2> SubdirNames; 358 SubdirNames.emplace_back(getTriple().getArchName()); 359 SubdirNames[0] += "-w64-mingw32"; 360 SubdirNames.emplace_back("mingw32"); 361 if (SubdirName.empty()) 362 SubdirName = std::string(SubdirNames[0].str()); 363 // lib: Arch Linux, Ubuntu, Windows 364 // lib64: openSUSE Linux 365 for (StringRef CandidateLib : {"lib", "lib64"}) { 366 for (StringRef CandidateSysroot : SubdirNames) { 367 llvm::SmallString<1024> LibDir(Base); 368 llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateSysroot); 369 if (findGccVersion(LibDir, GccLibDir, Ver)) { 370 SubdirName = std::string(CandidateSysroot); 371 return; 372 } 373 } 374 } 375 } 376 377 static llvm::ErrorOr<std::string> findGcc(const llvm::Triple &T) { 378 llvm::SmallVector<llvm::SmallString<32>, 2> Gccs; 379 Gccs.emplace_back(T.getArchName()); 380 Gccs[0] += "-w64-mingw32-gcc"; 381 Gccs.emplace_back("mingw32-gcc"); 382 // Please do not add "gcc" here 383 for (StringRef CandidateGcc : Gccs) 384 if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc)) 385 return GPPName; 386 return make_error_code(std::errc::no_such_file_or_directory); 387 } 388 389 static llvm::ErrorOr<std::string> 390 findClangRelativeSysroot(const Driver &D, const llvm::Triple &T, 391 std::string &SubdirName) { 392 llvm::SmallVector<llvm::SmallString<32>, 2> Subdirs; 393 Subdirs.emplace_back(T.str()); 394 Subdirs.emplace_back(T.getArchName()); 395 Subdirs[1] += "-w64-mingw32"; 396 StringRef ClangRoot = llvm::sys::path::parent_path(D.getInstalledDir()); 397 StringRef Sep = llvm::sys::path::get_separator(); 398 for (StringRef CandidateSubdir : Subdirs) { 399 if (llvm::sys::fs::is_directory(ClangRoot + Sep + CandidateSubdir)) { 400 SubdirName = std::string(CandidateSubdir); 401 return (ClangRoot + Sep + CandidateSubdir).str(); 402 } 403 } 404 return make_error_code(std::errc::no_such_file_or_directory); 405 } 406 407 toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, 408 const ArgList &Args) 409 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args), 410 RocmInstallation(D, Triple, Args) { 411 getProgramPaths().push_back(getDriver().getInstalledDir()); 412 413 // The sequence for detecting a sysroot here should be kept in sync with 414 // the testTriple function below. 415 if (getDriver().SysRoot.size()) 416 Base = getDriver().SysRoot; 417 // Look for <clang-bin>/../<triplet>; if found, use <clang-bin>/.. as the 418 // base as it could still be a base for a gcc setup with libgcc. 419 else if (llvm::ErrorOr<std::string> TargetSubdir = 420 findClangRelativeSysroot(getDriver(), getTriple(), SubdirName)) 421 Base = std::string(llvm::sys::path::parent_path(TargetSubdir.get())); 422 else if (llvm::ErrorOr<std::string> GPPName = findGcc(getTriple())) 423 Base = std::string(llvm::sys::path::parent_path( 424 llvm::sys::path::parent_path(GPPName.get()))); 425 else 426 Base = std::string( 427 llvm::sys::path::parent_path(getDriver().getInstalledDir())); 428 429 Base += llvm::sys::path::get_separator(); 430 findGccLibDir(); 431 // GccLibDir must precede Base/lib so that the 432 // correct crtbegin.o ,cetend.o would be found. 433 getFilePaths().push_back(GccLibDir); 434 getFilePaths().push_back( 435 (Base + SubdirName + llvm::sys::path::get_separator() + "lib").str()); 436 getFilePaths().push_back(Base + "lib"); 437 // openSUSE 438 getFilePaths().push_back(Base + SubdirName + "/sys-root/mingw/lib"); 439 440 NativeLLVMSupport = 441 Args.getLastArgValue(options::OPT_fuse_ld_EQ, CLANG_DEFAULT_LINKER) 442 .equals_insensitive("lld"); 443 } 444 445 bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; } 446 447 Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const { 448 switch (AC) { 449 case Action::PreprocessJobClass: 450 if (!Preprocessor) 451 Preprocessor.reset(new tools::gcc::Preprocessor(*this)); 452 return Preprocessor.get(); 453 case Action::CompileJobClass: 454 if (!Compiler) 455 Compiler.reset(new tools::gcc::Compiler(*this)); 456 return Compiler.get(); 457 default: 458 return ToolChain::getTool(AC); 459 } 460 } 461 462 Tool *toolchains::MinGW::buildAssembler() const { 463 return new tools::MinGW::Assembler(*this); 464 } 465 466 Tool *toolchains::MinGW::buildLinker() const { 467 return new tools::MinGW::Linker(*this); 468 } 469 470 bool toolchains::MinGW::HasNativeLLVMSupport() const { 471 return NativeLLVMSupport; 472 } 473 474 bool toolchains::MinGW::IsUnwindTablesDefault(const ArgList &Args) const { 475 Arg *ExceptionArg = Args.getLastArg(options::OPT_fsjlj_exceptions, 476 options::OPT_fseh_exceptions, 477 options::OPT_fdwarf_exceptions); 478 if (ExceptionArg && 479 ExceptionArg->getOption().matches(options::OPT_fseh_exceptions)) 480 return true; 481 return getArch() == llvm::Triple::x86_64 || 482 getArch() == llvm::Triple::aarch64; 483 } 484 485 bool toolchains::MinGW::isPICDefault() const { 486 return getArch() == llvm::Triple::x86_64 || 487 getArch() == llvm::Triple::aarch64; 488 } 489 490 bool toolchains::MinGW::isPIEDefault(const llvm::opt::ArgList &Args) const { 491 return false; 492 } 493 494 bool toolchains::MinGW::isPICDefaultForced() const { return true; } 495 496 llvm::ExceptionHandling 497 toolchains::MinGW::GetExceptionModel(const ArgList &Args) const { 498 if (getArch() == llvm::Triple::x86_64 || getArch() == llvm::Triple::aarch64) 499 return llvm::ExceptionHandling::WinEH; 500 return llvm::ExceptionHandling::DwarfCFI; 501 } 502 503 SanitizerMask toolchains::MinGW::getSupportedSanitizers() const { 504 SanitizerMask Res = ToolChain::getSupportedSanitizers(); 505 Res |= SanitizerKind::Address; 506 Res |= SanitizerKind::PointerCompare; 507 Res |= SanitizerKind::PointerSubtract; 508 Res |= SanitizerKind::Vptr; 509 return Res; 510 } 511 512 void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, 513 ArgStringList &CC1Args) const { 514 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); 515 } 516 517 void toolchains::MinGW::AddHIPIncludeArgs(const ArgList &DriverArgs, 518 ArgStringList &CC1Args) const { 519 RocmInstallation.AddHIPIncludeArgs(DriverArgs, CC1Args); 520 } 521 522 void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const { 523 CudaInstallation.print(OS); 524 RocmInstallation.print(OS); 525 } 526 527 // Include directories for various hosts: 528 529 // Windows, mingw.org 530 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++ 531 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32 532 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward 533 // c:\mingw\include 534 // c:\mingw\mingw32\include 535 536 // Windows, mingw-w64 mingw-builds 537 // c:\mingw32\i686-w64-mingw32\include 538 // c:\mingw32\i686-w64-mingw32\include\c++ 539 // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32 540 // c:\mingw32\i686-w64-mingw32\include\c++\backward 541 542 // Windows, mingw-w64 msys2 543 // c:\msys64\mingw32\include 544 // c:\msys64\mingw32\i686-w64-mingw32\include 545 // c:\msys64\mingw32\include\c++\4.9.2 546 // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32 547 // c:\msys64\mingw32\include\c++\4.9.2\backward 548 549 // openSUSE 550 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++ 551 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32 552 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward 553 // /usr/x86_64-w64-mingw32/sys-root/mingw/include 554 555 // Arch Linux 556 // /usr/i686-w64-mingw32/include/c++/5.1.0 557 // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32 558 // /usr/i686-w64-mingw32/include/c++/5.1.0/backward 559 // /usr/i686-w64-mingw32/include 560 561 // Ubuntu 562 // /usr/include/c++/4.8 563 // /usr/include/c++/4.8/x86_64-w64-mingw32 564 // /usr/include/c++/4.8/backward 565 // /usr/x86_64-w64-mingw32/include 566 567 void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 568 ArgStringList &CC1Args) const { 569 if (DriverArgs.hasArg(options::OPT_nostdinc)) 570 return; 571 572 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 573 SmallString<1024> P(getDriver().ResourceDir); 574 llvm::sys::path::append(P, "include"); 575 addSystemInclude(DriverArgs, CC1Args, P.str()); 576 } 577 578 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 579 return; 580 581 if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) { 582 // openSUSE 583 addSystemInclude(DriverArgs, CC1Args, 584 Base + SubdirName + "/sys-root/mingw/include"); 585 } 586 587 addSystemInclude(DriverArgs, CC1Args, 588 Base + SubdirName + llvm::sys::path::get_separator() + 589 "include"); 590 addSystemInclude(DriverArgs, CC1Args, Base + "include"); 591 } 592 593 void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( 594 const ArgList &DriverArgs, ArgStringList &CC1Args) const { 595 if (DriverArgs.hasArg(options::OPT_nostdlibinc) || 596 DriverArgs.hasArg(options::OPT_nostdincxx)) 597 return; 598 599 StringRef Slash = llvm::sys::path::get_separator(); 600 601 switch (GetCXXStdlibType(DriverArgs)) { 602 case ToolChain::CST_Libcxx: { 603 std::string TargetDir = (Base + "include" + Slash + getTripleString() + 604 Slash + "c++" + Slash + "v1") 605 .str(); 606 if (getDriver().getVFS().exists(TargetDir)) 607 addSystemInclude(DriverArgs, CC1Args, TargetDir); 608 addSystemInclude(DriverArgs, CC1Args, 609 Base + SubdirName + Slash + "include" + Slash + "c++" + 610 Slash + "v1"); 611 addSystemInclude(DriverArgs, CC1Args, 612 Base + "include" + Slash + "c++" + Slash + "v1"); 613 break; 614 } 615 616 case ToolChain::CST_Libstdcxx: 617 llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases; 618 CppIncludeBases.emplace_back(Base); 619 llvm::sys::path::append(CppIncludeBases[0], SubdirName, "include", "c++"); 620 CppIncludeBases.emplace_back(Base); 621 llvm::sys::path::append(CppIncludeBases[1], SubdirName, "include", "c++", 622 Ver); 623 CppIncludeBases.emplace_back(Base); 624 llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver); 625 CppIncludeBases.emplace_back(GccLibDir); 626 llvm::sys::path::append(CppIncludeBases[3], "include", "c++"); 627 for (auto &CppIncludeBase : CppIncludeBases) { 628 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase); 629 CppIncludeBase += Slash; 630 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + SubdirName); 631 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward"); 632 } 633 break; 634 } 635 } 636 637 static bool testTriple(const Driver &D, const llvm::Triple &Triple, 638 const ArgList &Args) { 639 // If an explicit sysroot is set, that will be used and we shouldn't try to 640 // detect anything else. 641 std::string SubdirName; 642 if (D.SysRoot.size()) 643 return true; 644 if (llvm::ErrorOr<std::string> TargetSubdir = 645 findClangRelativeSysroot(D, Triple, SubdirName)) 646 return true; 647 if (llvm::ErrorOr<std::string> GPPName = findGcc(Triple)) 648 return true; 649 // If we neither found a colocated sysroot or a matching gcc executable, 650 // conclude that we can't know if this is the correct spelling of the triple. 651 return false; 652 } 653 654 static llvm::Triple adjustTriple(const Driver &D, const llvm::Triple &Triple, 655 const ArgList &Args) { 656 // First test if the original triple can find a sysroot with the triple 657 // name. 658 if (testTriple(D, Triple, Args)) 659 return Triple; 660 llvm::SmallVector<llvm::StringRef, 3> Archs; 661 // If not, test a couple other possible arch names that might be what was 662 // intended. 663 if (Triple.getArch() == llvm::Triple::x86) { 664 Archs.emplace_back("i386"); 665 Archs.emplace_back("i586"); 666 Archs.emplace_back("i686"); 667 } else if (Triple.getArch() == llvm::Triple::arm || 668 Triple.getArch() == llvm::Triple::thumb) { 669 Archs.emplace_back("armv7"); 670 } 671 for (auto A : Archs) { 672 llvm::Triple TestTriple(Triple); 673 TestTriple.setArchName(A); 674 if (testTriple(D, TestTriple, Args)) 675 return TestTriple; 676 } 677 // If none was found, just proceed with the original value. 678 return Triple; 679 } 680 681 void toolchains::MinGW::fixTripleArch(const Driver &D, llvm::Triple &Triple, 682 const ArgList &Args) { 683 if (Triple.getArch() == llvm::Triple::x86 || 684 Triple.getArch() == llvm::Triple::arm || 685 Triple.getArch() == llvm::Triple::thumb) 686 Triple = adjustTriple(D, Triple, Args); 687 } 688