Files
Acture 1ba36147a8 flang: package standalone flang with LLVM 20+ driver fixes
Wire flang into llvmPackages as a first-class Fortran compiler. flang
is built standalone on top of the LLVM/clang package set rather than
bundled into the llvm derivation, with passthru metadata
(`langFortran`, `isFlang`, `isClang`, `hardeningUnsupportedFlags`) so
cc-wrapper and downstream tooling can detect and adapt to it.

Driver compatibility patches backported from upstream are applied
selectively per LLVM version:

  * `use-xflang-in-diagnostics` is applied to LLVM 20 and newer; it
    teaches the driver to suggest `-Xflang` instead of `-Xclang` in
    error messages for options only available to `flang -fc1`.
  * `warn-on-fbuiltin-and-fno-builtin` and
    `accept-and-ignore-some-gfortran-optimization-flags` are applied
    to LLVM 20 and 21 only. LLVM 22 has equivalent behaviour merged
    upstream (`warn_drv_invalid_argument_for_flang` and
    `clang_ignored_gcc_optimization_f_Group` handling in
    clang/lib/Driver/ToolChains/Flang.cpp), so the patches are skipped
    there.

Patches live under pkgs/development/compilers/llvm/21/flang/ and are
shared across versions via patches.nix. They are applied to a private
libclang variant rather than the flang source tree because standalone
flang resolves driver/option definitions through the installed libclang
package.

Two focused passthru tests are added:

  * `compile-smoke` exercises basic compilation and `@response-file`
    handling.
  * `driver-flags` covers wrapper flag isolation
    (`NIX_CFLAGS_COMPILE` must not leak into flang;
    `NIX_FFLAGS_COMPILE` must reach it), the backported driver
    diagnostics, and regression coverage for previously hard-erroring
    flags.

Build on the earlier standalone flang work by @picostove.

Co-authored-by: stove <stove@rivosinc.com>
Co-authored-by: acture <acture@gmail.com>
Co-authored-by: Alyssa Ross <hi@alyssa.is>
2026-05-04 18:06:36 +08:00

93 lines
2.8 KiB
Nix

{
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
'';
}