diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h --- a/clang/lib/Driver/ToolChains/CommonArgs.h +++ b/clang/lib/Driver/ToolChains/CommonArgs.h @@ -121,7 +121,8 @@ bool IsOffloadingHost = false, bool GompNeedsRT = false); /// Adds Fortran runtime libraries to \p CmdArgs. -void addFortranRuntimeLibs(llvm::opt::ArgStringList &CmdArgs); +void addFortranRuntimeLibs(const ToolChain &TC, + llvm::opt::ArgStringList &CmdArgs); /// Adds the path for the Fortran runtime libraries to \p CmdArgs. void addFortranRuntimeLibraryPath(const ToolChain &TC, diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp --- a/clang/lib/Driver/ToolChains/CommonArgs.cpp +++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -739,15 +739,28 @@ return true; } -void tools::addFortranRuntimeLibs(llvm::opt::ArgStringList &CmdArgs) { - CmdArgs.push_back("-lFortran_main"); - CmdArgs.push_back("-lFortranRuntime"); - CmdArgs.push_back("-lFortranDecimal"); +void tools::addFortranRuntimeLibs(const ToolChain &TC, + llvm::opt::ArgStringList &CmdArgs) { + if (TC.getTriple().isKnownWindowsMSVCEnvironment()) { + CmdArgs.push_back("Fortran_main.lib"); + CmdArgs.push_back("FortranRuntime.lib"); + CmdArgs.push_back("FortranDecimal.lib"); + } else { + CmdArgs.push_back("-lFortran_main"); + CmdArgs.push_back("-lFortranRuntime"); + CmdArgs.push_back("-lFortranDecimal"); + } } void tools::addFortranRuntimeLibraryPath(const ToolChain &TC, const llvm::opt::ArgList &Args, ArgStringList &CmdArgs) { + // NOTE: Generating executables by Flang is considered an "experimental" + // feature and hence this is guarded with a command line option. + // TODO: Make this work unconditionally once Flang is mature enough. + if (!Args.hasArg(options::OPT_flang_experimental_exec)) + return; + // Default to the /../lib directory. This works fine on the // platforms that we have tested so far. We will probably have to re-fine // this in the future. In particular, on some platforms, we may need to use @@ -755,7 +768,10 @@ SmallString<256> DefaultLibPath = llvm::sys::path::parent_path(TC.getDriver().Dir); llvm::sys::path::append(DefaultLibPath, "lib"); - CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath)); + if (TC.getTriple().isKnownWindowsMSVCEnvironment()) + CmdArgs.push_back(Args.MakeArgString("-libpath:" + DefaultLibPath)); + else + CmdArgs.push_back(Args.MakeArgString("-L" + DefaultLibPath)); } static void addSanitizerRuntime(const ToolChain &TC, const ArgList &Args, diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp --- a/clang/lib/Driver/ToolChains/Darwin.cpp +++ b/clang/lib/Driver/ToolChains/Darwin.cpp @@ -637,14 +637,9 @@ // Additional linker set-up and flags for Fortran. This is required in order // to generate executables. - // - // NOTE: Generating executables by Flang is considered an "experimental" - // feature and hence this is guarded with a command line option. - // TODO: Make this work unconditionally once Flang is mature enough. - if (getToolChain().getDriver().IsFlangMode() && - Args.hasArg(options::OPT_flang_experimental_exec)) { + if (getToolChain().getDriver().IsFlangMode()) { addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs); - addFortranRuntimeLibs(CmdArgs); + addFortranRuntimeLibs(getToolChain(), CmdArgs); } if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs)) diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp --- a/clang/lib/Driver/ToolChains/Gnu.cpp +++ b/clang/lib/Driver/ToolChains/Gnu.cpp @@ -596,13 +596,9 @@ // to generate executables. As Fortran runtime depends on the C runtime, // these dependencies need to be listed before the C runtime below (i.e. // AddRuntTimeLibs). - // - // NOTE: Generating executables by Flang is considered an "experimental" - // feature and hence this is guarded with a command line option. - // TODO: Make this work unconditionally once Flang is mature enough. - if (D.IsFlangMode() && Args.hasArg(options::OPT_flang_experimental_exec)) { + if (D.IsFlangMode()) { addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs); - addFortranRuntimeLibs(CmdArgs); + addFortranRuntimeLibs(ToolChain, CmdArgs); CmdArgs.push_back("-lm"); } diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp --- a/clang/lib/Driver/ToolChains/MSVC.cpp +++ b/clang/lib/Driver/ToolChains/MSVC.cpp @@ -81,7 +81,7 @@ Args.MakeArgString(std::string("-out:") + Output.getFilename())); if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nostartfiles) && - !C.getDriver().IsCLMode()) { + !C.getDriver().IsCLMode() && !C.getDriver().IsFlangMode()) { CmdArgs.push_back("-defaultlib:libcmt"); CmdArgs.push_back("-defaultlib:oldnames"); } @@ -130,6 +130,16 @@ Args.MakeArgString(std::string("-libpath:") + WindowsSdkLibPath)); } + if (C.getDriver().IsFlangMode()) { + addFortranRuntimeLibraryPath(TC, Args, CmdArgs); + addFortranRuntimeLibs(TC, CmdArgs); + + // Inform the MSVC linker that we're generating a console application, i.e. + // one with `main` as the "user-defined" entry point. The `main` function is + // defined in flang's runtime libraries. + CmdArgs.push_back("/subsystem:console"); + } + // Add the compiler-rt library directories to libpath if they exist to help // the linker find the various sanitizer, builtin, and profiling runtimes. for (const auto &LibPath : TC.getLibraryPaths()) { diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp --- a/clang/lib/Driver/ToolChains/MinGW.cpp +++ b/clang/lib/Driver/ToolChains/MinGW.cpp @@ -218,6 +218,11 @@ AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); + if (C.getDriver().IsFlangMode()) { + addFortranRuntimeLibraryPath(TC, Args, CmdArgs); + addFortranRuntimeLibs(TC, CmdArgs); + } + // TODO: Add profile stuff here if (TC.ShouldLinkCXXStdlib(Args)) { diff --git a/flang/test/Driver/linker-flags.f90 b/flang/test/Driver/linker-flags.f90 --- a/flang/test/Driver/linker-flags.f90 +++ b/flang/test/Driver/linker-flags.f90 @@ -2,18 +2,18 @@ ! invocation. These libraries are added on top of other standard runtime ! libraries that the Clang driver will include. -! NOTE: The additional linker flags tested here are currently only specified for -! GNU and Darwin. The following line will make sure that this test is skipped on -! Windows. If you are running this test on a yet another platform and it is -! failing for you, please either update the following or (preferably) update the -! linker invocation accordingly. -! UNSUPPORTED: system-windows +!------------- +! RUN COMMANDS +!------------- +! RUN: %flang -### -flang-experimental-exec -target ppc64le-linux-gnu %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,GNU +! RUN: %flang -### -flang-experimental-exec -target aarch64-apple-darwin %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,DARWIN +! RUN: %flang -### -flang-experimental-exec -target x86_64-windows-gnu %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MINGW -!------------ -! RUN COMMAND -!------------ -! Use `--ld-path` so that the linker location (used in the LABEL below) is deterministic. -! RUN: %flang -### -flang-experimental-exec --ld-path=/usr/bin/ld %S/Inputs/hello.f90 2>&1 | FileCheck %s +! NOTE: Clang's driver library, clangDriver, usually adds 'libcmt' and +! 'oldnames' on Windows, but they are not needed when compiling +! Fortran code and they might bring in additional dependencies. +! Make sure they're not added. +! RUN: %flang -### -flang-experimental-exec -target aarch64-windows-msvc %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC --implicit-check-not libcmt --implicit-check-not oldnames !---------------- ! EXPECTED OUTPUT @@ -23,9 +23,29 @@ ! CHECK-SAME: "-o" "[[object_file:.*\.o]]" {{.*}}Inputs/hello.f90 ! Linker invocation to generate the executable -! CHECK-LABEL: "/usr/bin/ld" -! CHECK-SAME: "[[object_file]]" -! CHECK-SAME: -lFortran_main -! CHECK-SAME: -lFortranRuntime -! CHECK-SAME: -lFortranDecimal -! CHECK-SAME: -lm +! GNU-LABEL: "{{.*}}ld" +! GNU-SAME: "[[object_file]]" +! GNU-SAME: -lFortran_main +! GNU-SAME: -lFortranRuntime +! GNU-SAME: -lFortranDecimal +! GNU-SAME: -lm + +! DARWIN-LABEL: "{{.*}}ld" +! DARWIN-SAME: "[[object_file]]" +! DARWIN-SAME: -lFortran_main +! DARWIN-SAME: -lFortranRuntime +! DARWIN-SAME: -lFortranDecimal + +! MINGW-LABEL: "{{.*}}ld" +! MINGW-SAME: "[[object_file]]" +! MINGW-SAME: -lFortran_main +! MINGW-SAME: -lFortranRuntime +! MINGW-SAME: -lFortranDecimal + +! NOTE: This check should also match if the default linker is lld-link.exe +! MSVC-LABEL: link.exe +! MSVC-SAME: Fortran_main.lib +! MSVC-SAME: FortranRuntime.lib +! MSVC-SAME: FortranDecimal.lib +! MSVC-SAME: /subsystem:console +! MSVC-SAME: "[[object_file]]"