Skip to content

Commit 50a5f5c

Browse files
[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 <[email protected]>
1 parent 19918ac commit 50a5f5c

File tree

6 files changed

+69
-47
lines changed

6 files changed

+69
-47
lines changed

clang/include/clang/Driver/Options.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6354,6 +6354,12 @@ def J : JoinedOrSeparate<["-"], "J">,
63546354
Group<gfortran_Group>,
63556355
Alias<module_dir>;
63566356

6357+
let Visibility = [FlangOption] in {
6358+
def no_fortran_main : Flag<["-"], "fno-fortran-main">,
6359+
Visibility<[FlangOption]>, Group<f_Group>,
6360+
HelpText<"Do not include Fortran_main.a (provided by Flang) when linking">;
6361+
} // let Visibility = [ FlangOption ]
6362+
63576363
//===----------------------------------------------------------------------===//
63586364
// FC1 Options
63596365
//===----------------------------------------------------------------------===//

clang/lib/Driver/ToolChains/CommonArgs.cpp

Lines changed: 49 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,55 +1120,61 @@ void tools::addFortranRuntimeLibs(const ToolChain &TC, const ArgList &Args,
11201120
llvm::opt::ArgStringList &CmdArgs) {
11211121
// These are handled earlier on Windows by telling the frontend driver to add
11221122
// the correct libraries to link against as dependents in the object file.
1123-
if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) {
1124-
// The --whole-archive option needs to be part of the link line to
1125-
// make sure that the main() function from Fortran_main.a is pulled
1126-
// in by the linker. Determine if --whole-archive is active when
1127-
// flang will try to link Fortran_main.a. If it is, don't add the
1128-
// --whole-archive flag to the link line. If it's not, add a proper
1129-
// --whole-archive/--no-whole-archive bracket to the link line.
1130-
bool WholeArchiveActive = false;
1131-
for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA))
1132-
if (Arg)
1133-
for (StringRef ArgValue : Arg->getValues()) {
1134-
if (ArgValue == "--whole-archive")
1135-
WholeArchiveActive = true;
1136-
if (ArgValue == "--no-whole-archive")
1137-
WholeArchiveActive = false;
1138-
}
11391123

1140-
if (!WholeArchiveActive)
1141-
CmdArgs.push_back("--whole-archive");
1142-
CmdArgs.push_back("-lFortran_main");
1143-
if (!WholeArchiveActive)
1144-
CmdArgs.push_back("--no-whole-archive");
1124+
// if -fno-fortran-main has been passed, skip linking Fortran_main.a
1125+
bool LinkFortranMain = !Args.hasArg(options::OPT_no_fortran_main);
1126+
if (!TC.getTriple().isKnownWindowsMSVCEnvironment()) {
1127+
if (LinkFortranMain) {
1128+
// The --whole-archive option needs to be part of the link line to
1129+
// make sure that the main() function from Fortran_main.a is pulled
1130+
// in by the linker. Determine if --whole-archive is active when
1131+
// flang will try to link Fortran_main.a. If it is, don't add the
1132+
// --whole-archive flag to the link line. If it's not, add a proper
1133+
// --whole-archive/--no-whole-archive bracket to the link line.
1134+
bool WholeArchiveActive = false;
1135+
for (auto *Arg : Args.filtered(options::OPT_Wl_COMMA))
1136+
if (Arg)
1137+
for (StringRef ArgValue : Arg->getValues()) {
1138+
if (ArgValue == "--whole-archive")
1139+
WholeArchiveActive = true;
1140+
if (ArgValue == "--no-whole-archive")
1141+
WholeArchiveActive = false;
1142+
}
11451143

1144+
if (!WholeArchiveActive)
1145+
CmdArgs.push_back("--whole-archive");
1146+
CmdArgs.push_back("-lFortran_main");
1147+
if (!WholeArchiveActive)
1148+
CmdArgs.push_back("--no-whole-archive");
1149+
}
11461150
// Perform regular linkage of the remaining runtime libraries.
11471151
CmdArgs.push_back("-lFortranRuntime");
11481152
CmdArgs.push_back("-lFortranDecimal");
11491153
} else {
1150-
unsigned RTOptionID = options::OPT__SLASH_MT;
1151-
if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
1152-
RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
1153-
.Case("static", options::OPT__SLASH_MT)
1154-
.Case("static_dbg", options::OPT__SLASH_MTd)
1155-
.Case("dll", options::OPT__SLASH_MD)
1156-
.Case("dll_dbg", options::OPT__SLASH_MDd)
1157-
.Default(options::OPT__SLASH_MT);
1158-
}
1159-
switch (RTOptionID) {
1160-
case options::OPT__SLASH_MT:
1161-
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static.lib");
1162-
break;
1163-
case options::OPT__SLASH_MTd:
1164-
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib");
1165-
break;
1166-
case options::OPT__SLASH_MD:
1167-
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib");
1168-
break;
1169-
case options::OPT__SLASH_MDd:
1170-
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib");
1171-
break;
1154+
if (LinkFortranMain) {
1155+
unsigned RTOptionID = options::OPT__SLASH_MT;
1156+
if (auto *rtl = Args.getLastArg(options::OPT_fms_runtime_lib_EQ)) {
1157+
RTOptionID = llvm::StringSwitch<unsigned>(rtl->getValue())
1158+
.Case("static", options::OPT__SLASH_MT)
1159+
.Case("static_dbg", options::OPT__SLASH_MTd)
1160+
.Case("dll", options::OPT__SLASH_MD)
1161+
.Case("dll_dbg", options::OPT__SLASH_MDd)
1162+
.Default(options::OPT__SLASH_MT);
1163+
}
1164+
switch (RTOptionID) {
1165+
case options::OPT__SLASH_MT:
1166+
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static.lib");
1167+
break;
1168+
case options::OPT__SLASH_MTd:
1169+
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.static_dbg.lib");
1170+
break;
1171+
case options::OPT__SLASH_MD:
1172+
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic.lib");
1173+
break;
1174+
case options::OPT__SLASH_MDd:
1175+
CmdArgs.push_back("/WHOLEARCHIVE:Fortran_main.dynamic_dbg.lib");
1176+
break;
1177+
}
11721178
}
11731179
}
11741180
}

clang/lib/Driver/ToolChains/Flang.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
231231
ArgStringList &CmdArgs) {
232232
assert(TC.getTriple().isKnownWindowsMSVCEnvironment() &&
233233
"can only add VS runtime library on Windows!");
234+
// if -fno-fortran-main has been passed, skip linking Fortran_main.a
235+
bool LinkFortranMain = !Args.hasArg(options::OPT_no_fortran_main);
234236
if (TC.getTriple().isKnownWindowsMSVCEnvironment()) {
235237
CmdArgs.push_back(Args.MakeArgString(
236238
"--dependent-lib=" + TC.getCompilerRTBasename(Args, "builtins")));
@@ -248,23 +250,26 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
248250
case options::OPT__SLASH_MT:
249251
CmdArgs.push_back("-D_MT");
250252
CmdArgs.push_back("--dependent-lib=libcmt");
251-
CmdArgs.push_back("--dependent-lib=Fortran_main.static.lib");
253+
if (LinkFortranMain)
254+
CmdArgs.push_back("--dependent-lib=Fortran_main.static.lib");
252255
CmdArgs.push_back("--dependent-lib=FortranRuntime.static.lib");
253256
CmdArgs.push_back("--dependent-lib=FortranDecimal.static.lib");
254257
break;
255258
case options::OPT__SLASH_MTd:
256259
CmdArgs.push_back("-D_MT");
257260
CmdArgs.push_back("-D_DEBUG");
258261
CmdArgs.push_back("--dependent-lib=libcmtd");
259-
CmdArgs.push_back("--dependent-lib=Fortran_main.static_dbg.lib");
262+
if (LinkFortranMain)
263+
CmdArgs.push_back("--dependent-lib=Fortran_main.static_dbg.lib");
260264
CmdArgs.push_back("--dependent-lib=FortranRuntime.static_dbg.lib");
261265
CmdArgs.push_back("--dependent-lib=FortranDecimal.static_dbg.lib");
262266
break;
263267
case options::OPT__SLASH_MD:
264268
CmdArgs.push_back("-D_MT");
265269
CmdArgs.push_back("-D_DLL");
266270
CmdArgs.push_back("--dependent-lib=msvcrt");
267-
CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic.lib");
271+
if (LinkFortranMain)
272+
CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic.lib");
268273
CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic.lib");
269274
CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic.lib");
270275
break;
@@ -273,7 +278,8 @@ static void processVSRuntimeLibrary(const ToolChain &TC, const ArgList &Args,
273278
CmdArgs.push_back("-D_DEBUG");
274279
CmdArgs.push_back("-D_DLL");
275280
CmdArgs.push_back("--dependent-lib=msvcrtd");
276-
CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic_dbg.lib");
281+
if (LinkFortranMain)
282+
CmdArgs.push_back("--dependent-lib=Fortran_main.dynamic_dbg.lib");
277283
CmdArgs.push_back("--dependent-lib=FortranRuntime.dynamic_dbg.lib");
278284
CmdArgs.push_back("--dependent-lib=FortranDecimal.dynamic_dbg.lib");
279285
break;

flang/test/Driver/driver-help-hidden.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@
6464
! CHECK-NEXT: Select Windows run-time library
6565
! CHECK-NEXT: -fno-automatic Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE
6666
! CHECK-NEXT: -fno-color-diagnostics Disable colors in diagnostics
67+
! CHECK-NEXT: -fno-fortran-main Do not include Fortran_main.a (provided by Flang) when linking
6768
! CHECK-NEXT: -fno-integrated-as Disable the integrated assembler
6869
! CHECK-NEXT: -fno-lto Disable LTO mode (default)
6970
! CHECK-NEXT: -fno-ppc-native-vector-element-order

flang/test/Driver/driver-help.f90

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@
5454
! HELP-NEXT: Select Windows run-time library
5555
! HELP-NEXT: -fno-automatic Implies the SAVE attribute for non-automatic local objects in subprograms unless RECURSIVE
5656
! HELP-NEXT: -fno-color-diagnostics Disable colors in diagnostics
57+
! HELP-NEXT: -fno-fortran-main Do not include Fortran_main.a (provided by Flang) when linking
5758
! HELP-NEXT: -fno-integrated-as Disable the integrated assembler
5859
! HELP-NEXT: -fno-lto Disable LTO mode (default)
5960
! HELP-NEXT: -fno-ppc-native-vector-element-order

flang/test/Driver/no-duplicate-main.f90

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
! RUN: %flang -o %t -c %s
55
! RUN: not %flang -o %t.exe %t %t.c-object 2>&1
66

7+
! RUN: %flang -fno-fortran-main -o %t.exe %t %t.c-object 2>&1
8+
79
! TODO: potentially add further checks to ensure that proper
810
! linker error messages are detected and checked via
911
! FileCheck.

0 commit comments

Comments
 (0)