Index: clang/lib/Driver/ToolChains/CommonArgs.h =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.h +++ 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, Index: clang/lib/Driver/ToolChains/CommonArgs.cpp =================================================================== --- clang/lib/Driver/ToolChains/CommonArgs.cpp +++ clang/lib/Driver/ToolChains/CommonArgs.cpp @@ -751,15 +751,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 @@ -767,7 +780,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, Index: clang/lib/Driver/ToolChains/Darwin.cpp =================================================================== --- clang/lib/Driver/ToolChains/Darwin.cpp +++ 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)) Index: clang/lib/Driver/ToolChains/Gnu.cpp =================================================================== --- clang/lib/Driver/ToolChains/Gnu.cpp +++ clang/lib/Driver/ToolChains/Gnu.cpp @@ -593,13 +593,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"); } Index: clang/lib/Driver/ToolChains/MSVC.cpp =================================================================== --- clang/lib/Driver/ToolChains/MSVC.cpp +++ 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()) { Index: clang/lib/Driver/ToolChains/MinGW.cpp =================================================================== --- clang/lib/Driver/ToolChains/MinGW.cpp +++ clang/lib/Driver/ToolChains/MinGW.cpp @@ -218,6 +218,11 @@ AddLinkerInputs(TC, Inputs, Args, CmdArgs, JA); + if (C.getDriver().IsFlangMode()) { + tools::addFortranRuntimeLibraryPath(TC, Args, CmdArgs); + tools::addFortranRuntimeLibs(TC, CmdArgs); + } + // TODO: Add profile stuff here if (TC.ShouldLinkCXXStdlib(Args)) { Index: flang/test/Driver/linker-flags.f90 =================================================================== --- flang/test/Driver/linker-flags.f90 +++ flang/test/Driver/linker-flags.f90 @@ -2,18 +2,15 @@ ! 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 COMMAND -!------------ +!------------- +! RUN COMMANDS +!------------- ! 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 that `--ld-path` is ignored on some systems. +! RUN: %flang -### -flang-experimental-exec -target %flangarch%-linux-gnu --ld-path=/usr/bin/ld %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,GNU,WITHLM +! RUN: %flang -### -flang-experimental-exec -target %flangarch%-apple-darwin --ld-path=/usr/bin/ld %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,GNU +! RUN: %flang -### -flang-experimental-exec -target %flangarch%-windows-gnu --ld-path=/usr/bin/ld %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,GNU +! RUN: %flang -### -flang-experimental-exec -target %flangarch%-windows-msvc %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC !---------------- ! EXPECTED OUTPUT @@ -22,10 +19,21 @@ ! CHECK-LABEL: {{.*}} "-emit-obj" ! 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 +! Linker invocation to generate the executable - GNU version +! GNU-LABEL: "/usr/bin/ld" +! GNU-SAME: "[[object_file]]" +! GNU-SAME: -lFortran_main +! GNU-SAME: -lFortranRuntime +! GNU-SAME: -lFortranDecimal +! WITHLM-SAME: -lm + +! Linker invocation to generate the executable - MSVC version +! NOTE: This check should also match if the default linker is lld-link.exe +! MSVC-LABEL: link.exe +! MSVC-NOT: libcmt +! MSVC-NOT: oldnames +! MSVC-SAME: Fortran_main.lib +! MSVC-SAME: FortranRuntime.lib +! MSVC-SAME: FortranDecimal.lib +! MSVC-SAME: /subsystem:console +! MSVC-SAME: "[[object_file]]" Index: flang/test/lit.cfg.py =================================================================== --- flang/test/lit.cfg.py +++ flang/test/lit.cfg.py @@ -45,6 +45,17 @@ for arch in config.targets_to_build.split(): config.available_features.add(arch.lower() + '-registered-target') +# Some driver tests need to use a supported and registered architecture as part +# of the target triple, so we define a substitution for it. Note that it doesn't +# matter which of the supported targets is used as long as it is enabled in +# LLVM_TARGETS_TO_BUILD. +if 'AArch64' in config.targets: + config.substitutions.append(('%flangarch%', 'aarch64')) +elif 'PowerPC' in config.targets: + config.substitutions.append(('%flangarch%', 'ppc64le')) +elif 'X86' in config.targets: + config.substitutions.append(('%flangarch%', 'x86_64')) + # excludes: A list of directories to exclude from the testsuite. The 'Inputs' # subdirectories contain auxiliary inputs for various tests in their parent # directories.