Skip to content

[flang][driver] Add -fno-fortran-main (link time) option to remove Fortran_main from link line #74139

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

Merged
merged 9 commits into from
Dec 11, 2023
6 changes: 6 additions & 0 deletions clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -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
//===----------------------------------------------------------------------===//
Expand Down
92 changes: 49 additions & 43 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}
}
Expand Down
14 changes: 10 additions & 4 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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")));
Expand All @@ -248,23 +250,26 @@ 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;
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");
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;
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");
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;
Expand All @@ -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;
Expand Down
1 change: 1 addition & 0 deletions flang/test/Driver/driver-help-hidden.f90
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions flang/test/Driver/driver-help.f90
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions flang/test/Driver/no-duplicate-main.f90
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down