1ba36147a8
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>
93 lines
2.8 KiB
Nix
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
|
|
'';
|
|
}
|