Skip to content

Commit

Permalink
[flang][windows] Add option to link against specific MSVC CRT (llvm#7…
Browse files Browse the repository at this point in the history
…0833)

Currently flang's runtime libraries are only built for the specific CRT
that LLVM itself was built against. This patch adds the cmake logic for
building a separate runtime for each CRT configuration and adds a flag
for selecting a CRT configuration to link against.
  • Loading branch information
DavidTruby authored Nov 10, 2023
1 parent 18a0313 commit cf1e342
Show file tree
Hide file tree
Showing 19 changed files with 169 additions and 31 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -2858,7 +2858,7 @@ def fms_compatibility_version
"version number to report in _MSC_VER (0 = don't define it "
"(default))">;
def fms_runtime_lib_EQ : Joined<["-"], "fms-runtime-lib=">, Group<f_Group>,
Flags<[]>, Visibility<[ClangOption, CLOption]>,
Flags<[]>, Visibility<[ClangOption, CLOption, FlangOption]>,
Values<"static,static_dbg,dll,dll_dbg">,
HelpText<"Select Windows run-time library">,
DocBrief<[{
Expand Down
42 changes: 38 additions & 4 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -976,12 +976,46 @@ bool tools::addOpenMPRuntime(ArgStringList &CmdArgs, const ToolChain &TC,
return true;
}

void tools::addFortranRuntimeLibs(const ToolChain &TC,
void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) {
if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
CmdArgs.push_back("Fortran_main.lib");
CmdArgs.push_back("FortranRuntime.lib");
CmdArgs.push_back("FortranDecimal.lib");
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 {
CmdArgs.push_back("-lFortran_main");
CmdArgs.push_back("-lFortranRuntime");
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/CommonArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
void addFortranRuntimeLibs(const ToolChain &TC, const llvm::opt::ArgList &Args,
llvm::opt::ArgStringList &CmdArgs);

/// Adds the path for the Fortran runtime libraries to \p CmdArgs.
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Darwin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(), CmdArgs);
addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);
}

if (!Args.hasArg(options::OPT_nostdlib, options::OPT_nodefaultlibs))
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/DragonFly.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ void dragonfly::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// AddRunTimeLibs).
if (D.IsFlangMode()) {
addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
addFortranRuntimeLibs(ToolChain, CmdArgs);
addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
CmdArgs.push_back("-lm");
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/FreeBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,7 @@ void freebsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// AddRunTimeLibs).
if (D.IsFlangMode()) {
addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
addFortranRuntimeLibs(ToolChain, CmdArgs);
addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
if (Profiling)
CmdArgs.push_back("-lm_p");
else
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -584,7 +584,7 @@ void tools::gnutools::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// AddRunTimeLibs).
if (D.IsFlangMode()) {
addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
addFortranRuntimeLibs(ToolChain, CmdArgs);
addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
CmdArgs.push_back("-lm");
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/Haiku.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ void haiku::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// AddRunTimeLibs).
if (D.IsFlangMode()) {
addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
addFortranRuntimeLibs(ToolChain, CmdArgs);
addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
}

CmdArgs.push_back("-lgcc");
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/MSVC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ void visualstudio::Linker::ConstructJob(Compilation &C, const JobAction &JA,

if (C.getDriver().IsFlangMode()) {
addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
addFortranRuntimeLibs(TC, CmdArgs);
addFortranRuntimeLibs(TC, Args, 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
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/MinGW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ void tools::MinGW::Linker::ConstructJob(Compilation &C, const JobAction &JA,

if (C.getDriver().IsFlangMode()) {
addFortranRuntimeLibraryPath(TC, Args, CmdArgs);
addFortranRuntimeLibs(TC, CmdArgs);
addFortranRuntimeLibs(TC, Args, CmdArgs);
}

// TODO: Add profile stuff here
Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/NetBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ void netbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// AddRunTimeLibs).
if (D.IsFlangMode()) {
addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
addFortranRuntimeLibs(ToolChain, CmdArgs);
addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
CmdArgs.push_back("-lm");
}

Expand Down
2 changes: 1 addition & 1 deletion clang/lib/Driver/ToolChains/OpenBSD.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ void openbsd::Linker::ConstructJob(Compilation &C, const JobAction &JA,
// AddRunTimeLibs).
if (D.IsFlangMode()) {
addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
addFortranRuntimeLibs(ToolChain, CmdArgs);
addFortranRuntimeLibs(ToolChain, Args, CmdArgs);
if (Profiling)
CmdArgs.push_back("-lm_p");
else
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/Driver/ToolChains/Solaris.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,8 @@ void solaris::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.
if (D.IsFlangMode()) {
addFortranRuntimeLibraryPath(ToolChain, Args, CmdArgs);
addFortranRuntimeLibs(ToolChain, CmdArgs);
addFortranRuntimeLibraryPath(getToolChain(), Args, CmdArgs);
addFortranRuntimeLibs(getToolChain(), Args, CmdArgs);
CmdArgs.push_back("-lm");
}
if (Args.hasArg(options::OPT_fstack_protector) ||
Expand Down
23 changes: 23 additions & 0 deletions flang/lib/Decimal/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,26 @@ add_flang_library(FortranDecimal INSTALL_WITH_TOOLCHAIN
binary-to-decimal.cpp
decimal-to-binary.cpp
)

if (DEFINED MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
add_flang_library(FortranDecimal.static INSTALL_WITH_TOOLCHAIN
binary-to-decimal.cpp
decimal-to-binary.cpp
)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)
add_flang_library(FortranDecimal.dynamic INSTALL_WITH_TOOLCHAIN
binary-to-decimal.cpp
decimal-to-binary.cpp
)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug)
add_flang_library(FortranDecimal.static_dbg INSTALL_WITH_TOOLCHAIN
binary-to-decimal.cpp
decimal-to-binary.cpp
)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebugDLL)
add_flang_library(FortranDecimal.dynamic_dbg INSTALL_WITH_TOOLCHAIN
binary-to-decimal.cpp
decimal-to-binary.cpp
)
endif()
40 changes: 34 additions & 6 deletions flang/runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,38 @@ if (NOT FLANG_EXPERIMENTAL_OMP_OFFLOAD_BUILD STREQUAL "off")
endif()
endif()

add_flang_library(FortranRuntime
${sources}
LINK_LIBS
FortranDecimal
if (NOT DEFINED MSVC)
add_flang_library(FortranRuntime
${sources}
LINK_LIBS
FortranDecimal

INSTALL_WITH_TOOLCHAIN
)
INSTALL_WITH_TOOLCHAIN
)
else()
add_flang_library(FortranRuntime
${sources}
LINK_LIBS
FortranDecimal
)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
add_flang_library(FortranRuntime.static ${sources}
LINK_LIBS
FortranDecimal.static
INSTALL_WITH_TOOLCHAIN)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)
add_flang_library(FortranRuntime.dynamic ${sources}
LINK_LIBS
FortranDecimal.dynamic
INSTALL_WITH_TOOLCHAIN)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug)
add_flang_library(FortranRuntime.static_dbg ${sources}
LINK_LIBS
FortranDecimal.static_dbg
INSTALL_WITH_TOOLCHAIN)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebugDLL)
add_flang_library(FortranRuntime.dynamic_dbg ${sources}
LINK_LIBS
FortranDecimal.dynamic_dbg
INSTALL_WITH_TOOLCHAIN)
endif()
18 changes: 18 additions & 0 deletions flang/runtime/FortranMain/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,21 @@
add_flang_library(Fortran_main STATIC INSTALL_WITH_TOOLCHAIN
Fortran_main.c
)
if (DEFINED MSVC)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded)
add_flang_library(Fortran_main.static STATIC INSTALL_WITH_TOOLCHAIN
Fortran_main.c
)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL)
add_flang_library(Fortran_main.dynamic STATIC INSTALL_WITH_TOOLCHAIN
Fortran_main.c
)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebug)
add_flang_library(Fortran_main.static_dbg STATIC INSTALL_WITH_TOOLCHAIN
Fortran_main.c
)
set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebugDLL)
add_flang_library(Fortran_main.dynamic_dbg STATIC INSTALL_WITH_TOOLCHAIN
Fortran_main.c
)
endif()
2 changes: 2 additions & 0 deletions flang/test/Driver/driver-help-hidden.f90
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
! CHECK-NEXT: -flto=jobserver Enable LTO in 'full' mode
! CHECK-NEXT: -flto=<value> Set LTO mode
! CHECK-NEXT: -flto Enable LTO in 'full' mode
! CHECK-NEXT: -fms-runtime-lib=<value>
! CHECK-NEXT: Select Windows run-time library
! CHECK-NEXT: -fno-alias-analysis Do not pass alias information on to LLVM (default for unoptimized builds)
! CHECK-NEXT: -fno-automatic Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE
! CHECK-NEXT: -fno-color-diagnostics Disable colors in diagnostics
Expand Down
2 changes: 2 additions & 0 deletions flang/test/Driver/driver-help.f90
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
! HELP-NEXT: -flto=jobserver Enable LTO in 'full' mode
! HELP-NEXT: -flto=<value> Set LTO mode
! HELP-NEXT: -flto Enable LTO in 'full' mode
! HELP-NEXT: -fms-runtime-lib=<value>
! HELP-NEXT: Select Windows run-time library
! HELP-NEXT: -fno-alias-analysis Do not pass alias information on to LLVM (default for unoptimized builds)
! HELP-NEXT: -fno-automatic Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE
! HELP-NEXT: -fno-color-diagnostics Disable colors in diagnostics
Expand Down
47 changes: 39 additions & 8 deletions flang/test/Driver/linker-flags.f90
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
! RUN: %flang -### --target=x86_64-unknown-haiku %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,HAIKU
! RUN: %flang -### --target=x86_64-windows-gnu %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MINGW

! 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 -### --target=aarch64-windows-msvc -fuse-ld= %S/Inputs/hello.f90 2>&1 | FileCheck %s --check-prefixes=CHECK,MSVC --implicit-check-not libcmt --implicit-check-not oldnames
! NOTE: Clang's driver library, clangDriver, usually adds 'oldnames' on Windows,
! 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"
Expand Down Expand Up @@ -52,8 +54,37 @@
! (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: Fortran_main.lib
! MSVC-SAME: FortranRuntime.lib
! MSVC-SAME: FortranDecimal.lib
! 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]]"

0 comments on commit cf1e342

Please sign in to comment.