Maintaining recent versions of multiple Fortran compilers can be
cumbersome if you infrequently need some of the compilers, so something
like the Compiler Explorer webpage is handly for running short standalone
minimal reproducers on a variety of compilers.
If you are not a GUI user the command line interface provided at
GitHub - xfgusta/cexpl: Command-line tool to interact with Compiler Explorer · GitHub lets you easily compiler and run these
little cases (Something that uses only a few seconds compile and execution
time essentially what is suitable).
If you want to run on multiple compilers and use custom options even the
simple-to-use cexpl interface can benefit from a wrapper.
Here is a bash shell that can act as a model for such a wrapper. You almost
certainly will want to customize the compiler options and the list of
compilers but with cexpl(1) installed you can run simple codes on half a
dozen common Fortran compilers without requiring any of the to be installed
and compare ouput with a single command line.
The output from the following script is formatted for use with Discourse.
So running
fall -e hello.f90
Will generate markdown output that shows the input code and the results
from a variety of compilers with the output prefixed with a line count and
the name of the Compiler Explorer mnemonic for the compiler. The example
output follows the script.
Example bash script
##!/bin/bash
#@(#) fall(1) - call Compiler Explorer Fortran compilers for specified file
################################################################################
HELP(){
cat <<\EOF
NAME
fall(1) - run a simple self-contained program with a variety of
Fortran compilers using cexpl(1).
SYNOPSIS
command format:
fall Fortran_Source_File
[-e] Execute program
[--cflags FLAGS] Additional compiler flags
[--args "ARGV [ARGV ..."] Command line arguments to pass
[--stdin STDIN ] Data to read as stdin
DESCRIPTION
fall(1) is a wrapper around cexpl(1). cexpl(1) is a command-line tool
to interact with Compiler Explorer.
Typically you only get a few seconds for a compilation and a few
seconds for an execution.
Note that in CE #include directives can access files via curl(1).
The environment variable COMPILER may be set to a list of
compilers. The default is
aoccflang520 - AOCC Flang 5.2.0
flangtrunk - flang-trunk
gfortran161 - x86-64 gfortran 16.1
ifxlatest - x86-64 ifx (latest)
lfortran0590 - LFortran 0.59.0
nvfortran_x86_26_3 - x86 nvfortran 26.3
OPTIONS:
optional arguments to pass to cexpl:
-e # execute
--cflags FLAGS # compiler flags
-a ARGV [ARGV ...], --args ARGV [ARGV ...] # the command-line arguments
--stdin STDIN [STDIN ...] # file to read as STDIN
EXAMPLE:
fall hello.f90 |tee log.txt
# execute as well as compile
fall hello.f90 -e |tee log.txt
# execute reading file "in" from stdin
fall hello.f90 --stdin="`cat in`" -e |tee log.txt
SEE ALSO:
cexpl --list-langs
cexpl --list-compilers fortran
# display predefined macros
cexpl --compiler aoccflang520 --cflags='-E -dM -Mpreprocess my_file.f90'
EOF
}
################################################################################
if [ "$#" -eq 0 ]
then
HELP
exit
fi
################################################################################
# main
FIRSTWORD=${1:-''}
case "$FIRSTWORD" in
--help|-help|-h)
HELP=TRUE
;;
*)
echo '### Fortran source'
echo '[details="click to see more..."]'
echo '```fortran'
for ARG in "$@"
do
case "$ARG" in
*90|*.f|*.F|*.ftn|*.FTN)
[ -e "$ARG" ] && cat $ARG
;;
esac
done
echo '```'
echo '[/details]'
;;
esac
#------------------------------------------------------------------------------#
(exec 2>&1
ALL='aoccflang520 flangtrunk ifxlatest lfortran0590 nvfortran_x86_26_3 gfortran161'
for COMPILER in ${COMPILER:-$ALL}
do
PREFIX=$(printf '%-20s :' $COMPILER)
if [ "$HELP" = TRUE ]
then
(set -v -x
TMP=/tmp/scr_$(uuidgen)
touch $TMP
cexpl -e -c $COMPILER --skip-asm --cflags='--help' $TMP 2>&1
rm -f $TMP
) | sed -e "s/^/$PREFIX/"
else
echo "### compiler $COMPILER"
echo '[details="click to see output..."]'
echo '```text'
case "$COMPILER" in
lfortran*) OPTIONS='--no-style-suggestions --cpp -DCOMPILER_='"$COMPILER" ;;
ifx*) OPTIONS='-fpp -warn all -check all,nouninit -error-limit 1 -O0 -g -assume byterecl -traceback -DCOMPILER_='"$COMPILER" ;;
flangtrunc*) OPTIONS='-cpp -DCOMPILER_='"$COMPILER" ;;
aoccflang520) OPTIONS='-cpp -DCOMPILER_='"$COMPILER" ;;
nvfortran*) OPTIONS='-Mbackslash -Mpreprocess -DCOMPILER_='"$COMPILER" ;;
gfortran*) OPTIONS='-cpp -Wall -Wextra -fPIC -fmax-errors=1 -g -fcheck=bounds -fcheck=array-temps -fbacktrace -fcoarray=single -DCOMPILER_='"$COMPILER" ;;
fppc64g9) OPTIONS='-cpp -DCOMPILER_='"$COMPILER" ;;
fppc64leg9) OPTIONS='-cpp -DCOMPILER_='"$COMPILER" ;;
*) OPTIONS='' ;;
esac
(set -v -x
cexpl -c $COMPILER --skip-asm --cflags="$OPTIONS" "$@" 2>&1
) | cat -nev | sed -e "s/^/$PREFIX/"
echo '```'
echo '[/details]'
fi
echo
done)
################################################################################
exit
################################################################################
Output Example
This example program echoes out the options it was compiled with and output
from inquiries of the timing routines available as an example:
Fortran source
click to see more...
program test_id
use, intrinsic :: iso_fortran_env, only : int32, int64
implicit none
call platform()
write(*,*)
call clockrate()
write(*,*)
call machineid()
contains
subroutine clockrate()
integer(kind=int64) :: count64, count_rate64, count_max64
integer(kind=int64) :: count64b
character(len=*), parameter :: g = '(1x,*(g0,1x))'
integer(kind=int64) :: i
integer(kind=int64) :: j
print g, huge(0_int64)
call system_clock(count64,count_rate64,count_max64)
print g, 'SYSTEM_CLOCK(3) (using integer(kind=int64), result may vary with argument type):'
print g, 'COUNT_MAX(64bit)= ', three(count_max64)
print g, 'COUNT_RATE(64bit)= ', three(count_rate64)
print g, 'CURRENT COUNT(64bit)=', three(count64)
do j=1,10
call system_clock(count64,count_rate64,count_max64)
do i=1,huge(0_int64)-1
call system_clock(count64b,count_rate64,count_max64)
if(count64b.ne.count64)then
write(*,'(1x,g0)',advance='no')count64b-count64
exit
endif
enddo
enddo
write(*,*)
end subroutine clockrate
subroutine platform()
use, intrinsic :: iso_fortran_env, only : compiler_version
use, intrinsic :: iso_fortran_env, only : compiler_options
implicit none
character(len=:),allocatable :: version, options
character(len=*),parameter :: nl=new_line('a')
integer :: where, start, break, i, last, col
version=compiler_version()//' '
options=' '//compiler_options()
start=1
do
where=index(options(start:),' -')
if(where.eq.0)exit
break=where+start-1
options(break:break)=nl
start=where
enddo
if(start.eq.1)then
do
where=index(options(start:),' /')
if(where.eq.0)exit
break=where+start-1
options(break:break)=nl
start=where
enddo
endif
last=len_trim(version)+1
col=0
do i=1,len_trim(version)
col=col+1
if(version(i:i).eq.' ')last=i
if(col.gt.76)then
version(last:last)=nl
col=0
endif
enddo
print '(a,/,3x,*(a))', 'This file was compiled by :', inset(version)
if(options.ne.'')then
print '(*(a))', 'using the options :', inset(options)
endif
end subroutine platform
function inset(string) result(longer)
character(len=*),intent(in) :: string
character(len=:),allocatable :: longer
character(len=*),parameter :: nl=new_line('a')
integer :: i
longer=''
do i=1,len(string)
longer=longer//string(i:i)
if(string(i:i).eq.nl)then
longer=longer//' '
endif
enddo
end function inset
function three(in) result(out)
integer(kind=int64),intent(in) :: in
character(len=:),allocatable :: temp
character(len=:),allocatable :: out
integer :: i
character(len=80) :: line
write(line,*)abs(in)
temp=' '//trim(adjustl(line))
out=''
do i=len(temp),3,-3
out=','//temp(i-2:i)//out
enddo
out=trim(adjustl(out(2:)))
out=merge(' ','-',in>0)//out
end function three
subroutine machineid()
! OS code for machine, not real hardware ID.
! should look something like 566f9e977c3c4c46d993b04f5f57f6a8
integer :: lun
integer :: iostat
character(len=256) :: line
open(newunit=lun,file='/var/lib/dbus/machine-id',iostat=iostat)
if(iostat.eq.0)then
read(lun,'(a)',iostat=iostat)line
if(iostat.eq.0)then
write(*,'(*(g0))')'pseudo machine-id : ',trim(line)
endif
endif
end subroutine machineid
end program test_id
compiler aoccflang520
click to see output...
++ cexpl -c aoccflang520 --skip-asm '--cflags=-cpp -DCOMPILER_=aoccflang520' -e fid.f90
aoccflang520 : 1 STDOUT:$
aoccflang520 : 2 This file was compiled by :$
aoccflang520 : 3 flang AOCC AOCC_5.2.0-Build#2035 2026_04_10 $
aoccflang520 : 4 using the options :$
aoccflang520 : 5 -o$
aoccflang520 : 6 -g$
aoccflang520 : 7 -fno-crash-diagnostics$
aoccflang520 : 8 -cpp$
aoccflang520 : 9 -DCOMPILER_=aoccflang520$
aoccflang520 : 10 -L./lib$
aoccflang520 : 11 -Wl,-rpath,./lib$
aoccflang520 : 12 $
aoccflang520 : 13 9223372036854775807$
aoccflang520 : 14 SYSTEM_CLOCK(3) (using integer(kind=int64), result may vary with argument type):$
aoccflang520 : 15 COUNT_MAX(64bit)= 9,223,372,036,854,775,807$
aoccflang520 : 16 COUNT_RATE(64bit)= 10,000,000$
aoccflang520 : 17 CURRENT COUNT(64bit)= -0$
aoccflang520 : 18 9 10 9 10 9 12 10 9 10 9$
aoccflang520 : 19 $
compiler flangtrunk
click to see output...
++ cexpl -c flangtrunk --skip-asm --cflags= -e fid.f90
flangtrunk : 1 STDOUT:$
flangtrunk : 2 This file was compiled by :$
flangtrunk : 3 flang version 23.0.0 (https://github.com/llvm/llvm-project.git$
flangtrunk : 4 8d61da2569a975346150371cb0d317fb9339be0c) $
flangtrunk : 5 using the options :$
flangtrunk : 6 -o /app/output.s$
flangtrunk : 7 -g$
flangtrunk : 8 -L./lib$
flangtrunk : 9 -Wl,-rpath,./lib$
flangtrunk : 10 $
flangtrunk : 11 9223372036854775807$
flangtrunk : 12 SYSTEM_CLOCK(3) (using integer(kind=int64), result may vary with argument type):$
flangtrunk : 13 COUNT_MAX(64bit)= 9,223,372,036,854,775,807$
flangtrunk : 14 COUNT_RATE(64bit)= 1,000,000,000$
flangtrunk : 15 CURRENT COUNT(64bit)= 260,190,959,342$
flangtrunk : 16 60 40 40 40 40 50 40 50 40 40$
flangtrunk : 17 $
compiler ifxlatest
click to see output...
++ cexpl -c ifxlatest --skip-asm '--cflags=-fpp -warn all -check all,nouninit -error-limit 1 -O0 -g -assume byterecl -traceback -DCOMPILER_=ifxlatest' -e fid.f90
ifxlatest : 1 STDOUT:$
ifxlatest : 2 This file was compiled by :$
ifxlatest : 3 Intel(R) Fortran Compiler for applications running on Intel(R) 64, Version$
ifxlatest : 4 2025.3.2 Build 20260112 $
ifxlatest : 5 using the options :$
ifxlatest : 6 -g$
ifxlatest : 7 -o /app/output.s$
ifxlatest : 8 -gxx-name=/opt/compiler-explorer/gcc-13.2.0/bin/g++$
ifxlatest : 9 -fpp$
ifxlatest : 10 -warn all$
ifxlatest : 11 -check all,nouninit$
ifxlatest : 12 -error-limit 1$
ifxlatest : 13 -O0$
ifxlatest : 14 -g$
ifxlatest : 15 -assume byterecl$
ifxlatest : 16 -traceback$
ifxlatest : 17 -DCOMPILER_=ifxlatest$
ifxlatest : 18 -L./lib$
ifxlatest : 19 -Wl,-rpath,./lib$
ifxlatest : 20 -Wl,-rpath,/opt/compiler-explorer/intel-fortran-2025.3.2.25/compiler/latest/lib $
ifxlatest : 21 $
ifxlatest : 22 9223372036854775807$
ifxlatest : 23 SYSTEM_CLOCK(3) (using integer(kind=int64), result may vary with argument type):$
ifxlatest : 24 COUNT_MAX(64bit)= 9,223,372,036,854,775,807$
ifxlatest : 25 COUNT_RATE(64bit)= 1,000,000$
ifxlatest : 26 CURRENT COUNT(64bit)= 1,783,217,917,642,439$
ifxlatest : 27 1 1 1 1 1 1 1 1 1 1$
ifxlatest : 28 $
compiler lfortran0590
click to see output...
++ cexpl -c lfortran0590 --skip-asm '--cflags=--no-style-suggestions --cpp -DCOMPILER_=lfortran0590' -e fid.f90
lfortran0590 : 1 STDOUT:$
lfortran0590 : 2 This file was compiled by :$
lfortran0590 : 3 LFortran version 0.59.0 $
lfortran0590 : 4 using the options : /opt/compiler-explorer/lfortran/v0.59.0/bin/lfortran$
lfortran0590 : 5 -o /app/output.s$
lfortran0590 : 6 --generate-object-code$
lfortran0590 : 7 --no-style-suggestions$
lfortran0590 : 8 --cpp$
lfortran0590 : 9 -DCOMPILER_=lfortran0590$
lfortran0590 : 10 -L./lib$
lfortran0590 : 11 -Wl,-rpath,./lib $
lfortran0590 : 12 $
lfortran0590 : 13 9223372036854775807 $
lfortran0590 : 14 SYSTEM_CLOCK(3) (using integer(kind=int64), result may vary with argument type): $
lfortran0590 : 15 COUNT_MAX(64bit)= 9,223,372,036,854,775,807 $
lfortran0590 : 16 COUNT_RATE(64bit)= 1,000,000,000 $
lfortran0590 : 17 CURRENT COUNT(64bit)= 37,100,504,932,788 $
lfortran0590 : 18 1932 2108 1916 1845 2429 1763 2015 1853 1957 1712$
lfortran0590 : 19 $
lfortran0590 : 20 No file found with given unit$
lfortran0590 : 21 STDERR:$
lfortran0590 : 22 warning: `--generate-object-code` is deprecated and will be removed in a future release; use `--separate-compilation` instead.$
lfortran0590 : 23 warning: `--generate-object-code` is deprecated and will be removed in a future release; use `--separate-compilation` instead.$
compiler nvfortran_x86_26_3
click to see output...
++ cexpl -c nvfortran_x86_26_3 --skip-asm '--cflags=-Mbackslash -Mpreprocess -DCOMPILER_=nvfortran_x86_26_3' -e fid.f90
nvfortran_x86_26_3 : 1 STDOUT:$
nvfortran_x86_26_3 : 2 This file was compiled by :$
nvfortran_x86_26_3 : 3 nvfortran 26.3-0 $
nvfortran_x86_26_3 : 4 using the options : /app/example.f90$
nvfortran_x86_26_3 : 5 -g$
nvfortran_x86_26_3 : 6 -o /app/output.s$
nvfortran_x86_26_3 : 7 -Mbackslash$
nvfortran_x86_26_3 : 8 -Mpreprocess$
nvfortran_x86_26_3 : 9 -DCOMPILER_=nvfortran_x86_26_3$
nvfortran_x86_26_3 : 10 -L./lib$
nvfortran_x86_26_3 : 11 -Wl,-rpath,./lib$
nvfortran_x86_26_3 : 12 $
nvfortran_x86_26_3 : 13 9223372036854775807$
nvfortran_x86_26_3 : 14 SYSTEM_CLOCK(3) (using integer(kind=int64), result may vary with argument type):$
nvfortran_x86_26_3 : 15 COUNT_MAX(64bit)= 9,223,372,036,854,775,807$
nvfortran_x86_26_3 : 16 COUNT_RATE(64bit)= 10,000,000$
nvfortran_x86_26_3 : 17 CURRENT COUNT(64bit)= -0$
nvfortran_x86_26_3 : 18 9 10 9 12 10 9 10 9 10 12$
nvfortran_x86_26_3 : 19 $
compiler gfortran161
click to see output...
++ cexpl -c gfortran161 --skip-asm '--cflags=-cpp -Wall -Wextra -fPIC -fmax-errors=1 -g -fcheck=bounds -fcheck=array-temps -fbacktrace -fcoarray=single -DCOMPILER_=gfortran161' -e fid.f90
gfortran161 : 1 STDOUT:$
gfortran161 : 2 This file was compiled by :$
gfortran161 : 3 GCC version 16.1.0 $
gfortran161 : 4 using the options :$
gfortran161 : 5 -fdiagnostics-color=always$
gfortran161 : 6 -cpp$
gfortran161 : 7 -imultiarch x86_64-linux-gnu$
gfortran161 : 8 -iprefix /cefs/38/383ad2f84cbd57a52fd68bbe_consolidated/compilers_c++_x86_gcc_16.1.0/bin/../lib/gcc/x86_64-linux-gnu/16.1.0/$
gfortran161 : 9 -D COMPILER_=gfortran161$
gfortran161 : 10 -mtune=generic$
gfortran161 : 11 -march=x86-64$
gfortran161 : 12 -g$
gfortran161 : 13 -g$
gfortran161 : 14 -Wall$
gfortran161 : 15 -Wextra$
gfortran161 : 16 -fno-verbose-asm$
gfortran161 : 17 -fPIC$
gfortran161 : 18 -fmax-errors=1$
gfortran161 : 19 -fbounds-check$
gfortran161 : 20 -fcheck=array-temps$
gfortran161 : 21 -fbacktrace$
gfortran161 : 22 -fcoarray=single$
gfortran161 : 23 -fpre-include=/usr/include/finclude/x86_64-linux-gnu/math-vector-fortran.h$
gfortran161 : 24 $
gfortran161 : 25 9223372036854775807$
gfortran161 : 26 SYSTEM_CLOCK(3) (using integer(kind=int64), result may vary with argument type):$
gfortran161 : 27 COUNT_MAX(64bit)= 9,223,372,036,854,775,807$
gfortran161 : 28 COUNT_RATE(64bit)= 1,000,000,000$
gfortran161 : 29 CURRENT COUNT(64bit)= 275,401,152,216$
gfortran161 : 30 70 40 40 50 40 40 40 40 40 40$
gfortran161 : 31 $
Hopefully it is straight-forward to see how to customize the script for various needs and to select different compilers. The output does not need to be run through cat -nev to expand non-printable characters and add line numbers to output, or run through sed to prefix the output with the compiler mnemonic, for example.