diff --git a/lib/Driver/ToolChains/CommonArgs.cpp b/lib/Driver/ToolChains/CommonArgs.cpp index 535ae12193a5..59beec5b5959 100644 --- a/lib/Driver/ToolChains/CommonArgs.cpp +++ b/lib/Driver/ToolChains/CommonArgs.cpp @@ -67,7 +67,7 @@ bool tools::needFortranLibs(const Driver &D, const ArgList &Args) { } /// \brief Determine if Fortran "main" object is needed -static bool needFortranMain(const Driver &D, const ArgList &Args) { +bool tools::needFortranMain(const Driver &D, const ArgList &Args) { return (needFortranLibs(D, Args) && (!Args.hasArg(options::OPT_Mnomain) || !Args.hasArg(options::OPT_no_fortran_main))); diff --git a/lib/Driver/ToolChains/CommonArgs.h b/lib/Driver/ToolChains/CommonArgs.h index 6e1ed090611e..815b3faf5f77 100644 --- a/lib/Driver/ToolChains/CommonArgs.h +++ b/lib/Driver/ToolChains/CommonArgs.h @@ -22,6 +22,8 @@ namespace tools { bool needFortranLibs(const Driver &D, const llvm::opt::ArgList &Args); +bool needFortranMain(const Driver &D, const llvm::opt::ArgList &Args); + void addPathIfExists(const Driver &D, const Twine &Path, ToolChain::path_list &Paths); diff --git a/lib/Driver/ToolChains/Flang.cpp b/lib/Driver/ToolChains/Flang.cpp index fb44cdcbc1aa..968ec8f5f49f 100644 --- a/lib/Driver/ToolChains/Flang.cpp +++ b/lib/Driver/ToolChains/Flang.cpp @@ -1050,6 +1050,14 @@ if(Args.getAllArgValues(options::OPT_fopenmp_targets_EQ).size() > 0) { LowerCmdArgs.push_back(Args.MakeArgString(OutFile)); } + bool IsWindowsMSVC = getToolChain().getTriple().isWindowsMSVCEnvironment(); + if (IsWindowsMSVC && !Args.hasArg(options::OPT_noFlangLibs)) { + getToolChain().AddFortranStdlibLibArgs(Args, LowerCmdArgs); + for (auto Arg : Args.filtered(options::OPT_noFlangLibs)) { + Arg->claim(); + } + } + C.addCommand(llvm::make_unique(JA, *this, LowerExec, LowerCmdArgs, Inputs)); } diff --git a/lib/Driver/ToolChains/MSVC.cpp b/lib/Driver/ToolChains/MSVC.cpp index ae41ee9e22cf..d1cde6496567 100644 --- a/lib/Driver/ToolChains/MSVC.cpp +++ b/lib/Driver/ToolChains/MSVC.cpp @@ -326,7 +326,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, Args.MakeArgString(std::string("-out:") + Output.getFilename())); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) && - !C.getDriver().IsCLMode()) + !C.getDriver().IsCLMode() && !C.getDriver().IsFortranMode()) CmdArgs.push_back("-defaultlib:libcmt"); if (!llvm::sys::Process::GetEnv("LIB")) { @@ -426,6 +426,11 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA, } } + if (C.getDriver().IsFortranMode()) { + CmdArgs.push_back(Args.MakeArgString(std::string("-libpath:") + + TC.getDriver().Dir + "/../lib")); + } + // Add compiler-rt lib in case if it was explicitly // specified as an argument for --rtlib option. if (!Args.hasArg(options::OPT_nostdlib)) { @@ -736,6 +741,85 @@ void MSVCToolChain::AddCudaIncludeArgs(const ArgList &DriverArgs, CudaInstallation.AddCudaIncludeArgs(DriverArgs, CC1Args); } + +void MSVCToolChain::AddFortranStdlibLibArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + bool staticFlangLibs = false; + bool useOpenMP = false; + + if (Args.hasArg(options::OPT_staticFlangLibs)) { + for (auto *A: Args.filtered(options::OPT_staticFlangLibs)) { + A->claim(); + staticFlangLibs = true; + } + } + + Arg *A = Args.getLastArg(options::OPT_mp, options::OPT_nomp, + options::OPT_fopenmp, options::OPT_fno_openmp); + if (A && + (A->getOption().matches(options::OPT_mp) || + A->getOption().matches(options::OPT_fopenmp))) { + useOpenMP = true; + } + + if (needFortranMain(getDriver(), Args)) { + // flangmain is always static + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/subsystem:console"); + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:flangmain.lib"); + } + + if (staticFlangLibs) { + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:libflang.lib"); + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:libflangrti.lib"); + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:libpgmath.lib"); + } else { + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:flang.lib"); + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:flangrti.lib"); + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:pgmath.lib"); + } + if (useOpenMP) { + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/nodefaultlib:vcomp.lib"); + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/nodefaultlib:vcompd.lib"); + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:libomp.lib"); + } + else { + if (staticFlangLibs) { + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:libompstub.lib"); + } else { + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:ompstub.lib"); + } + } + + // Allways link Fortran executables with Pthreads + // CmdArgs.push_back("-lpthread"); + + // These options are added clang-cl in Clang.cpp for C/C++ + // In clang-cl.exe -MD and -MT control these options, but in + // flang.exe like clang.exe these are different options for + // dependency tracking. Let's assume that if somebody needs + // static flang libs, they need static runtime libs as well. + if (staticFlangLibs) { + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:libcmt.lib"); + } else { + CmdArgs.push_back("-linker"); + CmdArgs.push_back("/defaultlib:msvcrt.lib"); + } +} + void MSVCToolChain::printVerboseInfo(raw_ostream &OS) const { CudaInstallation.print(OS); } diff --git a/lib/Driver/ToolChains/MSVC.h b/lib/Driver/ToolChains/MSVC.h index 854f88a36fd2..b7c89090e175 100644 --- a/lib/Driver/ToolChains/MSVC.h +++ b/lib/Driver/ToolChains/MSVC.h @@ -109,6 +109,9 @@ class LLVM_LIBRARY_VISIBILITY MSVCToolChain : public ToolChain { void AddCudaIncludeArgs(const llvm::opt::ArgList &DriverArgs, llvm::opt::ArgStringList &CC1Args) const override; + void AddFortranStdlibLibArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const override; + bool getWindowsSDKLibraryPath(std::string &path) const; /// \brief Check if Universal CRT should be used if available bool getUniversalCRTLibraryPath(std::string &path) const;