Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[flang] Add runtimes using --dependent-lib on MSVC targets #72519

Merged
merged 3 commits into from
Nov 23, 2023

Conversation

DavidTruby
Copy link
Member

@DavidTruby DavidTruby commented Nov 16, 2023

This patch uses the added --dependent-lib support to add the relevant
runtimes on MSVC targets as /DEFAULTLIB: sections in the object file
rather than on the link line. This should help CMake support for flang
on Windows.

Fixes #63741
Fixes #68017

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' flang:driver flang Flang issues not falling into any other category labels Nov 16, 2023
@llvmbot
Copy link
Member

llvmbot commented Nov 16, 2023

@llvm/pr-subscribers-clang

@llvm/pr-subscribers-flang-driver

Author: David Truby (DavidTruby)

Changes

This patch uses the added --dependent-lib support to add the relevant
runtimes on MSVC targets as /DEFAULTLIB: sections in the object file
rather than on the link line. This should help CMake support for flang
on Windows.


Full diff: https://github.com/llvm/llvm-project/pull/72519.diff

15 Files Affected:

  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+3-40)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.h (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Darwin.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/DragonFly.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+58)
  • (modified) clang/lib/Driver/ToolChains/FreeBSD.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Gnu.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Haiku.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/MSVC.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/MinGW.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/NetBSD.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/OpenBSD.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Solaris.cpp (+1-1)
  • (modified) flang/test/Driver/linker-flags.f90 (-35)
  • (added) flang/test/Driver/msvc-dependent-lib-flags.f90 (+36)
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 5d2cd1959b06925..55951162df50a75 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -977,47 +977,10 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
   return true;
 }
 
-void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args,
+void tools::addFortranRuntimeLibs(const ToolChain &TC,
                                   llvm::opt::ArgStringList &CmdArgs) {
-  if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
-    CmdArgs.push_back(Args.MakeArgString(
-        "/DEFAULTLIB:" + TC.getCompilerRTBasename(Args, "builtins")));
-    unsigned RTOptionID = options::OPT__SLASH_MT;
-    if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
-      RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
-                       .Case("static", options::OPT__SLASH_MT)
-                       .Case("static_dbg", options::OPT__SLASH_MTd)
-                       .Case("dll", options::OPT__SLASH_MD)
-                       .Case("dll_dbg", options::OPT__SLASH_MDd)
-                       .Default(options::OPT__SLASH_MT);
-    }
-    switch (RTOptionID) {
-    case options::OPT__SLASH_MT:
-      CmdArgs.push_back("/DEFAULTLIB:libcmt");
-      CmdArgs.push_back("Fortran_main.static.lib");
-      CmdArgs.push_back("FortranRuntime.static.lib");
-      CmdArgs.push_back("FortranDecimal.static.lib");
-      break;
-    case options::OPT__SLASH_MTd:
-      CmdArgs.push_back("/DEFAULTLIB:libcmtd");
-      CmdArgs.push_back("Fortran_main.static_dbg.lib");
-      CmdArgs.push_back("FortranRuntime.static_dbg.lib");
-      CmdArgs.push_back("FortranDecimal.static_dbg.lib");
-      break;
-    case options::OPT__SLASH_MD:
-      CmdArgs.push_back("/DEFAULTLIB:msvcrt");
-      CmdArgs.push_back("Fortran_main.dynamic.lib");
-      CmdArgs.push_back("FortranRuntime.dynamic.lib");
-      CmdArgs.push_back("FortranDecimal.dynamic.lib");
-      break;
-    case options::OPT__SLASH_MDd:
-      CmdArgs.push_back("/DEFAULTLIB:msvcrtd");
-      CmdArgs.push_back("Fortran_main.dynamic_dbg.lib");
-      CmdArgs.push_back("FortranRuntime.dynamic_dbg.lib");
-      CmdArgs.push_back("FortranDecimal.dynamic_dbg.lib");
-      break;
-    }
-  } else {
+  // These are handled by adding link options to the object file on Windows
+  if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) {
     CmdArgs.push_back("-lFortran_main");
     CmdArgs.push_back("-lFortranRuntime");
     CmdArgs.push_back("-lFortranDecimal");
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h
index 0a0951c5386e601..f364c9793c9be62 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -116,7 +116,7 @@ bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC,
                       bool IsOffloadingHost = false, bool GompNeedsRT = false);
 
 /// Adds Fortran runtime libraries to \p CmdArgs.
-void addFortranRuntimeLibs(const ToolChain &TC, const llvm::opt::ArgList &Args,
+void addFortranRuntimeLibs(const ToolChain &TC,
                            llvm::opt::ArgStringList &CmdArgs);
 
 /// Adds the path for the Fortran runtime libraries to \p CmdArgs.
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 7481f6cab9a968d..f28e08d81bf29b4 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -678,7 +678,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   // to generate executables.
   if (getToolChain().getDriver().IsFlangMode()) {
     addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
-    addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);
+    addFortranRuntimeLibs(getToolChain(), CmdArgs);
   }
 
   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
diff --git a/clang/lib/Driver/ToolChains/DragonFly.cpp b/clang/lib/Driver/ToolChains/DragonFly.cpp
index b13449bf778fa9f..cced977bf029256 100644
--- a/clang/lib/Driver/ToolChains/DragonFly.cpp
+++ b/clang/lib/Driver/ToolChains/DragonFly.cpp
@@ -153,7 +153,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // AddRunTimeLibs).
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-      addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+      addFortranRuntimeLibs(ToolChain, CmdArgs);
       CmdArgs.push_back("-lm");
     }
 
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 8bdd920c3dcbb79..84659b20eb53514 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -204,6 +204,60 @@ void Flang::AddAArch64TargetArgs(const ArgList &Args,
   }
 }
 
+static void processVSRuntimeLibrary(const ToolChain &TC,
+                                    const ArgList &Args,
+                                    ArgStringList &CmdArgs) {
+  assert(TC.getTriple().isKnownWindowsMSVCEnvironment() &&
+         "can only add VS runtime library on Windows!");
+  if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
+    CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" + 
+                      TC.getCompilerRTBasename(Args, "builtins")));
+  }
+  unsigned RTOptionID = options::OPT__SLASH_MT;
+  if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+    RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
+                     .Case("static", options::OPT__SLASH_MT)
+                     .Case("static_dbg", options::OPT__SLASH_MTd)
+                     .Case("dll", options::OPT__SLASH_MD)
+                     .Case("dll_dbg", options::OPT__SLASH_MDd)
+                     .Default(options::OPT__SLASH_MT);
+  }
+  switch (RTOptionID) {
+    case options::OPT__SLASH_MT:
+      CmdArgs.push_back("-D_MT");
+      CmdArgs.push_back("--dependent-lib=libcmt");
+      CmdArgs.push_back("--dependent-lib=Fortran_main.static.lib");
+      CmdArgs.push_back("--dependent-lib=FortranRuntime.static.lib");
+      CmdArgs.push_back("--dependent-lib=FortranDecimal.static.lib");
+      break;
+    case options::OPT__SLASH_MTd:
+      CmdArgs.push_back("-D_MT");
+      CmdArgs.push_back("-D_DEBUG");
+      CmdArgs.push_back("--dependent-lib=libcmtd");
+      CmdArgs.push_back("--dependent-lib=Fortran_main.static_dbg.lib");
+      CmdArgs.push_back("--dependent-lib=FortranRuntime.static_dbg.lib");
+      CmdArgs.push_back("--dependent-lib=FortranDecimal.static_dbg.lib");
+      break;
+    case options::OPT__SLASH_MD:
+      CmdArgs.push_back("-D_MT");
+      CmdArgs.push_back("-D_DLL");
+      CmdArgs.push_back("--dependent-lib=msvcrt");
+      CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic.lib");
+      CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic.lib");
+      CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic.lib");
+      break;
+    case options::OPT__SLASH_MDd:
+      CmdArgs.push_back("-D_MT");
+      CmdArgs.push_back("-D_DEBUG");
+      CmdArgs.push_back("-D_DLL");
+      CmdArgs.push_back("--dependent-lib=msvcrtd");
+      CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic_dbg.lib");
+      CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic_dbg.lib");
+      CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic_dbg.lib");
+      break;
+    }
+  }
+
 void Flang::addTargetOptions(const ArgList &Args,
                              ArgStringList &CmdArgs) const {
   const ToolChain &TC = getToolChain();
@@ -267,6 +321,10 @@ void Flang::addTargetOptions(const ArgList &Args,
     }
   }
 
+  if (Triple.isKnownWindowsMSVCEnvironment()) {
+    processVSRuntimeLibrary(TC, Args, CmdArgs);
+  }
+
   // TODO: Add target specific flags, ABI, mtune option etc.
 }
 
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index d46feb3459a6344..d08764aeef77539 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -310,7 +310,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // AddRunTimeLibs).
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-      addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+      addFortranRuntimeLibs(ToolChain, CmdArgs);
       if (Profiling)
         CmdArgs.push_back("-lm_p");
       else
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 76986481686adc6..5d6386b40cddf4c 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -579,7 +579,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   // AddRunTimeLibs).
   if (D.IsFlangMode()) {
     addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-    addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+    addFortranRuntimeLibs(ToolChain, CmdArgs);
     CmdArgs.push_back("-lm");
   }
 
diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp b/clang/lib/Driver/ToolChains/Haiku.cpp
index e0d94035823fd37..3fe92054ac53e15 100644
--- a/clang/lib/Driver/ToolChains/Haiku.cpp
+++ b/clang/lib/Driver/ToolChains/Haiku.cpp
@@ -118,7 +118,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // AddRunTimeLibs).
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-      addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+      addFortranRuntimeLibs(ToolChain, CmdArgs);
     }
 
     CmdArgs.push_back("-lgcc");
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 8a4a174c90ea855..4966d102c51f1ac 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -131,7 +131,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 
   if (C.getDriver().IsFlangMode()) {
     addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
-    addFortranRuntimeLibs(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
diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index 5d7f8675daf8d28..39d767795445dbe 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -249,7 +249,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 
   if (C.getDriver().IsFlangMode()) {
     addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
-    addFortranRuntimeLibs(TC, Args, CmdArgs);
+    addFortranRuntimeLibs(TC, CmdArgs);
   }
 
   // TODO: Add profile stuff here
diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp
index 240bf5764b9cce2..90b195a007caa78 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -325,7 +325,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // AddRunTimeLibs).
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-      addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+      addFortranRuntimeLibs(ToolChain, CmdArgs);
       CmdArgs.push_back("-lm");
     }
 
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index 5d06cd8ab0bad16..b27a0129e2d4c7a 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -237,7 +237,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // AddRunTimeLibs).
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-      addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+      addFortranRuntimeLibs(ToolChain, CmdArgs);
       if (Profiling)
         CmdArgs.push_back("-lm_p");
       else
diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp
index 96757f07a54974f..badfc33a74f2958 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -229,7 +229,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // these dependencies need to be listed before the C runtime below.
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
-      addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);
+      addFortranRuntimeLibs(getToolChain(), CmdArgs);
       CmdArgs.push_back("-lm");
     }
     if (Args.hasArg(options::OPT_fstack_protector) ||
diff --git a/flang/test/Driver/linker-flags.f90 b/flang/test/Driver/linker-flags.f90
index a1417057d4da068..85c4d60b3f09862 100644
--- a/flang/test/Driver/linker-flags.f90
+++ b/flang/test/Driver/linker-flags.f90
@@ -16,9 +16,6 @@
 !       but it is not needed when compiling Fortran code and they might bring in
 !       additional dependencies. Make sure its not added.
 ! RUN: %flang -### --target=aarch64-windows-msvc -fuse-ld= %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC --implicit-check-not oldnames
-! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=static_dbg -fuse-ld= %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC-DEBUG --implicit-check-not oldnames
-! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=dll -fuse-ld= %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC-DLL --implicit-check-not oldnames
-! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=dll_dbg -fuse-ld= %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC-DLL-DEBUG --implicit-check-not oldnames
 
 ! Compiler invocation to generate the object file
 ! CHECK-LABEL: {{.*}} "-emit-obj"
@@ -54,37 +51,5 @@
 !       (lld-)link.exe on Windows platforms. The suffix may not be added
 !       when the executable is not found or on non-Windows platforms.
 ! MSVC-LABEL: link
-! MSVC-SAME: /DEFAULTLIB:clang_rt.builtins-aarch64.lib
-! MSVC-SAME: /DEFAULTLIB:libcmt
-! MSVC-SAME: Fortran_main.static.lib
-! MSVC-SAME: FortranRuntime.static.lib
-! MSVC-SAME: FortranDecimal.static.lib
 ! MSVC-SAME: /subsystem:console
 ! MSVC-SAME: "[[object_file]]"
-
-! MSVC-DEBUG-LABEL: link
-! MSVC-DEBUG-SAME: /DEFAULTLIB:clang_rt.builtins-aarch64.lib
-! MSVC-DEBUG-SAME: /DEFAULTLIB:libcmtd
-! MSVC-DEBUG-SAME: Fortran_main.static_dbg.lib
-! MSVC-DEBUG-SAME: FortranRuntime.static_dbg.lib
-! MSVC-DEBUG-SAME: FortranDecimal.static_dbg.lib
-! MSVC-DEBUG-SAME: /subsystem:console
-! MSVC-DEBUG-SAME: "[[object_file]]"
-
-! MSVC-DLL-LABEL: link
-! MSVC-DLL-SAME: /DEFAULTLIB:clang_rt.builtins-aarch64.lib
-! MSVC-DLL-SAME: /DEFAULTLIB:msvcrt
-! MSVC-DLL-SAME: Fortran_main.dynamic.lib
-! MSVC-DLL-SAME: FortranRuntime.dynamic.lib
-! MSVC-DLL-SAME: FortranDecimal.dynamic.lib
-! MSVC-DLL-SAME: /subsystem:console
-! MSVC-DLL-SAME: "[[object_file]]"
-
-! MSVC-DLL-DEBUG-LABEL: link
-! MSVC-DLL-DEBUG-SAME: /DEFAULTLIB:clang_rt.builtins-aarch64.lib
-! MSVC-DLL-DEBUG-SAME: /DEFAULTLIB:msvcrtd
-! MSVC-DLL-DEBUG-SAME: Fortran_main.dynamic_dbg.lib
-! MSVC-DLL-DEBUG-SAME: FortranRuntime.dynamic_dbg.lib
-! MSVC-DLL-DEBUG-SAME: FortranDecimal.dynamic_dbg.lib
-! MSVC-DLL-DEBUG-SAME: /subsystem:console
-! MSVC-DLL-DEBUG-SAME: "[[object_file]]"
diff --git a/flang/test/Driver/msvc-dependent-lib-flags.f90 b/flang/test/Driver/msvc-dependent-lib-flags.f90
new file mode 100644
index 000000000000000..9d971d5b1ec66fa
--- /dev/null
+++ b/flang/test/Driver/msvc-dependent-lib-flags.f90
@@ -0,0 +1,36 @@
+! RUN: %flang -### --target=aarch64-windows-msvc -fuse-ld= %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC
+! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=static_dbg -fuse-ld= %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DEBUG
+! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=dll -fuse-ld= %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL
+! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=dll_dbg -fuse-ld= %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL-DEBUG
+
+! MSVC: --dependent-lib=clang_rt.builtins-aarch64.lib
+! MSVC-SAME: -D_MT
+! MSVC-SAME: --dependent-lib=libcmt
+! MSVC-SAME: --dependent-lib=Fortran_main.static.lib
+! MSVC-SAME: --dependent-lib=FortranRuntime.static.lib
+! MSVC-SAME: --dependent-lib=FortranDecimal.static.lib
+
+! MSVC-DEBUG: --dependent-lib=clang_rt.builtins-aarch64.lib
+! MSVC-DEBUG-SAME: -D_MT
+! MSVC-DEBUG-SAME: -D_DEBUG
+! MSVC-DEBUG-SAME: --dependent-lib=libcmtd
+! MSVC-DEBUG-SAME: --dependent-lib=Fortran_main.static_dbg.lib
+! MSVC-DEBUG-SAME: --dependent-lib=FortranRuntime.static_dbg.lib
+! MSVC-DEBUG-SAME: --dependent-lib=FortranDecimal.static_dbg.lib
+
+! MSVC-DLL: --dependent-lib=clang_rt.builtins-aarch64.lib
+! MSVC-DLL-SAME: -D_MT
+! MSVC-DLL-SAME: -D_DLL
+! MSVC-DLL-SAME: --dependent-lib=msvcrt
+! MSVC-DLL-SAME: --dependent-lib=Fortran_main.dynamic.lib
+! MSVC-DLL-SAME: --dependent-lib=FortranRuntime.dynamic.lib
+! MSVC-DLL-SAME: --dependent-lib=FortranDecimal.dynamic.lib
+
+! MSVC-DLL-DEBUG: --dependent-lib=clang_rt.builtins-aarch64.lib
+! MSVC-DLL-DEBUG-SAME: -D_MT
+! MSVC-DLL-DEBUG-SAME: -D_DEBUG
+! MSVC-DLL-DEBUG-SAME: -D_DLL
+! MSVC-DLL-DEBUG-SAME: --dependent-lib=msvcrtd
+! MSVC-DLL-DEBUG-SAME: --dependent-lib=Fortran_main.dynamic_dbg.lib
+! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranRuntime.dynamic_dbg.lib
+! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranDecimal.dynamic_dbg.lib

@llvmbot
Copy link
Member

llvmbot commented Nov 16, 2023

@llvm/pr-subscribers-clang-driver

Author: David Truby (DavidTruby)

Changes

This patch uses the added --dependent-lib support to add the relevant
runtimes on MSVC targets as /DEFAULTLIB: sections in the object file
rather than on the link line. This should help CMake support for flang
on Windows.


Full diff: https://github.com/llvm/llvm-project/pull/72519.diff

15 Files Affected:

  • (modified) clang/lib/Driver/ToolChains/CommonArgs.cpp (+3-40)
  • (modified) clang/lib/Driver/ToolChains/CommonArgs.h (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Darwin.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/DragonFly.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Flang.cpp (+58)
  • (modified) clang/lib/Driver/ToolChains/FreeBSD.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Gnu.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Haiku.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/MSVC.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/MinGW.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/NetBSD.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/OpenBSD.cpp (+1-1)
  • (modified) clang/lib/Driver/ToolChains/Solaris.cpp (+1-1)
  • (modified) flang/test/Driver/linker-flags.f90 (-35)
  • (added) flang/test/Driver/msvc-dependent-lib-flags.f90 (+36)
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 5d2cd1959b06925..55951162df50a75 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -977,47 +977,10 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
   return true;
 }
 
-void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args,
+void tools::addFortranRuntimeLibs(const ToolChain &TC,
                                   llvm::opt::ArgStringList &CmdArgs) {
-  if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
-    CmdArgs.push_back(Args.MakeArgString(
-        "/DEFAULTLIB:" + TC.getCompilerRTBasename(Args, "builtins")));
-    unsigned RTOptionID = options::OPT__SLASH_MT;
-    if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
-      RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
-                       .Case("static", options::OPT__SLASH_MT)
-                       .Case("static_dbg", options::OPT__SLASH_MTd)
-                       .Case("dll", options::OPT__SLASH_MD)
-                       .Case("dll_dbg", options::OPT__SLASH_MDd)
-                       .Default(options::OPT__SLASH_MT);
-    }
-    switch (RTOptionID) {
-    case options::OPT__SLASH_MT:
-      CmdArgs.push_back("/DEFAULTLIB:libcmt");
-      CmdArgs.push_back("Fortran_main.static.lib");
-      CmdArgs.push_back("FortranRuntime.static.lib");
-      CmdArgs.push_back("FortranDecimal.static.lib");
-      break;
-    case options::OPT__SLASH_MTd:
-      CmdArgs.push_back("/DEFAULTLIB:libcmtd");
-      CmdArgs.push_back("Fortran_main.static_dbg.lib");
-      CmdArgs.push_back("FortranRuntime.static_dbg.lib");
-      CmdArgs.push_back("FortranDecimal.static_dbg.lib");
-      break;
-    case options::OPT__SLASH_MD:
-      CmdArgs.push_back("/DEFAULTLIB:msvcrt");
-      CmdArgs.push_back("Fortran_main.dynamic.lib");
-      CmdArgs.push_back("FortranRuntime.dynamic.lib");
-      CmdArgs.push_back("FortranDecimal.dynamic.lib");
-      break;
-    case options::OPT__SLASH_MDd:
-      CmdArgs.push_back("/DEFAULTLIB:msvcrtd");
-      CmdArgs.push_back("Fortran_main.dynamic_dbg.lib");
-      CmdArgs.push_back("FortranRuntime.dynamic_dbg.lib");
-      CmdArgs.push_back("FortranDecimal.dynamic_dbg.lib");
-      break;
-    }
-  } else {
+  // These are handled by adding link options to the object file on Windows
+  if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) {
     CmdArgs.push_back("-lFortran_main");
     CmdArgs.push_back("-lFortranRuntime");
     CmdArgs.push_back("-lFortranDecimal");
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.h b/clang/lib/Driver/ToolChains/CommonArgs.h
index 0a0951c5386e601..f364c9793c9be62 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.h
+++ b/clang/lib/Driver/ToolChains/CommonArgs.h
@@ -116,7 +116,7 @@ bool addOpenMPRuntime(llvm::opt::ArgStringList &CmdArgs, const ToolChain &TC,
                       bool IsOffloadingHost = false, bool GompNeedsRT = false);
 
 /// Adds Fortran runtime libraries to \p CmdArgs.
-void addFortranRuntimeLibs(const ToolChain &TC, const llvm::opt::ArgList &Args,
+void addFortranRuntimeLibs(const ToolChain &TC,
                            llvm::opt::ArgStringList &CmdArgs);
 
 /// Adds the path for the Fortran runtime libraries to \p CmdArgs.
diff --git a/clang/lib/Driver/ToolChains/Darwin.cpp b/clang/lib/Driver/ToolChains/Darwin.cpp
index 7481f6cab9a968d..f28e08d81bf29b4 100644
--- a/clang/lib/Driver/ToolChains/Darwin.cpp
+++ b/clang/lib/Driver/ToolChains/Darwin.cpp
@@ -678,7 +678,7 @@ void darwin::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   // to generate executables.
   if (getToolChain().getDriver().IsFlangMode()) {
     addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
-    addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);
+    addFortranRuntimeLibs(getToolChain(), CmdArgs);
   }
 
   if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
diff --git a/clang/lib/Driver/ToolChains/DragonFly.cpp b/clang/lib/Driver/ToolChains/DragonFly.cpp
index b13449bf778fa9f..cced977bf029256 100644
--- a/clang/lib/Driver/ToolChains/DragonFly.cpp
+++ b/clang/lib/Driver/ToolChains/DragonFly.cpp
@@ -153,7 +153,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // AddRunTimeLibs).
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-      addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+      addFortranRuntimeLibs(ToolChain, CmdArgs);
       CmdArgs.push_back("-lm");
     }
 
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 8bdd920c3dcbb79..84659b20eb53514 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -204,6 +204,60 @@ void Flang::AddAArch64TargetArgs(const ArgList &Args,
   }
 }
 
+static void processVSRuntimeLibrary(const ToolChain &TC,
+                                    const ArgList &Args,
+                                    ArgStringList &CmdArgs) {
+  assert(TC.getTriple().isKnownWindowsMSVCEnvironment() &&
+         "can only add VS runtime library on Windows!");
+  if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
+    CmdArgs.push_back(Args.MakeArgString("--dependent-lib=" + 
+                      TC.getCompilerRTBasename(Args, "builtins")));
+  }
+  unsigned RTOptionID = options::OPT__SLASH_MT;
+  if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
+    RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
+                     .Case("static", options::OPT__SLASH_MT)
+                     .Case("static_dbg", options::OPT__SLASH_MTd)
+                     .Case("dll", options::OPT__SLASH_MD)
+                     .Case("dll_dbg", options::OPT__SLASH_MDd)
+                     .Default(options::OPT__SLASH_MT);
+  }
+  switch (RTOptionID) {
+    case options::OPT__SLASH_MT:
+      CmdArgs.push_back("-D_MT");
+      CmdArgs.push_back("--dependent-lib=libcmt");
+      CmdArgs.push_back("--dependent-lib=Fortran_main.static.lib");
+      CmdArgs.push_back("--dependent-lib=FortranRuntime.static.lib");
+      CmdArgs.push_back("--dependent-lib=FortranDecimal.static.lib");
+      break;
+    case options::OPT__SLASH_MTd:
+      CmdArgs.push_back("-D_MT");
+      CmdArgs.push_back("-D_DEBUG");
+      CmdArgs.push_back("--dependent-lib=libcmtd");
+      CmdArgs.push_back("--dependent-lib=Fortran_main.static_dbg.lib");
+      CmdArgs.push_back("--dependent-lib=FortranRuntime.static_dbg.lib");
+      CmdArgs.push_back("--dependent-lib=FortranDecimal.static_dbg.lib");
+      break;
+    case options::OPT__SLASH_MD:
+      CmdArgs.push_back("-D_MT");
+      CmdArgs.push_back("-D_DLL");
+      CmdArgs.push_back("--dependent-lib=msvcrt");
+      CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic.lib");
+      CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic.lib");
+      CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic.lib");
+      break;
+    case options::OPT__SLASH_MDd:
+      CmdArgs.push_back("-D_MT");
+      CmdArgs.push_back("-D_DEBUG");
+      CmdArgs.push_back("-D_DLL");
+      CmdArgs.push_back("--dependent-lib=msvcrtd");
+      CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic_dbg.lib");
+      CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic_dbg.lib");
+      CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic_dbg.lib");
+      break;
+    }
+  }
+
 void Flang::addTargetOptions(const ArgList &Args,
                              ArgStringList &CmdArgs) const {
   const ToolChain &TC = getToolChain();
@@ -267,6 +321,10 @@ void Flang::addTargetOptions(const ArgList &Args,
     }
   }
 
+  if (Triple.isKnownWindowsMSVCEnvironment()) {
+    processVSRuntimeLibrary(TC, Args, CmdArgs);
+  }
+
   // TODO: Add target specific flags, ABI, mtune option etc.
 }
 
diff --git a/clang/lib/Driver/ToolChains/FreeBSD.cpp b/clang/lib/Driver/ToolChains/FreeBSD.cpp
index d46feb3459a6344..d08764aeef77539 100644
--- a/clang/lib/Driver/ToolChains/FreeBSD.cpp
+++ b/clang/lib/Driver/ToolChains/FreeBSD.cpp
@@ -310,7 +310,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // AddRunTimeLibs).
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-      addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+      addFortranRuntimeLibs(ToolChain, CmdArgs);
       if (Profiling)
         CmdArgs.push_back("-lm_p");
       else
diff --git a/clang/lib/Driver/ToolChains/Gnu.cpp b/clang/lib/Driver/ToolChains/Gnu.cpp
index 76986481686adc6..5d6386b40cddf4c 100644
--- a/clang/lib/Driver/ToolChains/Gnu.cpp
+++ b/clang/lib/Driver/ToolChains/Gnu.cpp
@@ -579,7 +579,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
   // AddRunTimeLibs).
   if (D.IsFlangMode()) {
     addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-    addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+    addFortranRuntimeLibs(ToolChain, CmdArgs);
     CmdArgs.push_back("-lm");
   }
 
diff --git a/clang/lib/Driver/ToolChains/Haiku.cpp b/clang/lib/Driver/ToolChains/Haiku.cpp
index e0d94035823fd37..3fe92054ac53e15 100644
--- a/clang/lib/Driver/ToolChains/Haiku.cpp
+++ b/clang/lib/Driver/ToolChains/Haiku.cpp
@@ -118,7 +118,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // AddRunTimeLibs).
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-      addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+      addFortranRuntimeLibs(ToolChain, CmdArgs);
     }
 
     CmdArgs.push_back("-lgcc");
diff --git a/clang/lib/Driver/ToolChains/MSVC.cpp b/clang/lib/Driver/ToolChains/MSVC.cpp
index 8a4a174c90ea855..4966d102c51f1ac 100644
--- a/clang/lib/Driver/ToolChains/MSVC.cpp
+++ b/clang/lib/Driver/ToolChains/MSVC.cpp
@@ -131,7 +131,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 
   if (C.getDriver().IsFlangMode()) {
     addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
-    addFortranRuntimeLibs(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
diff --git a/clang/lib/Driver/ToolChains/MinGW.cpp b/clang/lib/Driver/ToolChains/MinGW.cpp
index 5d7f8675daf8d28..39d767795445dbe 100644
--- a/clang/lib/Driver/ToolChains/MinGW.cpp
+++ b/clang/lib/Driver/ToolChains/MinGW.cpp
@@ -249,7 +249,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,
 
   if (C.getDriver().IsFlangMode()) {
     addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
-    addFortranRuntimeLibs(TC, Args, CmdArgs);
+    addFortranRuntimeLibs(TC, CmdArgs);
   }
 
   // TODO: Add profile stuff here
diff --git a/clang/lib/Driver/ToolChains/NetBSD.cpp b/clang/lib/Driver/ToolChains/NetBSD.cpp
index 240bf5764b9cce2..90b195a007caa78 100644
--- a/clang/lib/Driver/ToolChains/NetBSD.cpp
+++ b/clang/lib/Driver/ToolChains/NetBSD.cpp
@@ -325,7 +325,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // AddRunTimeLibs).
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-      addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+      addFortranRuntimeLibs(ToolChain, CmdArgs);
       CmdArgs.push_back("-lm");
     }
 
diff --git a/clang/lib/Driver/ToolChains/OpenBSD.cpp b/clang/lib/Driver/ToolChains/OpenBSD.cpp
index 5d06cd8ab0bad16..b27a0129e2d4c7a 100644
--- a/clang/lib/Driver/ToolChains/OpenBSD.cpp
+++ b/clang/lib/Driver/ToolChains/OpenBSD.cpp
@@ -237,7 +237,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // AddRunTimeLibs).
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
-      addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
+      addFortranRuntimeLibs(ToolChain, CmdArgs);
       if (Profiling)
         CmdArgs.push_back("-lm_p");
       else
diff --git a/clang/lib/Driver/ToolChains/Solaris.cpp b/clang/lib/Driver/ToolChains/Solaris.cpp
index 96757f07a54974f..badfc33a74f2958 100644
--- a/clang/lib/Driver/ToolChains/Solaris.cpp
+++ b/clang/lib/Driver/ToolChains/Solaris.cpp
@@ -229,7 +229,7 @@ void solaris::Linker::ConstructJob(Compilation &C, const JobAction &JA,
     // these dependencies need to be listed before the C runtime below.
     if (D.IsFlangMode()) {
       addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
-      addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);
+      addFortranRuntimeLibs(getToolChain(), CmdArgs);
       CmdArgs.push_back("-lm");
     }
     if (Args.hasArg(options::OPT_fstack_protector) ||
diff --git a/flang/test/Driver/linker-flags.f90 b/flang/test/Driver/linker-flags.f90
index a1417057d4da068..85c4d60b3f09862 100644
--- a/flang/test/Driver/linker-flags.f90
+++ b/flang/test/Driver/linker-flags.f90
@@ -16,9 +16,6 @@
 !       but it is not needed when compiling Fortran code and they might bring in
 !       additional dependencies. Make sure its not added.
 ! RUN: %flang -### --target=aarch64-windows-msvc -fuse-ld= %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC --implicit-check-not oldnames
-! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=static_dbg -fuse-ld= %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC-DEBUG --implicit-check-not oldnames
-! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=dll -fuse-ld= %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC-DLL --implicit-check-not oldnames
-! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=dll_dbg -fuse-ld= %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC-DLL-DEBUG --implicit-check-not oldnames
 
 ! Compiler invocation to generate the object file
 ! CHECK-LABEL: {{.*}} "-emit-obj"
@@ -54,37 +51,5 @@
 !       (lld-)link.exe on Windows platforms. The suffix may not be added
 !       when the executable is not found or on non-Windows platforms.
 ! MSVC-LABEL: link
-! MSVC-SAME: /DEFAULTLIB:clang_rt.builtins-aarch64.lib
-! MSVC-SAME: /DEFAULTLIB:libcmt
-! MSVC-SAME: Fortran_main.static.lib
-! MSVC-SAME: FortranRuntime.static.lib
-! MSVC-SAME: FortranDecimal.static.lib
 ! MSVC-SAME: /subsystem:console
 ! MSVC-SAME: "[[object_file]]"
-
-! MSVC-DEBUG-LABEL: link
-! MSVC-DEBUG-SAME: /DEFAULTLIB:clang_rt.builtins-aarch64.lib
-! MSVC-DEBUG-SAME: /DEFAULTLIB:libcmtd
-! MSVC-DEBUG-SAME: Fortran_main.static_dbg.lib
-! MSVC-DEBUG-SAME: FortranRuntime.static_dbg.lib
-! MSVC-DEBUG-SAME: FortranDecimal.static_dbg.lib
-! MSVC-DEBUG-SAME: /subsystem:console
-! MSVC-DEBUG-SAME: "[[object_file]]"
-
-! MSVC-DLL-LABEL: link
-! MSVC-DLL-SAME: /DEFAULTLIB:clang_rt.builtins-aarch64.lib
-! MSVC-DLL-SAME: /DEFAULTLIB:msvcrt
-! MSVC-DLL-SAME: Fortran_main.dynamic.lib
-! MSVC-DLL-SAME: FortranRuntime.dynamic.lib
-! MSVC-DLL-SAME: FortranDecimal.dynamic.lib
-! MSVC-DLL-SAME: /subsystem:console
-! MSVC-DLL-SAME: "[[object_file]]"
-
-! MSVC-DLL-DEBUG-LABEL: link
-! MSVC-DLL-DEBUG-SAME: /DEFAULTLIB:clang_rt.builtins-aarch64.lib
-! MSVC-DLL-DEBUG-SAME: /DEFAULTLIB:msvcrtd
-! MSVC-DLL-DEBUG-SAME: Fortran_main.dynamic_dbg.lib
-! MSVC-DLL-DEBUG-SAME: FortranRuntime.dynamic_dbg.lib
-! MSVC-DLL-DEBUG-SAME: FortranDecimal.dynamic_dbg.lib
-! MSVC-DLL-DEBUG-SAME: /subsystem:console
-! MSVC-DLL-DEBUG-SAME: "[[object_file]]"
diff --git a/flang/test/Driver/msvc-dependent-lib-flags.f90 b/flang/test/Driver/msvc-dependent-lib-flags.f90
new file mode 100644
index 000000000000000..9d971d5b1ec66fa
--- /dev/null
+++ b/flang/test/Driver/msvc-dependent-lib-flags.f90
@@ -0,0 +1,36 @@
+! RUN: %flang -### --target=aarch64-windows-msvc -fuse-ld= %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC
+! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=static_dbg -fuse-ld= %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DEBUG
+! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=dll -fuse-ld= %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL
+! RUN: %flang -### --target=aarch64-windows-msvc -fms-runtime-lib=dll_dbg -fuse-ld= %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC-DLL-DEBUG
+
+! MSVC: --dependent-lib=clang_rt.builtins-aarch64.lib
+! MSVC-SAME: -D_MT
+! MSVC-SAME: --dependent-lib=libcmt
+! MSVC-SAME: --dependent-lib=Fortran_main.static.lib
+! MSVC-SAME: --dependent-lib=FortranRuntime.static.lib
+! MSVC-SAME: --dependent-lib=FortranDecimal.static.lib
+
+! MSVC-DEBUG: --dependent-lib=clang_rt.builtins-aarch64.lib
+! MSVC-DEBUG-SAME: -D_MT
+! MSVC-DEBUG-SAME: -D_DEBUG
+! MSVC-DEBUG-SAME: --dependent-lib=libcmtd
+! MSVC-DEBUG-SAME: --dependent-lib=Fortran_main.static_dbg.lib
+! MSVC-DEBUG-SAME: --dependent-lib=FortranRuntime.static_dbg.lib
+! MSVC-DEBUG-SAME: --dependent-lib=FortranDecimal.static_dbg.lib
+
+! MSVC-DLL: --dependent-lib=clang_rt.builtins-aarch64.lib
+! MSVC-DLL-SAME: -D_MT
+! MSVC-DLL-SAME: -D_DLL
+! MSVC-DLL-SAME: --dependent-lib=msvcrt
+! MSVC-DLL-SAME: --dependent-lib=Fortran_main.dynamic.lib
+! MSVC-DLL-SAME: --dependent-lib=FortranRuntime.dynamic.lib
+! MSVC-DLL-SAME: --dependent-lib=FortranDecimal.dynamic.lib
+
+! MSVC-DLL-DEBUG: --dependent-lib=clang_rt.builtins-aarch64.lib
+! MSVC-DLL-DEBUG-SAME: -D_MT
+! MSVC-DLL-DEBUG-SAME: -D_DEBUG
+! MSVC-DLL-DEBUG-SAME: -D_DLL
+! MSVC-DLL-DEBUG-SAME: --dependent-lib=msvcrtd
+! MSVC-DLL-DEBUG-SAME: --dependent-lib=Fortran_main.dynamic_dbg.lib
+! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranRuntime.dynamic_dbg.lib
+! MSVC-DLL-DEBUG-SAME: --dependent-lib=FortranDecimal.dynamic_dbg.lib

@DavidTruby
Copy link
Member Author

@bradking I'm hoping this finally fixes this issue in a way that is more helpful to you, could you confirm that for me? Thanks!

Copy link

github-actions bot commented Nov 16, 2023

✅ With the latest revision this PR passed the C/C++ code formatter.

@bradking
Copy link
Contributor

I tried this locally, but it doesn't quite work:

>flang-new foo.f90
... fatal error LNK1276: invalid directive 'clang_rt.builtins-x86_64.lib' found; does not start with '/'

The directives appear in the object file with an extra space:

>flang-new -c foo.f90
>grep -ai defaultlib foo.o
 /DEFAULTLIB: clang_rt.builtins-x86_64.lib /DEFAULTLIB: libcmt /DEFAULTLIB: Fortran_main.static.lib /DEFAULTLIB: FortranRuntime.static.lib /DEFAULTLIB: FortranDecimal.static.lib.text

There should not be a space after /DEFAULTLIB: before the library name.

Copy link
Contributor

@banach-space banach-space Nov 19, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add some comments to clarify the difference between:

  • "msvc-dependent-lib-flags.f90", and
  • "linker-flags.f90"

Related to this, I think that renaming:

  • "linker-flags.f90" as "default-fortran-linker-flags.f90",

would really help.

Copy link
Member Author

@DavidTruby DavidTruby Nov 20, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the new file (msvc-dependent-lib-flags.f90) just tests this specific feature; I can probably just put that in the other linker flags file but that's getting rather big anyway and doesn't necessarily need yet more run lines added to it!
Additionally these aren't really linker flags, they're not passed to the link line explicitly by the driver but as directives in the object files.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From your explanation it is clear that these files test completely different (though related) things. I would keep them separate (i agree that "linker-flags.f90" is getting long and complex).

So, is this checking the frontend driver invocation?

! MSVC: --dependent-lib=clang_rt.builtins-aarch64.lib

? That might help make the distinction clear (the other file checks the linker invocation).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, these are checking the invocation of the frontend driver

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] Could you add MSVC: flang-new -fc1 in there then? I feel that that part is quite important.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've had to add it as just -fc1 because of the way lit does argument passing on Windows (it puts the "flang-new" and "-fc1" in quotes, but only sometimes :))

Comment on lines 982 to 983
// These are handled by adding link options to the object file on Windows
if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean it's user's responsibility to add these? Why can't these be added auto-magically like on other platforms?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, these are added automatically. They're just added at a different place, because they aren't added to the link line but rather added as link directives in the object file, matching what cl.exe and clang do and therefore what link.exe expects.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would expand the comment then - it's worth clarifying that this is also done automatically, but when creating a ... frontend driver (?) rather than liker invocation? Just to avoid surprising our future selves :)

@@ -0,0 +1,36 @@
! RUN: %flang -### --target=aarch64-windows-msvc -fuse-ld= %S/Inputs/hello.f90 -v 2>&1 | FileCheck %s --check-prefixes=MSVC
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you remind the rationale behind an empty -fuse-ld=?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know that there is one honestly, I copied these build lines from another file! Happy to remove it

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lets remove it then.

@DavidTruby
Copy link
Member Author

I tried this locally, but it doesn't quite work:

>flang-new foo.f90
... fatal error LNK1276: invalid directive 'clang_rt.builtins-x86_64.lib' found; does not start with '/'

The directives appear in the object file with an extra space:

>flang-new -c foo.f90
>grep -ai defaultlib foo.o
 /DEFAULTLIB: clang_rt.builtins-x86_64.lib /DEFAULTLIB: libcmt /DEFAULTLIB: Fortran_main.static.lib /DEFAULTLIB: FortranRuntime.static.lib /DEFAULTLIB: FortranDecimal.static.lib.text

There should not be a space after /DEFAULTLIB: before the library name.

This looks like a small bug in the previous patch in this series due to a misunderstanding by me of how llvm.linker.options works. I'll push a quick fix for that and then rebase this patch on that which should fix the issue

This patch uses the added --dependent-lib support to add the relevant
runtimes on MSVC targets as `/DEFAULTLIB:` sections in the object file
rather than on the link line. This should help CMake support for flang
on Windows.
@DavidTruby
Copy link
Member Author

DavidTruby commented Nov 20, 2023

@bradking this now works for me at least locally, sorry for the confusion. Could you try again? Thanks!

@bradking
Copy link
Contributor

@DavidTruby that fixed it, thanks. Nice work. I've locally updated CMake to use flang-new's MSVC runtime library selection flags (-fms-runtime-lib={static,static_dbg,dll,dll_dbg}). It passes CMake's test suite, including the MSVCRuntimeLibrary.Fortran test that covers all four variants' preprocessor definitions and linking behavior. Once this is merged I'll update CMake to use this feature for LLVMFlang 18.0 and above.

The only remaining issue I see after this is that the default FortranRuntime.lib library (and friends) are still installed even though they are only needed inside the llvm-project/flang build tree for testing. Only the

Fortran*.{static,static_dbg,dynamic,dynamic_dbg}.lib

variants should be installed. That could be considered out-of-scope for this PR though and done in a follow-up instead.

Therefore I think this PR/commit can be marked as Fixes: #68017.

Copy link
Contributor

@banach-space banach-space left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks for addressing my comments!

Feel free to ignore my final nit or to address it when merging.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nit] Could you add MSVC: flang-new -fc1 in there then? I feel that that part is quite important.

@DavidTruby DavidTruby merged commit 0bc7cd4 into llvm:main Nov 23, 2023
@DavidTruby DavidTruby deleted the crt branch November 23, 2023 14:22
Guzhu-AMD pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Nov 30, 2023
Local branch amd-gfx 9460104 Merged main:7b97d5048a8f into amd-gfx:3ab181f6d3ad
Remote branch main 0bc7cd4 [flang] Add runtimes using --dependent-lib on MSVC targets (llvm#72519)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:driver 'clang' and 'clang++' user-facing binaries. Not 'clang-cl' clang Clang issues not falling into any other category flang:driver flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[flang] MSVC runtime library selection [flang] Support --dependent-lib=
4 participants