[clang] 26041e1 - Update link job for flang on windows
Diana Picus via cfe-commits
cfe-commits at lists.llvm.org
Mon Jun 20 00:34:47 PDT 2022
Author: Diana Picus
Date: 2022-06-20T07:25:10Z
New Revision: 26041e17006cf30e9c2d06706fe6bd3fa818e356
URL: https://github.com/llvm/llvm-project/commit/26041e17006cf30e9c2d06706fe6bd3fa818e356
DIFF: https://github.com/llvm/llvm-project/commit/26041e17006cf30e9c2d06706fe6bd3fa818e356.diff
LOG: Update link job for flang on windows
When linking a Fortran program, we need to add the runtime libraries to
the command line. This is exactly what we do for Linux/Darwin, but the
MSVC interface is slightly different (e.g. -libpath instead of -L).
We also remove oldnames and libcmt, since they're not needed at the
moment and they bring in more dependencies.
We also pass `/subsystem:console` to the linker so it can figure out the
right entry point. This is only needed for MSVC's `link.exe`. For LLD it
is redundant but doesn't hurt.
Differential Revision: https://reviews.llvm.org/D126291
Co-authored-by: Markus Mützel <markus.muetzel at gmx.de>
Added:
Modified:
clang/lib/Driver/ToolChains/CommonArgs.cpp
clang/lib/Driver/ToolChains/CommonArgs.h
clang/lib/Driver/ToolChains/Darwin.cpp
clang/lib/Driver/ToolChains/Gnu.cpp
clang/lib/Driver/ToolChains/MSVC.cpp
clang/lib/Driver/ToolChains/MinGW.cpp
flang/test/Driver/linker-flags.f90
Removed:
################################################################################
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index e2437e5787fd7..d297b808b567f 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -739,15 +739,28 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
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 <driver-path>/../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 @@ void tools::addFortranRuntimeLibraryPath(const ToolChain &TC,
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/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h
index 3052cbf1a3c38..8e62af70ff7f7 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -121,7 +121,8 @@ bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC,
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/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 5d98a6497827f..0a8a9c6eb6ff0 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -637,14 +637,9 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// 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
index d09f41136895e..dc99010107376 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -596,13 +596,9 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// 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
index eea4b74ccb576..14ebe38ee1918 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -81,7 +81,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().IsFlangMode()) {
CmdArgs.push_back("-defaultlib:libcmt");
CmdArgs.push_back("-defaultlib:oldnames");
}
@@ -130,6 +130,16 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
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
index 43466ef2b40f5..c4b4f8e9b89bb 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -218,6 +218,11 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
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
index c46331f37029b..44205f9817e0c 100644
--- 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]]"
More information about the cfe-commits
mailing list