1 //===--- MinGW.cpp - MinGWToolChain Implementation ------------------------===// 2 // 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 "MinGW.h" 11 #include "InputInfo.h" 12 #include "CommonArgs.h" 13 #include "clang/Driver/Compilation.h" 14 #include "clang/Driver/Driver.h" 15 #include "clang/Driver/DriverDiagnostic.h" 16 #include "clang/Driver/Options.h" 17 #include "llvm/Option/ArgList.h" 18 #include "llvm/Support/FileSystem.h" 19 #include "llvm/Support/Path.h" 20 #include <system_error> 21 22 using namespace clang::diag; 23 using namespace clang::driver; 24 using namespace clang; 25 using namespace llvm::opt; 26 27 /// MinGW Tools 28 void tools::MinGW::Assembler::ConstructJob(Compilation &C, const JobAction &JA, 29 const InputInfo &Output, 30 const InputInfoList &Inputs, 31 const ArgList &Args, 32 const char *LinkingOutput) const { 33 claimNoWarnArgs(Args); 34 ArgStringList CmdArgs; 35 36 if (getToolChain().getArch() == llvm::Triple::x86) { 37 CmdArgs.push_back("--32"); 38 } else if (getToolChain().getArch() == llvm::Triple::x86_64) { 39 CmdArgs.push_back("--64"); 40 } 41 42 Args.AddAllArgValues(CmdArgs, options::OPT_Wa_COMMA, options::OPT_Xassembler); 43 44 CmdArgs.push_back("-o"); 45 CmdArgs.push_back(Output.getFilename()); 46 47 for (const auto &II : Inputs) 48 CmdArgs.push_back(II.getFilename()); 49 50 const char *Exec = Args.MakeArgString(getToolChain().GetProgramPath("as")); 51 C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); 52 53 if (Args.hasArg(options::OPT_gsplit_dwarf)) 54 SplitDebugInfo(getToolChain(), C, *this, JA, Args, Output, 55 SplitDebugName(Args, Inputs[0])); 56 } 57 58 void tools::MinGW::Linker::AddLibGCC(const ArgList &Args, 59 ArgStringList &CmdArgs) const { 60 if (Args.hasArg(options::OPT_mthreads)) 61 CmdArgs.push_back("-lmingwthrd"); 62 CmdArgs.push_back("-lmingw32"); 63 64 // Make use of compiler-rt if --rtlib option is used 65 ToolChain::RuntimeLibType RLT = getToolChain().GetRuntimeLibType(Args); 66 if (RLT == ToolChain::RLT_Libgcc) { 67 bool Static = Args.hasArg(options::OPT_static_libgcc) || 68 Args.hasArg(options::OPT_static); 69 bool Shared = Args.hasArg(options::OPT_shared); 70 bool CXX = getToolChain().getDriver().CCCIsCXX(); 71 72 if (Static || (!CXX && !Shared)) { 73 CmdArgs.push_back("-lgcc"); 74 CmdArgs.push_back("-lgcc_eh"); 75 } else { 76 CmdArgs.push_back("-lgcc_s"); 77 CmdArgs.push_back("-lgcc"); 78 } 79 } else { 80 AddRunTimeLibs(getToolChain(), getToolChain().getDriver(), CmdArgs, Args); 81 } 82 83 CmdArgs.push_back("-lmoldname"); 84 CmdArgs.push_back("-lmingwex"); 85 CmdArgs.push_back("-lmsvcrt"); 86 } 87 88 void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA, 89 const InputInfo &Output, 90 const InputInfoList &Inputs, 91 const ArgList &Args, 92 const char *LinkingOutput) const { 93 const ToolChain &TC = getToolChain(); 94 const Driver &D = TC.getDriver(); 95 // const SanitizerArgs &Sanitize = TC.getSanitizerArgs(); 96 97 ArgStringList CmdArgs; 98 99 // Silence warning for "clang -g foo.o -o foo" 100 Args.ClaimAllArgs(options::OPT_g_Group); 101 // and "clang -emit-llvm foo.o -o foo" 102 Args.ClaimAllArgs(options::OPT_emit_llvm); 103 // and for "clang -w foo.o -o foo". Other warning options are already 104 // handled somewhere else. 105 Args.ClaimAllArgs(options::OPT_w); 106 107 StringRef LinkerName = Args.getLastArgValue(options::OPT_fuse_ld_EQ, "ld"); 108 if (LinkerName.equals_lower("lld")) { 109 CmdArgs.push_back("-flavor"); 110 CmdArgs.push_back("gnu"); 111 } else if (!LinkerName.equals_lower("ld")) { 112 D.Diag(diag::err_drv_unsupported_linker) << LinkerName; 113 } 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 if (TC.getArch() == llvm::Triple::x86) 123 CmdArgs.push_back("i386pe"); 124 if (TC.getArch() == llvm::Triple::x86_64) 125 CmdArgs.push_back("i386pep"); 126 if (TC.getArch() == llvm::Triple::arm) 127 CmdArgs.push_back("thumb2pe"); 128 129 if (Args.hasArg(options::OPT_mwindows)) { 130 CmdArgs.push_back("--subsystem"); 131 CmdArgs.push_back("windows"); 132 } else if (Args.hasArg(options::OPT_mconsole)) { 133 CmdArgs.push_back("--subsystem"); 134 CmdArgs.push_back("console"); 135 } 136 137 if (Args.hasArg(options::OPT_static)) 138 CmdArgs.push_back("-Bstatic"); 139 else { 140 if (Args.hasArg(options::OPT_mdll)) 141 CmdArgs.push_back("--dll"); 142 else if (Args.hasArg(options::OPT_shared)) 143 CmdArgs.push_back("--shared"); 144 CmdArgs.push_back("-Bdynamic"); 145 if (Args.hasArg(options::OPT_mdll) || Args.hasArg(options::OPT_shared)) { 146 CmdArgs.push_back("-e"); 147 if (TC.getArch() == llvm::Triple::x86) 148 CmdArgs.push_back("_DllMainCRTStartup@12"); 149 else 150 CmdArgs.push_back("DllMainCRTStartup"); 151 CmdArgs.push_back("--enable-auto-image-base"); 152 } 153 } 154 155 CmdArgs.push_back("-o"); 156 CmdArgs.push_back(Output.getFilename()); 157 158 Args.AddAllArgs(CmdArgs, options::OPT_e); 159 // FIXME: add -N, -n flags 160 Args.AddLastArg(CmdArgs, options::OPT_r); 161 Args.AddLastArg(CmdArgs, options::OPT_s); 162 Args.AddLastArg(CmdArgs, options::OPT_t); 163 Args.AddAllArgs(CmdArgs, options::OPT_u_Group); 164 Args.AddLastArg(CmdArgs, options::OPT_Z_Flag); 165 166 if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles)) { 167 if (Args.hasArg(options::OPT_shared) || Args.hasArg(options::OPT_mdll)) { 168 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("dllcrt2.o"))); 169 } else { 170 if (Args.hasArg(options::OPT_municode)) 171 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2u.o"))); 172 else 173 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crt2.o"))); 174 } 175 if (Args.hasArg(options::OPT_pg)) 176 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("gcrt2.o"))); 177 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtbegin.o"))); 178 } 179 180 Args.AddAllArgs(CmdArgs, options::OPT_L); 181 TC.AddFilePathLibArgs(Args, CmdArgs); 182 AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); 183 184 // TODO: Add ASan stuff here 185 186 // TODO: Add profile stuff here 187 188 if (D.CCCIsCXX() && 189 !Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) { 190 bool OnlyLibstdcxxStatic = Args.hasArg(options::OPT_static_libstdcxx) && 191 !Args.hasArg(options::OPT_static); 192 if (OnlyLibstdcxxStatic) 193 CmdArgs.push_back("-Bstatic"); 194 TC.AddCXXStdlibLibArgs(Args, CmdArgs); 195 if (OnlyLibstdcxxStatic) 196 CmdArgs.push_back("-Bdynamic"); 197 } 198 199 if (!Args.hasArg(options::OPT_nostdlib)) { 200 if (!Args.hasArg(options::OPT_nodefaultlibs)) { 201 if (Args.hasArg(options::OPT_static)) 202 CmdArgs.push_back("--start-group"); 203 204 if (Args.hasArg(options::OPT_fstack_protector) || 205 Args.hasArg(options::OPT_fstack_protector_strong) || 206 Args.hasArg(options::OPT_fstack_protector_all)) { 207 CmdArgs.push_back("-lssp_nonshared"); 208 CmdArgs.push_back("-lssp"); 209 } 210 if (Args.hasArg(options::OPT_fopenmp)) 211 CmdArgs.push_back("-lgomp"); 212 213 AddLibGCC(Args, CmdArgs); 214 215 if (Args.hasArg(options::OPT_pg)) 216 CmdArgs.push_back("-lgmon"); 217 218 if (Args.hasArg(options::OPT_pthread)) 219 CmdArgs.push_back("-lpthread"); 220 221 // add system libraries 222 if (Args.hasArg(options::OPT_mwindows)) { 223 CmdArgs.push_back("-lgdi32"); 224 CmdArgs.push_back("-lcomdlg32"); 225 } 226 CmdArgs.push_back("-ladvapi32"); 227 CmdArgs.push_back("-lshell32"); 228 CmdArgs.push_back("-luser32"); 229 CmdArgs.push_back("-lkernel32"); 230 231 if (Args.hasArg(options::OPT_static)) 232 CmdArgs.push_back("--end-group"); 233 else if (!LinkerName.equals_lower("lld")) 234 AddLibGCC(Args, CmdArgs); 235 } 236 237 if (!Args.hasArg(options::OPT_nostartfiles)) { 238 // Add crtfastmath.o if available and fast math is enabled. 239 TC.AddFastMathRuntimeIfAvailable(Args, CmdArgs); 240 241 CmdArgs.push_back(Args.MakeArgString(TC.GetFilePath("crtend.o"))); 242 } 243 } 244 const char *Exec = Args.MakeArgString(TC.GetProgramPath(LinkerName.data())); 245 C.addCommand(llvm::make_unique<Command>(JA, *this, Exec, CmdArgs, Inputs)); 246 } 247 248 // Simplified from Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple. 249 static bool findGccVersion(StringRef LibDir, std::string &GccLibDir, 250 std::string &Ver) { 251 auto Version = toolchains::Generic_GCC::GCCVersion::Parse("0.0.0"); 252 std::error_code EC; 253 for (llvm::sys::fs::directory_iterator LI(LibDir, EC), LE; !EC && LI != LE; 254 LI = LI.increment(EC)) { 255 StringRef VersionText = llvm::sys::path::filename(LI->path()); 256 auto CandidateVersion = 257 toolchains::Generic_GCC::GCCVersion::Parse(VersionText); 258 if (CandidateVersion.Major == -1) 259 continue; 260 if (CandidateVersion <= Version) 261 continue; 262 Ver = VersionText; 263 GccLibDir = LI->path(); 264 } 265 return Ver.size(); 266 } 267 268 void toolchains::MinGW::findGccLibDir() { 269 llvm::SmallVector<llvm::SmallString<32>, 2> Archs; 270 Archs.emplace_back(getTriple().getArchName()); 271 Archs[0] += "-w64-mingw32"; 272 Archs.emplace_back("mingw32"); 273 Arch = Archs[0].str(); 274 // lib: Arch Linux, Ubuntu, Windows 275 // lib64: openSUSE Linux 276 for (StringRef CandidateLib : {"lib", "lib64"}) { 277 for (StringRef CandidateArch : Archs) { 278 llvm::SmallString<1024> LibDir(Base); 279 llvm::sys::path::append(LibDir, CandidateLib, "gcc", CandidateArch); 280 if (findGccVersion(LibDir, GccLibDir, Ver)) { 281 Arch = CandidateArch; 282 return; 283 } 284 } 285 } 286 } 287 288 llvm::ErrorOr<std::string> toolchains::MinGW::findGcc() { 289 llvm::SmallVector<llvm::SmallString<32>, 2> Gccs; 290 Gccs.emplace_back(getTriple().getArchName()); 291 Gccs[0] += "-w64-mingw32-gcc"; 292 Gccs.emplace_back("mingw32-gcc"); 293 // Please do not add "gcc" here 294 for (StringRef CandidateGcc : Gccs) 295 if (llvm::ErrorOr<std::string> GPPName = llvm::sys::findProgramByName(CandidateGcc)) 296 return GPPName; 297 return make_error_code(std::errc::no_such_file_or_directory); 298 } 299 300 toolchains::MinGW::MinGW(const Driver &D, const llvm::Triple &Triple, 301 const ArgList &Args) 302 : ToolChain(D, Triple, Args), CudaInstallation(D, Triple, Args) { 303 getProgramPaths().push_back(getDriver().getInstalledDir()); 304 305 if (getDriver().SysRoot.size()) 306 Base = getDriver().SysRoot; 307 else if (llvm::ErrorOr<std::string> GPPName = findGcc()) 308 Base = llvm::sys::path::parent_path( 309 llvm::sys::path::parent_path(GPPName.get())); 310 else 311 Base = llvm::sys::path::parent_path(getDriver().getInstalledDir()); 312 313 Base += llvm::sys::path::get_separator(); 314 findGccLibDir(); 315 // GccLibDir must precede Base/lib so that the 316 // correct crtbegin.o ,cetend.o would be found. 317 getFilePaths().push_back(GccLibDir); 318 getFilePaths().push_back( 319 (Base + Arch + llvm::sys::path::get_separator() + "lib").str()); 320 getFilePaths().push_back(Base + "lib"); 321 // openSUSE 322 getFilePaths().push_back(Base + Arch + "/sys-root/mingw/lib"); 323 } 324 325 bool toolchains::MinGW::IsIntegratedAssemblerDefault() const { return true; } 326 327 Tool *toolchains::MinGW::getTool(Action::ActionClass AC) const { 328 switch (AC) { 329 case Action::PreprocessJobClass: 330 if (!Preprocessor) 331 Preprocessor.reset(new tools::gcc::Preprocessor(*this)); 332 return Preprocessor.get(); 333 case Action::CompileJobClass: 334 if (!Compiler) 335 Compiler.reset(new tools::gcc::Compiler(*this)); 336 return Compiler.get(); 337 default: 338 return ToolChain::getTool(AC); 339 } 340 } 341 342 Tool *toolchains::MinGW::buildAssembler() const { 343 return new tools::MinGW::Assembler(*this); 344 } 345 346 Tool *toolchains::MinGW::buildLinker() const { 347 return new tools::MinGW::Linker(*this); 348 } 349 350 bool toolchains::MinGW::IsUnwindTablesDefault() const { 351 return getArch() == llvm::Triple::x86_64; 352 } 353 354 bool toolchains::MinGW::isPICDefault() const { 355 return getArch() == llvm::Triple::x86_64; 356 } 357 358 bool toolchains::MinGW::isPIEDefault() const { return false; } 359 360 bool toolchains::MinGW::isPICDefaultForced() const { 361 return getArch() == llvm::Triple::x86_64; 362 } 363 364 bool toolchains::MinGW::UseSEHExceptions() const { 365 return getArch() == llvm::Triple::x86_64; 366 } 367 368 void toolchains::MinGW::AddCudaIncludeArgs(const ArgList &DriverArgs, 369 ArgStringList &CC1Args) const { 370 CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); 371 } 372 373 void toolchains::MinGW::printVerboseInfo(raw_ostream &OS) const { 374 CudaInstallation.print(OS); 375 } 376 377 // Include directories for various hosts: 378 379 // Windows, mingw.org 380 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++ 381 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\mingw32 382 // c:\mingw\lib\gcc\mingw32\4.8.1\include\c++\backward 383 // c:\mingw\include 384 // c:\mingw\mingw32\include 385 386 // Windows, mingw-w64 mingw-builds 387 // c:\mingw32\i686-w64-mingw32\include 388 // c:\mingw32\i686-w64-mingw32\include\c++ 389 // c:\mingw32\i686-w64-mingw32\include\c++\i686-w64-mingw32 390 // c:\mingw32\i686-w64-mingw32\include\c++\backward 391 392 // Windows, mingw-w64 msys2 393 // c:\msys64\mingw32\include 394 // c:\msys64\mingw32\i686-w64-mingw32\include 395 // c:\msys64\mingw32\include\c++\4.9.2 396 // c:\msys64\mingw32\include\c++\4.9.2\i686-w64-mingw32 397 // c:\msys64\mingw32\include\c++\4.9.2\backward 398 399 // openSUSE 400 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++ 401 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/x86_64-w64-mingw32 402 // /usr/lib64/gcc/x86_64-w64-mingw32/5.1.0/include/c++/backward 403 // /usr/x86_64-w64-mingw32/sys-root/mingw/include 404 405 // Arch Linux 406 // /usr/i686-w64-mingw32/include/c++/5.1.0 407 // /usr/i686-w64-mingw32/include/c++/5.1.0/i686-w64-mingw32 408 // /usr/i686-w64-mingw32/include/c++/5.1.0/backward 409 // /usr/i686-w64-mingw32/include 410 411 // Ubuntu 412 // /usr/include/c++/4.8 413 // /usr/include/c++/4.8/x86_64-w64-mingw32 414 // /usr/include/c++/4.8/backward 415 // /usr/x86_64-w64-mingw32/include 416 417 void toolchains::MinGW::AddClangSystemIncludeArgs(const ArgList &DriverArgs, 418 ArgStringList &CC1Args) const { 419 if (DriverArgs.hasArg(options::OPT_nostdinc)) 420 return; 421 422 if (!DriverArgs.hasArg(options::OPT_nobuiltininc)) { 423 SmallString<1024> P(getDriver().ResourceDir); 424 llvm::sys::path::append(P, "include"); 425 addSystemInclude(DriverArgs, CC1Args, P.str()); 426 } 427 428 if (DriverArgs.hasArg(options::OPT_nostdlibinc)) 429 return; 430 431 if (GetRuntimeLibType(DriverArgs) == ToolChain::RLT_Libgcc) { 432 // openSUSE 433 addSystemInclude(DriverArgs, CC1Args, 434 Base + Arch + "/sys-root/mingw/include"); 435 } 436 437 addSystemInclude(DriverArgs, CC1Args, 438 Base + Arch + llvm::sys::path::get_separator() + "include"); 439 addSystemInclude(DriverArgs, CC1Args, Base + "include"); 440 } 441 442 void toolchains::MinGW::AddClangCXXStdlibIncludeArgs( 443 const ArgList &DriverArgs, ArgStringList &CC1Args) const { 444 if (DriverArgs.hasArg(options::OPT_nostdlibinc) || 445 DriverArgs.hasArg(options::OPT_nostdincxx)) 446 return; 447 448 switch (GetCXXStdlibType(DriverArgs)) { 449 case ToolChain::CST_Libcxx: 450 addSystemInclude(DriverArgs, CC1Args, 451 Base + "include" + llvm::sys::path::get_separator() + 452 "c++" + llvm::sys::path::get_separator() + "v1"); 453 break; 454 455 case ToolChain::CST_Libstdcxx: 456 llvm::SmallVector<llvm::SmallString<1024>, 4> CppIncludeBases; 457 CppIncludeBases.emplace_back(Base); 458 llvm::sys::path::append(CppIncludeBases[0], Arch, "include", "c++"); 459 CppIncludeBases.emplace_back(Base); 460 llvm::sys::path::append(CppIncludeBases[1], Arch, "include", "c++", Ver); 461 CppIncludeBases.emplace_back(Base); 462 llvm::sys::path::append(CppIncludeBases[2], "include", "c++", Ver); 463 CppIncludeBases.emplace_back(GccLibDir); 464 llvm::sys::path::append(CppIncludeBases[3], "include", "c++"); 465 for (auto &CppIncludeBase : CppIncludeBases) { 466 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase); 467 CppIncludeBase += llvm::sys::path::get_separator(); 468 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + Arch); 469 addSystemInclude(DriverArgs, CC1Args, CppIncludeBase + "backward"); 470 } 471 break; 472 } 473 } 474