flang: update support and add flang-rt (#452306)

This commit is contained in:
Alyssa Ross
2026-05-11 14:28:54 +00:00
committed by GitHub
16 changed files with 587 additions and 88 deletions
@@ -36,6 +36,6 @@ elif [[ $0 != *cpp ]]; then
fi
fi
if [[ "@darwinMinVersion@" ]]; then
if [[ "@darwinMinVersion@" ]] && [ "@isFlang@" != 1 ]; then
extraBefore+=(-Werror=unguarded-availability)
fi
@@ -11,6 +11,8 @@ var_templates_list=(
NIX_CXXSTDLIB_COMPILE
NIX_CXXSTDLIB_LINK
NIX_GNATFLAGS_COMPILE
NIX_FFLAGS_COMPILE
NIX_FFLAGS_COMPILE_BEFORE
)
var_templates_bool=(
NIX_ENFORCE_NO_NATIVE
+14 -4
View File
@@ -44,7 +44,7 @@ while (( "$n" < "$nParams" )); do
case "$p" in
-[cSEM] | -MM) dontLink=1 ;;
-cc1) cc1=1 ;;
-cc1 | -fc1 ) cc1=1 ;;
-nostdinc) cInclude=0 cxxInclude=0 ;;
-nostdinc++) cxxInclude=0 ;;
-nostdlib) cxxLibrary=0 ;;
@@ -185,9 +185,19 @@ fi
source @out@/nix-support/add-hardening.sh
# Add the flags for the C compiler proper.
extraAfter=(${hardeningCFlagsAfter[@]+"${hardeningCFlagsAfter[@]}"} $NIX_CFLAGS_COMPILE_@suffixSalt@)
extraBefore=(${hardeningCFlagsBefore[@]+"${hardeningCFlagsBefore[@]}"} $NIX_CFLAGS_COMPILE_BEFORE_@suffixSalt@)
# Add the flags for the compiler proper. Flang reads its user-supplied
# flags from the Fortran-specific NIX_FFLAGS_COMPILE channel so that
# C-only flags injected by setup hooks (e.g. -frandom-seed= from
# reproducible-builds.sh, which Flang does not accept) never reach the
# Fortran driver. This mirrors the NIX_GNATFLAGS_COMPILE channel that
# the Ada/GNAT wrapper uses for the same reason.
if [ "@isFlang@" = 1 ]; then
extraAfter=(${hardeningCFlagsAfter[@]+"${hardeningCFlagsAfter[@]}"} $NIX_FFLAGS_COMPILE_@suffixSalt@)
extraBefore=(${hardeningCFlagsBefore[@]+"${hardeningCFlagsBefore[@]}"} $NIX_FFLAGS_COMPILE_BEFORE_@suffixSalt@)
else
extraAfter=(${hardeningCFlagsAfter[@]+"${hardeningCFlagsAfter[@]}"} $NIX_CFLAGS_COMPILE_@suffixSalt@)
extraBefore=(${hardeningCFlagsBefore[@]+"${hardeningCFlagsBefore[@]}"} $NIX_CFLAGS_COMPILE_BEFORE_@suffixSalt@)
fi
if [ "$dontLink" != 1 ]; then
linkType=$(checkLinkType $NIX_LDFLAGS_BEFORE_@suffixSalt@ "${params[@]}" ${NIX_CFLAGS_LINK_@suffixSalt@:-} $NIX_LDFLAGS_@suffixSalt@)
+26 -14
View File
@@ -26,6 +26,7 @@
nixSupport ? { },
isGNU ? false,
isClang ? cc.isClang or false,
isFlang ? cc.isFlang or false,
isZig ? cc.isZig or false,
isArocc ? cc.isArocc or false,
isCcache ? cc.isCcache or false,
@@ -387,7 +388,9 @@ let
#
# TODO: Drop `mangle-NIX_STORE-in-__FILE__.patch` from GCC and make
# this unconditional once the upstream bug is fixed.
useMacroPrefixMap = !isGNU;
useMacroPrefixMap = !isGNU && !isFlang;
systemIncludeFlag = if isFlang || isArocc then "-I" else "-idirafter";
fortifyIncludeFlag = if isFlang then "-I" else "-isystem";
in
assert includeFortifyHeaders' -> fortify-headers != null;
@@ -575,10 +578,18 @@ stdenvNoCC.mkDerivation {
''
+ optionalString cc.langFortran or false ''
wrap ${targetPrefix}gfortran $wrapper $ccPath/${targetPrefix}gfortran
ln -sv ${targetPrefix}gfortran $out/bin/${targetPrefix}g77
ln -sv ${targetPrefix}gfortran $out/bin/${targetPrefix}f77
export named_fc=${targetPrefix}gfortran
if [ -e $ccPath/${targetPrefix}gfortran ]; then
wrap ${targetPrefix}gfortran $wrapper $ccPath/${targetPrefix}gfortran
ln -sv ${targetPrefix}gfortran $out/bin/${targetPrefix}g77
ln -sv ${targetPrefix}gfortran $out/bin/${targetPrefix}f77
export named_fc=${targetPrefix}gfortran
elif [ -e $ccPath/${targetPrefix}flang ]; then
wrap ${targetPrefix}flang $wrapper $ccPath/${targetPrefix}flang
export named_fc=${targetPrefix}flang
elif [ -e $ccPath/flang ]; then
wrap ${targetPrefix}flang $wrapper $ccPath/flang
export named_fc=${targetPrefix}flang
fi
''
+ optionalString cc.langGo or false ''
@@ -714,9 +725,7 @@ stdenvNoCC.mkDerivation {
echo "-B${libc_lib}${libc.libdir or "/lib/"}" >> $out/nix-support/libc-crt1-cflags
''
+ ''
include "-${
if isArocc then "I" else "idirafter"
}" "${libc_dev}${libc.incdir or "/include"}" >> $out/nix-support/libc-cflags
include "${systemIncludeFlag}" "${libc_dev}${libc.incdir or "/include"}" >> $out/nix-support/libc-cflags
''
+ optionalString isGNU ''
for dir in "${cc}"/lib/gcc/*/*/include-fixed; do
@@ -724,9 +733,9 @@ stdenvNoCC.mkDerivation {
done
''
+ optionalString (libc.w32api or null != null) ''
echo '-idirafter ${lib.getDev libc.w32api}${
include "${systemIncludeFlag}" "${lib.getDev libc.w32api}${
libc.incdir or "/include/w32api"
}' >> $out/nix-support/libc-cflags
}" >> $out/nix-support/libc-cflags
''
+ ''
@@ -741,7 +750,7 @@ stdenvNoCC.mkDerivation {
# like option that forces the libc headers before all -idirafter,
# hence -isystem here.
+ optionalString includeFortifyHeaders' ''
include -isystem "${fortify-headers}/include" >> $out/nix-support/libc-cflags
include "${fortifyIncludeFlag}" "${fortify-headers}/include" >> $out/nix-support/libc-cflags
''
)
@@ -762,7 +771,7 @@ stdenvNoCC.mkDerivation {
# already knows how to find its own libstdc++, and adding
# additional -isystem flags will confuse gfortran (see
# https://github.com/NixOS/nixpkgs/pull/209870#issuecomment-1500550903)
+ optionalString (libcxx == null && isClang && (useGccForLibs && gccForLibs.langCC or false)) ''
+ optionalString (libcxx == null && isClang && useGccForLibs && (cc.langCC or false)) ''
for dir in ${gccForLibs}/include/c++/*; do
include -cxx-isystem "$dir" >> $out/nix-support/libcxx-cxxflags
done
@@ -829,6 +838,7 @@ stdenvNoCC.mkDerivation {
optionalString
(
(cc.isClang or false)
&& !isFlang
&& !(cc.isROCm or false)
&& !targetPlatform.isDarwin
&& !targetPlatform.isAndroid
@@ -863,7 +873,8 @@ stdenvNoCC.mkDerivation {
let
enable_fp = !targetPlatform.isx86_32 && !targetPlatform.isS390;
enable_leaf_fp =
enable_fp
!isFlang
&& enable_fp
&& (
targetPlatform.isx86_64
|| targetPlatform.isAarch64
@@ -929,7 +940,7 @@ stdenvNoCC.mkDerivation {
# well with multi line flags, so make the flags single line again
+ ''
for flags in "$out/nix-support"/*flags*; do
substituteInPlace "$flags" --replace $'\n' ' '
substituteInPlace "$flags" --replace-quiet $'\n' ' '
done
substituteAll ${./add-flags.sh} $out/nix-support/add-flags.sh
@@ -975,6 +986,7 @@ stdenvNoCC.mkDerivation {
env = {
inherit isClang;
inherit isFlang;
# for substitution in utils.bash
# TODO(@sternenseemann): invent something cleaner than passing in "" in case of absence
@@ -0,0 +1,49 @@
From da7174958be43d69b2ed6b581c8ac8a382b59180 Mon Sep 17 00:00:00 2001
From: Tarun Prabhu <tarun.prabhu@gmail.com>
Date: Tue, 28 Oct 2025 19:35:27 -0600
Subject: [PATCH] [flang][Driver] Accept (and ignore) some gfortran-specific
options
Enable the clang_ignored_gcc_optimization_f_group in flang. These options are
accepted by clang, but ignored after emitting a warning message. flang's
behavior now mirrors clang.
Fixes #158436
---
clang/include/clang/Driver/Options.td | 3 ++-
clang/lib/Driver/ToolChains/Flang.cpp | 8 ++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index ef1c8758705f4..cac122d296624 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -316,7 +316,8 @@ def mno_mpx : Flag<["-"], "mno-mpx">, Group<clang_ignored_legacy_options_Group>;
// Group that ignores all gcc optimizations that won't be implemented
def clang_ignored_gcc_optimization_f_Group : OptionGroup<
- "<clang_ignored_gcc_optimization_f_Group>">, Group<f_Group>, Flags<[Ignored]>;
+ "<clang_ignored_gcc_optimization_f_Group>">,
+ Group<f_Group>, Flags<[Ignored]>, Visibility<[ClangOption, FlangOption]>;
class DiagnosticOpts<string base>
: KeyPathAndMacro<"DiagnosticOpts->", base, "DIAG_"> {}
diff --git a/lib/Driver/ToolChains/Flang.cpp b/lib/Driver/ToolChains/Flang.cpp
index 88bce181d40d2..2f5e93d139858 100644
--- a/lib/Driver/ToolChains/Flang.cpp
+++ b/lib/Driver/ToolChains/Flang.cpp
@@ -858,6 +858,14 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
if (const Arg *A = Args.getLastArg(Opt))
D.Diag(diag::warn_drv_invalid_argument_for_flang) << A->getSpelling();
+ // Warn about options that are ignored by flang. These are options that are
+ // accepted by gfortran, but have no equivalent in flang.
+ for (const Arg *A :
+ Args.filtered(options::OPT_clang_ignored_gcc_optimization_f_Group)) {
+ D.Diag(diag::warn_ignored_gcc_optimization) << A->getAsString(Args);
+ A->claim();
+ }
+
const InputInfo &Input = Inputs[0];
types::ID InputType = Input.getType();
@@ -0,0 +1,40 @@
From 9ab9d33171ee35c948967a2a2d714b8059887607 Mon Sep 17 00:00:00 2001
From: Tarun Prabhu <tarun@lanl.gov>
Date: Wed, 29 Oct 2025 09:13:17 -0600
Subject: [PATCH] [flang][driver] Use -Xflang in diagnostics
When an option that is only available in `flang -fc1` is provided to
`flang`, emit a diagnostic with a suggestion containing "did you mean
-Xflang '-foo'".
Partially addresses #163550.
---
clang/lib/Driver/Driver.cpp | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index 40ea513e85427..71c52807091ba 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -365,9 +365,18 @@
auto ArgString = A->getAsString(Args);
std::string Nearest;
if (getOpts().findNearest(ArgString, Nearest, VisibilityMask) > 1) {
- if (!IsCLMode() &&
- getOpts().findExact(ArgString, Nearest,
- llvm::opt::Visibility(options::CC1Option))) {
+ if (IsFlangMode()) {
+ if (getOpts().findExact(ArgString, Nearest,
+ llvm::opt::Visibility(options::FC1Option))) {
+ DiagID = diag::err_drv_unknown_argument_with_suggestion;
+ Diags.Report(DiagID) << ArgString << "-Xflang " + Nearest;
+ } else {
+ DiagID = diag::err_drv_unknown_argument;
+ Diags.Report(DiagID) << ArgString;
+ }
+ } else if (!IsCLMode() && getOpts().findExact(ArgString, Nearest,
+ llvm::opt::Visibility(
+ options::CC1Option))) {
DiagID = diag::err_drv_unknown_argument_with_suggestion;
Diags.Report(DiagID) << ArgString << "-Xclang " + Nearest;
} else {
@@ -0,0 +1,74 @@
From 263377a175709c2d11f3ff63c2d2d2843afb91ea Mon Sep 17 00:00:00 2001
From: Tarun Prabhu <tarun@lanl.gov>
Date: Thu, 23 Oct 2025 13:24:20 -0600
Subject: [PATCH] [flang][Driver] Warn on -fbuiltin and -fno-builtin
The options -fbuiltin and -fno-builtin are not valid for Fortran. However,
they are accepted by gfortran which emits a warning message but continues to
compile the code. Both -fbuiltin and -fno-builtin have been enabled for flang.
Specifying either will result in a warning message being shown but no other
effects. Compilation will proceed normally after these warnings are shown. This
brings flang's behavior in line with gfortran for these options.
Fixes #164766
---
clang/include/clang/Basic/DiagnosticDriverKinds.td | 3 +++
clang/include/clang/Driver/Options.td | 4 ++--
clang/lib/Driver/ToolChains/Flang.cpp | 7 +++++++
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/include/clang/Basic/DiagnosticDriverKinds.td b/include/clang/Basic/DiagnosticDriverKinds.td
index 0581bf353d936..83980e3ac35b7 100644
--- a/include/clang/Basic/DiagnosticDriverKinds.td
+++ b/include/clang/Basic/DiagnosticDriverKinds.td
@@ -131,6 +131,9 @@ def warn_drv_unsupported_option_for_offload_arch_req_feature : Warning<
def warn_drv_unsupported_option_for_target : Warning<
"ignoring '%0' option as it is not currently supported for target '%1'">,
InGroup<OptionIgnored>;
+def warn_drv_invalid_argument_for_flang : Warning<
+ "'%0' is not valid for Fortran">,
+ InGroup<OptionIgnored>;
def warn_drv_unsupported_option_for_flang : Warning<
"the argument '%0' is not supported for option '%1'. Mapping to '%1%2'">,
InGroup<OptionIgnored>;
diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td
index ef1c8758705f4..bca8b26bc3d30 100644
--- a/include/clang/Driver/Options.td
+++ b/include/clang/Driver/Options.td
@@ -1940,7 +1940,7 @@ defm borland_extensions : BoolFOption<"borland-extensions",
"Accept non-standard constructs supported by the Borland compiler">,
NegFlag<SetFalse>>;
def fbuiltin : Flag<["-"], "fbuiltin">, Group<f_Group>,
- Visibility<[ClangOption, CLOption, DXCOption]>;
+ Visibility<[ClangOption, CLOption, DXCOption, FlangOption, FC1Option]>;
def fbuiltin_module_map : Flag <["-"], "fbuiltin-module-map">, Group<f_Group>,
Flags<[]>, HelpText<"Load the clang builtins module map file.">;
defm caret_diagnostics : BoolFOption<"caret-diagnostics",
@@ -3493,7 +3493,7 @@ def fno_assume_sane_operator_new : Flag<["-"], "fno-assume-sane-operator-new">,
HelpText<"Don't assume that C++'s global operator new can't alias any pointer">,
Visibility<[ClangOption, CC1Option]>,
MarshallingInfoNegativeFlag<CodeGenOpts<"AssumeSaneOperatorNew">>;
def fno_builtin : Flag<["-"], "fno-builtin">, Group<f_Group>,
- Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>,
+ Visibility<[ClangOption, CC1Option, CLOption, DXCOption, FlangOption, FC1Option]>,
HelpText<"Disable implicit builtin knowledge of functions">;
def fno_builtin_ : Joined<["-"], "fno-builtin-">, Group<f_Group>,
Visibility<[ClangOption, CC1Option, CLOption, DXCOption]>,
diff --git a/lib/Driver/ToolChains/Flang.cpp b/lib/Driver/ToolChains/Flang.cpp
index a56fa41c49d34..88bce181d40d2 100644
--- a/lib/Driver/ToolChains/Flang.cpp
+++ b/lib/Driver/ToolChains/Flang.cpp
@@ -851,6 +851,13 @@ void Flang::ConstructJob(Compilation &C, const JobAction &JA,
assert(false && "Unexpected action class for Flang tool.");
}
+ // We support some options that are invalid for Fortran and have no effect.
+ // These are solely for compatibility with other compilers. Emit a warning if
+ // any such options are provided, then proceed normally.
+ for (options::ID Opt : {options::OPT_fbuiltin, options::OPT_fno_builtin})
+ if (const Arg *A = Args.getLastArg(Opt))
+ D.Diag(diag::warn_drv_invalid_argument_for_flang) << A->getSpelling();
+
const InputInfo &Input = Inputs[0];
types::ID InputType = Input.getType();
@@ -16,6 +16,7 @@
fixDarwinDylibNames,
enableManpages ? false,
enableClangToolsExtra ? true,
extraPatches ? [ ],
devExtraCmakeFlags ? [ ],
replaceVars,
getVersionFile,
@@ -73,7 +74,8 @@ stdenv.mkDerivation (
];
stripLen = 1;
hash = "sha256-1NKej08R9SPlbDY/5b0OKUsHjX07i9brR84yXiPwi7E=";
});
})
++ extraPatches;
nativeBuildInputs = [
cmake
@@ -189,6 +191,8 @@ stdenv.mkDerivation (
passthru = {
inherit libllvm;
isClang = true;
langC = true;
langCC = true;
hardeningUnsupportedFlagsByTargetPlatform =
targetPlatform:
[ "fortify3" ]
@@ -476,28 +476,93 @@ makeScopeWithSplicing' {
// lib.optionalAttrs (lib.versionAtLeast metadata.release_version "19") {
bolt = callPackage ./bolt { };
}
// lib.optionalAttrs (lib.versionAtLeast metadata.release_version "20") {
flang = callPackage ./flang { };
// lib.optionalAttrs (lib.versionAtLeast metadata.release_version "20") (
let
# Standalone flang still resolves driver/option definitions via the
# installed libclang package, so keep flang-specific driver backports
# in a private libclang variant instead of patching the flang source
# tree. The `-Xflang` diagnostic improvement applies to every
# supported standalone-flang version (20+); the other two backports
# are only needed up to LLVM 21 because upstream merged equivalent
# behaviour into LLVM 22.
flangDriverPatches =
lib.optionals (lib.versionAtLeast metadata.release_version "20") [
(metadata.getVersionFile "flang/use-xflang-in-diagnostics.patch")
]
++
lib.optionals
(lib.versionAtLeast metadata.release_version "20" && lib.versionOlder metadata.release_version "22")
[
(metadata.getVersionFile "flang/warn-on-fbuiltin-and-fno-builtin.patch")
(metadata.getVersionFile "flang/accept-and-ignore-some-gfortran-optimization-flags.patch")
];
flangLibclang =
if flangDriverPatches == [ ] then
self.libclang
else
self.libclang.override {
extraPatches = flangDriverPatches;
};
flangUnwrapped = callPackage ./flang {
libclang = flangLibclang;
};
flangRt = callPackage ./flang-rt {
buildFlang = buildLlvmPackages.flang-unwrapped;
};
in
{
flang-unwrapped = flangUnwrapped;
flang-rt = flangRt;
flang =
let
wrapped = wrapCCWith rec {
cc = flangUnwrapped;
bintools = bintools';
extraPackages = [ targetLlvmPackages.flang-rt ];
extraBuildCommands = mkExtraBuildCommands0 cc + ''
# triplet however is not used in darwin
PLATFORM_DIR="${if stdenv.targetPlatform.isDarwin then "darwin" else stdenv.targetPlatform.config}"
RT_LIB_PATH="${targetLlvmPackages.flang-rt}/lib/clang/${clangVersion}/lib/$PLATFORM_DIR"
if [ -d "$RT_LIB_PATH" ]; then
ln -s "$RT_LIB_PATH" "$rsrc"/lib
echo "-L$rsrc/lib" >> $out/nix-support/cc-ldflags
else
ln -s "${targetLlvmPackages.flang-rt}/lib" "$rsrc"/lib
echo "-L$rsrc/lib" >> $out/nix-support/cc-ldflags
fi
'';
};
tests = callPackage ./flang/tests.nix {
flang = wrapped;
};
in
wrapped
// {
passthru = (wrapped.passthru or { }) // {
inherit tests;
};
};
libc-overlay = callPackage ./libc {
isFullBuild = false;
# Use clang due to "gnu::naked" not working on aarch64.
# Issue: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77882
stdenv = overrideCC stdenv buildLlvmPackages.clang;
};
libc-overlay = callPackage ./libc {
isFullBuild = false;
# Use clang due to "gnu::naked" not working on aarch64.
# Issue: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77882
stdenv = overrideCC stdenv buildLlvmPackages.clang;
};
libc-full = callPackage ./libc {
isFullBuild = true;
# Use clang due to "gnu::naked" not working on aarch64.
# Issue: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77882
stdenv = overrideCC stdenv buildLlvmPackages.clangNoLibcNoRt;
# FIXME: This should almost certainly be `stdenv.hostPlatform`.
cmake = if stdenv.targetPlatform.libc == "llvm" then cmakeMinimal else cmake;
python3 = if stdenv.targetPlatform.libc == "llvm" then python3Minimal else python3;
};
libc-full = callPackage ./libc {
isFullBuild = true;
# Use clang due to "gnu::naked" not working on aarch64.
# Issue: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=77882
stdenv = overrideCC stdenv buildLlvmPackages.clangNoLibcNoRt;
# FIXME: This should almost certainly be `stdenv.hostPlatform`.
cmake = if stdenv.targetPlatform.libc == "llvm" then cmakeMinimal else cmake;
python3 = if stdenv.targetPlatform.libc == "llvm" then python3Minimal else python3;
};
libc =
# FIXME: This should almost certainly be `stdenv.hostPlatform`.
if stdenv.targetPlatform.libc == "llvm" then self.libc-full else self.libc-overlay;
};
libc =
# FIXME: This should almost certainly be `stdenv.hostPlatform`.
if stdenv.targetPlatform.libc == "llvm" then self.libc-full else self.libc-overlay;
}
);
}
@@ -0,0 +1,81 @@
{
lib,
stdenv,
llvm_meta,
monorepoSrc,
runCommand,
cmake,
libllvm,
ninja,
python3,
buildFlang,
version,
}:
let
minDarwinVersion = "10.12";
effectiveDarwinVersion =
if stdenv.isDarwin && lib.versionOlder stdenv.hostPlatform.darwinMinVersion minDarwinVersion then
minDarwinVersion
else
stdenv.hostPlatform.darwinMinVersion;
in
stdenv.mkDerivation (finalAttrs: {
pname = "flang-rt";
inherit version;
src =
runCommand "${finalAttrs.pname}-src-${version}"
{
inherit (monorepoSrc) passthru;
}
''
mkdir -p "$out"
cp -r ${monorepoSrc}/cmake "$out"
mkdir -p "$out/llvm"
cp -r ${monorepoSrc}/llvm/cmake "$out/llvm"
cp -r ${monorepoSrc}/llvm/utils "$out/llvm"
cp -r ${monorepoSrc}/third-party "$out"
cp -r ${monorepoSrc}/${finalAttrs.pname} "$out"
cp -r ${monorepoSrc}/flang "$out"
cp -r ${monorepoSrc}/runtimes "$out"
'';
sourceRoot = "${finalAttrs.src.name}/runtimes";
outputs = [ "out" ];
nativeBuildInputs = [
buildFlang
cmake
ninja
python3
];
buildInputs = [
libllvm
];
env = lib.optionalAttrs stdenv.isDarwin {
MACOSX_DEPLOYMENT_TARGET = effectiveDarwinVersion;
NIX_CFLAGS_COMPILE = "-mmacosx-version-min=${effectiveDarwinVersion}";
};
cmakeFlags = [
(lib.cmakeFeature "LLVM_DEFAULT_TARGET_TRIPLE" stdenv.hostPlatform.config)
(lib.cmakeFeature "CMAKE_Fortran_COMPILER" "${buildFlang}/bin/flang")
(lib.cmakeBool "CMAKE_Fortran_COMPILER_WORKS" true)
(lib.cmakeBool "CMAKE_Fortran_COMPILER_SUPPORTS_F90" true)
(lib.cmakeFeature "LLVM_DIR" "${libllvm.dev}/lib/cmake/llvm")
(lib.cmakeFeature "LLVM_ENABLE_RUNTIMES" "flang-rt")
]
++ lib.optionals stdenv.isDarwin [
(lib.cmakeFeature "CMAKE_OSX_DEPLOYMENT_TARGET" effectiveDarwinVersion)
];
meta = llvm_meta // {
homepage = "https://flang.llvm.org";
description = "LLVM Fortran Runtime";
};
})
@@ -23,21 +23,25 @@ stdenv.mkDerivation (finalAttrs: {
pname = "flang";
inherit version;
src = runCommand "flang-src-${version}" { inherit (monorepoSrc) passthru; } ''
mkdir -p "$out"
cp -r ${monorepoSrc}/${finalAttrs.pname} "$out"
cp -r ${monorepoSrc}/cmake "$out"
cp -r ${monorepoSrc}/llvm "$out"
cp -r ${monorepoSrc}/clang "$out"
cp -r ${monorepoSrc}/mlir "$out"
cp -r ${monorepoSrc}/third-party "$out"
chmod -R +w $out/llvm
'';
src =
runCommand "${finalAttrs.pname}-src-${finalAttrs.version}"
{
inherit (monorepoSrc) passthru;
}
''
mkdir -p "$out"
cp -r ${monorepoSrc}/${finalAttrs.pname} "$out"
cp -r ${monorepoSrc}/cmake "$out"
cp -r ${monorepoSrc}/llvm "$out"
cp -r ${monorepoSrc}/clang "$out"
cp -r ${monorepoSrc}/mlir "$out"
cp -r ${monorepoSrc}/third-party "$out"
cp -r ${monorepoSrc}/flang-rt "$out"
chmod -R +w $out/llvm
'';
patches = [
./dummy_target_19+.patch
];
patchFlags = [ "-p2" ];
patches = [ ];
patchFlags = [ "-p1" ];
sourceRoot = "${finalAttrs.src.name}/flang";
@@ -62,24 +66,35 @@ stdenv.mkDerivation (finalAttrs: {
ls -l ${mlir.dev}/lib/cmake/mlir/MLIRConfig.cmake
'';
cmakeFlags = [
(lib.cmakeBool "CMAKE_VERBOSE_MAKEFILE" true)
(lib.cmakeFeature "LLVM_DIR" "${libllvm.dev}/lib/cmake/llvm")
# TODO: Needs patches and the `lit` package like other LLVM builds?
(lib.cmakeFeature "LLVM_TOOLS_BINARY_DIR" "${buildLlvmPackages.tblgen}/bin/")
(lib.cmakeFeature "LLVM_EXTERNAL_LIT" "${buildLlvmPackages.tblgen}/bin/llvm-lit")
(lib.cmakeFeature "CLANG_DIR" "${libclang.dev}/lib/cmake/clang")
(lib.cmakeFeature "MLIR_DIR" "${mlir.dev}/lib/cmake/mlir")
(lib.cmakeFeature "MLIR_TABLEGEN_EXE" "${buildLlvmPackages.tblgen}/bin/mlir-tblgen")
(lib.cmakeFeature "MLIR_TABLEGEN_TARGET" "MLIR-TBLGen")
(lib.cmakeBool "LLVM_BUILD_EXAMPLES" false)
(lib.cmakeBool "MLIR_LINK_MLIR_DYLIB" (!stdenv.hostPlatform.isStatic))
(lib.cmakeFeature "LLVM_LIT_ARGS" "-v")
(lib.cmakeBool "LLVM_ENABLE_PLUGINS" false)
(lib.cmakeBool "FLANG_STANDALONE_BUILD" true)
(lib.cmakeBool "LLVM_INCLUDE_EXAMPLES" false)
(lib.cmakeBool "FLANG_INCLUDE_TESTS" false)
]
++ devExtraCmakeFlags;
passthru = {
# Used by cc-wrapper to determine whether or not the default setup hook is enabled.
langC = false;
langCC = false;
langFortran = true;
isClang = true;
isFlang = true;
hardeningUnsupportedFlags = [
"zerocallusedregs"
"stackprotector"
"stackclashprotection"
];
};
postUnpack = ''
chmod -R u+w -- $sourceRoot/..
'';
@@ -1,27 +0,0 @@
diff --git a/flang/CMakeLists.txt b/flang/CMakeLists.txt
index 070c39eb6e9a..168c97524943 100644
--- a/flang/CMakeLists.txt
+++ b/flang/CMakeLists.txt
@@ -1,6 +1,22 @@
cmake_minimum_required(VERSION 3.20.0)
set(LLVM_SUBPROJECT_TITLE "Flang")
+# Patch: define dummy mlir-tblgen target for TableGen.cmake
+if(DEFINED MLIR_TABLEGEN_EXE AND NOT TARGET mlir-tblgen)
+ add_executable(mlir-tblgen IMPORTED GLOBAL)
+ set_target_properties(mlir-tblgen PROPERTIES
+ IMPORTED_LOCATION "${MLIR_TABLEGEN_EXE}"
+ )
+endif()
+
+if(DEFINED MLIR_TABLEGEN_EXE AND NOT TARGET MLIR-TBLGen)
+ add_executable(MLIR-TBLGen IMPORTED GLOBAL)
+ set_target_properties(MLIR-TBLGen PROPERTIES
+ IMPORTED_LOCATION "${MLIR_TABLEGEN_EXE}"
+ )
+endif()
+
+
if(NOT DEFINED LLVM_COMMON_CMAKE_UTILS)
set(LLVM_COMMON_CMAKE_UTILS ${CMAKE_CURRENT_SOURCE_DIR}/../cmake)
endif()
@@ -0,0 +1,92 @@
{
runCommand,
flang,
}:
let
flangExe = "${flang}/bin/flang";
writeHello = ''
cat > hello.f90 <<'EOF'
program hello
end program hello
EOF
'';
in
{
compile-smoke = runCommand "flang-compile-smoke" { } ''
set -euo pipefail
${writeHello}
${flangExe} -c hello.f90 -o compile.o
[ -f compile.o ]
cat > args.rsp <<'EOF'
-c
hello.f90
-o
response.o
EOF
${flangExe} @args.rsp
[ -f response.o ]
touch $out
'';
driver-flags = runCommand "flang-driver-flags" { } ''
set -euo pipefail
${writeHello}
${flangExe} -### -c hello.f90 > no-seed.log 2>&1
if grep -F -- "-frandom-seed=" no-seed.log; then
echo "wrapper unexpectedly injected -frandom-seed" >&2
exit 1
fi
# Confirm that user-supplied NIX_CFLAGS_COMPILE does not leak into the
# Fortran wrapper invocation: the wrapper must source flags from
# NIX_FFLAGS_COMPILE only, so a marker placed in NIX_CFLAGS_COMPILE
# must not appear in the resulting flang command line.
NIX_CFLAGS_COMPILE="-Icflags-leak-marker-include" \
${flangExe} -### -c hello.f90 > cflags-isolation.log 2>&1
if grep -F -- "cflags-leak-marker-include" cflags-isolation.log; then
echo "NIX_CFLAGS_COMPILE leaked into the flang wrapper" >&2
exit 1
fi
# Confirm that NIX_FFLAGS_COMPILE is the user-facing channel for
# Fortran flags and flows through to the driver.
NIX_FFLAGS_COMPILE="-Iffflags-marker-include" \
${flangExe} -### -c hello.f90 > fflags-passthrough.log 2>&1
grep -F -- "ffflags-marker-include" fflags-passthrough.log
${flangExe} -### -fbuiltin -fno-builtin hello.f90 > builtin.log 2>&1
grep -F -- "warning: '-fbuiltin' is not valid for Fortran" builtin.log
grep -F -- "warning: '-fno-builtin' is not valid for Fortran" builtin.log
if grep -F -- "error: unknown argument" builtin.log; then
echo "builtin compatibility flags unexpectedly failed" >&2
exit 1
fi
${flangExe} -### -fexpensive-optimizations hello.f90 > ignored-flag.log 2>&1
grep -F -- "optimization flag '-fexpensive-optimizations' is not supported" ignored-flag.log
if grep -F -- "error: unknown argument" ignored-flag.log; then
echo "ignored gfortran-style flag unexpectedly failed" >&2
exit 1
fi
if ${flangExe} -### -complex-range=full hello.f90 > suggestion.log 2>&1; then
echo "expected -complex-range=full to fail at the driver layer" >&2
exit 1
fi
grep -F -- "error: unknown argument '-complex-range=full'" suggestion.log
grep -F -- "did you mean '-Xflang -complex-range=full'" suggestion.log
if grep -F -- "-Xclang -complex-range=full" suggestion.log; then
echo "driver suggested -Xclang instead of -Xflang" >&2
exit 1
fi
touch $out
'';
}
@@ -39,6 +39,14 @@ stdenv.mkDerivation (finalAttrs: {
patches = [
./gnu-install-dirs.patch
# MLIRConfig.cmake unconditionally overwrites MLIR_TABLEGEN_EXE, breaking standalone
# builds that provide their own pre-built mlir-tblgen (e.g. in Nix sandboxed builds).
# The patch adds guards to respect caller-set values and auto-creates an imported
# mlir-tblgen target for downstream consumers. This replaces the previous dummy target
# workaround in flang's CMakeLists.txt.
# Upstream issue: https://github.com/llvm/llvm-project/issues/150986
./mlir-tablegen-imported-target.patch
]
++ lib.optional (lib.versionOlder release_version "20") [
# Fix build with gcc15
@@ -0,0 +1,54 @@
diff --git a/cmake/modules/MLIRConfig.cmake.in b/cmake/modules/MLIRConfig.cmake.in
index 71f3e028b1e8..b30b6cdc0de1 100644
--- a/cmake/modules/MLIRConfig.cmake.in
+++ b/cmake/modules/MLIRConfig.cmake.in
@@ -9,9 +9,16 @@ find_package(LLVM ${LLVM_VERSION} EXACT REQUIRED CONFIG
set(MLIR_EXPORTED_TARGETS "@MLIR_EXPORTS@")
set(MLIR_CMAKE_DIR "@MLIR_CONFIG_CMAKE_DIR@")
set(MLIR_INCLUDE_DIRS "@MLIR_CONFIG_INCLUDE_DIRS@")
-set(MLIR_TABLEGEN_EXE "@MLIR_CONFIG_TABLEGEN_EXE@")
-set(MLIR_PDLL_TABLEGEN_EXE "@MLIR_CONFIG_PDLL_TABLEGEN_EXE@")
-set(MLIR_SRC_SHARDER_TABLEGEN_EXE "@MLIR_CONFIG_SRC_SHARDER_TABLEGEN_EXE@")
+# Allow users to override tablegen executables (e.g. for sandboxed builds).
+if(NOT MLIR_TABLEGEN_EXE)
+ set(MLIR_TABLEGEN_EXE "@MLIR_CONFIG_TABLEGEN_EXE@")
+endif()
+if(NOT MLIR_PDLL_TABLEGEN_EXE)
+ set(MLIR_PDLL_TABLEGEN_EXE "@MLIR_CONFIG_PDLL_TABLEGEN_EXE@")
+endif()
+if(NOT MLIR_SRC_SHARDER_TABLEGEN_EXE)
+ set(MLIR_SRC_SHARDER_TABLEGEN_EXE "@MLIR_CONFIG_SRC_SHARDER_TABLEGEN_EXE@")
+endif()
set(MLIR_IRDL_TO_CPP_EXE "@MLIR_CONFIG_IRDL_TO_CPP_EXE@")
set(MLIR_INSTALL_AGGREGATE_OBJECTS "@MLIR_INSTALL_AGGREGATE_OBJECTS@")
set(MLIR_ENABLE_BINDINGS_PYTHON "@MLIR_ENABLE_BINDINGS_PYTHON@")
@@ -32,6 +39,29 @@ if(NOT TARGET MLIRSupport)
@MLIR_CONFIG_INCLUDE_EXPORTS@
endif()
+# Ensure MLIR_TABLEGEN_EXE is a full path and has a corresponding imported
+# target. In install trees, MLIR_TABLEGEN_EXE may be a bare name
+# ("mlir-tblgen") rather than an absolute path. Resolve it so that
+# TableGen.cmake can use it as both a COMMAND and a DEPENDS entry.
+if(MLIR_TABLEGEN_EXE AND NOT IS_ABSOLUTE "${MLIR_TABLEGEN_EXE}"
+ AND NOT TARGET "${MLIR_TABLEGEN_EXE}")
+ find_program(_mlir_tblgen_exe "${MLIR_TABLEGEN_EXE}"
+ HINTS "${LLVM_TOOLS_BINARY_DIR}")
+ if(_mlir_tblgen_exe)
+ set(MLIR_TABLEGEN_EXE "${_mlir_tblgen_exe}")
+ endif()
+ unset(_mlir_tblgen_exe)
+endif()
+
+if(NOT TARGET mlir-tblgen AND MLIR_TABLEGEN_EXE)
+ add_executable(mlir-tblgen IMPORTED GLOBAL)
+ set_target_properties(mlir-tblgen PROPERTIES
+ IMPORTED_LOCATION "${MLIR_TABLEGEN_EXE}")
+endif()
+if(NOT DEFINED MLIR_TABLEGEN_TARGET)
+ set(MLIR_TABLEGEN_TARGET mlir-tblgen)
+endif()
+
# By creating these targets here, subprojects that depend on MLIR's
# tablegen-generated headers can always depend on these targets whether building
# in-tree with MLIR or not.
@@ -138,4 +138,24 @@
path = ../19;
}
];
"flang/warn-on-fbuiltin-and-fno-builtin.patch" = [
{
after = "20";
before = "22";
path = ../21;
}
];
"flang/accept-and-ignore-some-gfortran-optimization-flags.patch" = [
{
after = "20";
before = "22";
path = ../21;
}
];
"flang/use-xflang-in-diagnostics.patch" = [
{
after = "20";
path = ../21;
}
];
}