[flang-commits] [flang] 50a5f5c - [flang][driver] Add -fno-fortran-main (link time) option to remove Fortran_main from link line (#74139)
via flang-commits
flang-commits at lists.llvm.org
Mon Dec 11 04:35:33 PST 2023
Author: Michael Klemm
Date: 2023-12-11T13:35:27+01:00
New Revision: 50a5f5c1838f8583d050eb15a3b770bb4661910d
URL: https://github.com/llvm/llvm-project/commit/50a5f5c1838f8583d050eb15a3b770bb4661910d
DIFF: https://github.com/llvm/llvm-project/commit/50a5f5c1838f8583d050eb15a3b770bb4661910d.diff
LOG: [flang][driver] Add -fno-fortran-main (link time) option to remove Fortran_main from link line (#74139)
This PR adds the `-fno-fortran-main` command line option to remove
`Fortran_main.a` from the link and to allow for linking Fortran code w/o
program unit with C/C++ translation units that provide the `main()`
entrypoint.
When linking Fortran code with C/C++ code (Fortran calling into C/C++),
PR #73124 introduced a proper error message that would prevent
successful linkage, if there was a program unit from Fortran *and*
`main()` function coming from C/C++. Alas, this caused some breakage of
code that would call Fortran code from C/C++ and rightfully provided the
`main()` entrypoint. Classic Flang had the command-line option
`-fno-fortran-main` to then remove the entrypoints for the Fortran
program unit from the linker stage.
This PR is related to PR #74120 and (merged) PR #73124.
---------
Co-authored-by: Andrzej WarzyĆski <andrzej.warzynski at gmail.com>
Added:
Modified:
clang/include/clang/Driver/Options.td
clang/lib/Driver/ToolChains/CommonArgs.cpp
clang/lib/Driver/ToolChains/Flang.cpp
flang/test/Driver/driver-help-hidden.f90
flang/test/Driver/driver-help.f90
flang/test/Driver/no-duplicate-main.f90
Removed:
################################################################################
diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td
index b959fd20fe413..cf969cb0b318a 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -6354,6 +6354,12 @@ def J : JoinedOrSeparate<["-"], "J">,
Group<gfortran_Group>,
Alias<module_dir>;
+let Visibility = [FlangOption] in {
+def no_fortran_main : Flag<["-"], "fno-fortran-main">,
+ Visibility<[FlangOption]>, Group<f_Group>,
+ HelpText<"Do not include Fortran_main.a (provided by Flang) when linking">;
+} // let Visibility = [ FlangOption ]
+
//===----------------------------------------------------------------------===//
// FC1 Options
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 51b336216c565..31e7d68161ff1 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -1120,55 +1120,61 @@ void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args,
llvm::opt::ArgStringList &CmdArgs) {
// These are handled earlier on Windows by telling the frontend driver to add
// the correct libraries to link against as dependents in the object file.
- if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) {
- // The --whole-archive option needs to be part of the link line to
- // make sure that the main() function from Fortran_main.a is pulled
- // in by the linker. Determine if --whole-archive is active when
- // flang will try to link Fortran_main.a. If it is, don't add the
- // --whole-archive flag to the link line. If it's not, add a proper
- // --whole-archive/--no-whole-archive bracket to the link line.
- bool WholeArchiveActive = false;
- for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA))
- if (Arg)
- for (StringRef ArgValue : Arg->getValues()) {
- if (ArgValue == "--whole-archive")
- WholeArchiveActive = true;
- if (ArgValue == "--no-whole-archive")
- WholeArchiveActive = false;
- }
- if (!WholeArchiveActive)
- CmdArgs.push_back("--whole-archive");
- CmdArgs.push_back("-lFortran_main");
- if (!WholeArchiveActive)
- CmdArgs.push_back("--no-whole-archive");
+ // if -fno-fortran-main has been passed, skip linking Fortran_main.a
+ bool LinkFortranMain = !Args.hasArg(options::OPT_no_fortran_main);
+ if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) {
+ if (LinkFortranMain) {
+ // The --whole-archive option needs to be part of the link line to
+ // make sure that the main() function from Fortran_main.a is pulled
+ // in by the linker. Determine if --whole-archive is active when
+ // flang will try to link Fortran_main.a. If it is, don't add the
+ // --whole-archive flag to the link line. If it's not, add a proper
+ // --whole-archive/--no-whole-archive bracket to the link line.
+ bool WholeArchiveActive = false;
+ for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA))
+ if (Arg)
+ for (StringRef ArgValue : Arg->getValues()) {
+ if (ArgValue == "--whole-archive")
+ WholeArchiveActive = true;
+ if (ArgValue == "--no-whole-archive")
+ WholeArchiveActive = false;
+ }
+ if (!WholeArchiveActive)
+ CmdArgs.push_back("--whole-archive");
+ CmdArgs.push_back("-lFortran_main");
+ if (!WholeArchiveActive)
+ CmdArgs.push_back("--no-whole-archive");
+ }
// Perform regular linkage of the remaining runtime libraries.
CmdArgs.push_back("-lFortranRuntime");
CmdArgs.push_back("-lFortranDecimal");
} else {
- 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("/WHOLEARCHIVE:Fortran_main.static.lib");
- break;
- case options::OPT__SLASH_MTd:
- CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib");
- break;
- case options::OPT__SLASH_MD:
- CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib");
- break;
- case options::OPT__SLASH_MDd:
- CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib");
- break;
+ if (LinkFortranMain) {
+ 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("/WHOLEARCHIVE:Fortran_main.static.lib");
+ break;
+ case options::OPT__SLASH_MTd:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib");
+ break;
+ case options::OPT__SLASH_MD:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib");
+ break;
+ case options::OPT__SLASH_MDd:
+ CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib");
+ break;
+ }
}
}
}
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp b/clang/lib/Driver/ToolChains/Flang.cpp
index 9b21fe952af7a..502b9f17a06c5 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -231,6 +231,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
ArgStringList &CmdArgs) {
assert(TC.getTriple().isKnownWindowsMSVCEnvironment() &&
"can only add VS runtime library on Windows!");
+ // if -fno-fortran-main has been passed, skip linking Fortran_main.a
+ bool LinkFortranMain = !Args.hasArg(options::OPT_no_fortran_main);
if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
CmdArgs.push_back(Args.MakeArgString(
"--dependent-lib=" + TC.getCompilerRTBasename(Args, "builtins")));
@@ -248,7 +250,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
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");
+ if (LinkFortranMain)
+ 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;
@@ -256,7 +259,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
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");
+ if (LinkFortranMain)
+ 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;
@@ -264,7 +268,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
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");
+ if (LinkFortranMain)
+ 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;
@@ -273,7 +278,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
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");
+ if (LinkFortranMain)
+ 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;
diff --git a/flang/test/Driver/driver-help-hidden.f90 b/flang/test/Driver/driver-help-hidden.f90
index 8cb8b54d59412..9a11a7a571ffc 100644
--- a/flang/test/Driver/driver-help-hidden.f90
+++ b/flang/test/Driver/driver-help-hidden.f90
@@ -64,6 +64,7 @@
! CHECK-NEXT: Select Windows run-time library
! 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
+! CHECK-NEXT: -fno-fortran-main Do not include Fortran_main.a (provided by Flang) when linking
! CHECK-NEXT: -fno-integrated-as Disable the integrated assembler
! CHECK-NEXT: -fno-lto Disable LTO mode (default)
! CHECK-NEXT: -fno-ppc-native-vector-element-order
diff --git a/flang/test/Driver/driver-help.f90 b/flang/test/Driver/driver-help.f90
index 0607ffde23789..e0e74dc56f331 100644
--- a/flang/test/Driver/driver-help.f90
+++ b/flang/test/Driver/driver-help.f90
@@ -54,6 +54,7 @@
! HELP-NEXT: Select Windows run-time library
! 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
+! HELP-NEXT: -fno-fortran-main Do not include Fortran_main.a (provided by Flang) when linking
! HELP-NEXT: -fno-integrated-as Disable the integrated assembler
! HELP-NEXT: -fno-lto Disable LTO mode (default)
! HELP-NEXT: -fno-ppc-native-vector-element-order
diff --git a/flang/test/Driver/no-duplicate-main.f90 b/flang/test/Driver/no-duplicate-main.f90
index 4e33f4f2aeba3..12d5e46247bad 100644
--- a/flang/test/Driver/no-duplicate-main.f90
+++ b/flang/test/Driver/no-duplicate-main.f90
@@ -4,6 +4,8 @@
! RUN: %flang -o %t -c %s
! RUN: not %flang -o %t.exe %t %t.c-object 2>&1
+! RUN: %flang -fno-fortran-main -o %t.exe %t %t.c-object 2>&1
+
! TODO: potentially add further checks to ensure that proper
! linker error messages are detected and checked via
! FileCheck.
More information about the flang-commits
mailing list