Major changes in Gfortran by version

Gfortran and Intel Fortran are the most advanced modern Fortran compilers, particularly with regard to Fortran 2008 and Fortran 2018 standards. Very useful Fortran 2018 enhancements include:

  • error stop within pure procedures
  • random_init to initialize random number seed

minimum Gfortran version to support

We currently recommend Gfortran 6 as the minimum version to support. Gfortran 6 as a minimum version is a good tradeoff between ease of install on older operating systems and useful Fortran standard features. Gfortran < 5 is lacking too many features of “modern Fortran” that is, Fortran 2003 / 2008 / 2018 features to be useful for current development.

Intel Fortran

  • Intel Fortran 18 includes “complete” Fortran 2008 support.
  • Intel Fortran 19 improves upon Fortran 2018 support.

Gfortran major changes

Gfortran 9

Addeed numerous enhancements, including random_init()

Gfortran 8.1

Gfortran 8.2 and 8.3 did not introduce new Fortran features

  • Optimization: automatic nested loop exchange with do concurrent
  • Checks: Actual argument array with too few elements for dummy argument now errors
  • Polymorphism: initial support for parameterized derived types (simply define kind at initialization)
  • Coarray: Initial support for teams

Gfortran 8

  • std=f2008ts deprecated, do not use as it errors on compiling error stop for Gfortran < 8.
  • std=f2018 added

Gfortran 7

  • Polymorphism: derived type IO select type etc. fully supported from Fortran 2003.
  • Fortran 2018: Non-constant stop and error stop codes
  • Compatibility: -fdec- options help compiling very old non-standard code that was previously only compatible with Intel Fortran (of DEC heritage).

Gfortran 6

  • Fortran 2008: submodule support, useful for large projects to save compilation time and allow powerful use scenarios
  • Fortran 2003: improved support for deferred-length character. These are very useful for avoiding bothersome trim() everywhere. Example:

    character(256) :: argv
    character(:), allocatable :: filename
    
    call get_command_argument(1, argv)
    filename = trim(argv)
    
    end program

In this example, filename is now exactly the length required to fit the text. If the filename (in argv) was “hello.txt” then len(filename) is 9. That is, len_trim == len with auto-allocated characters (unless subsequently rewritten with a shorter string).

Practical examples are in gitrev.f90 and split_string.f90. For split_string.f90, note that this is the proper way to avoid assumed-length character functions, which are obsolete as of Fortran 95. Specifically:

Bad:

! don't do this!
character(*) function myfun(a)

Good:

pure function myfun(a)
character(:), allocatable :: myfun

Gfortran 5

Gfortran 5 is the bare minimum version to even consider using, with Gfortran ≥ 6 strongly recommended

  • OpenMP 4.0 fully supported
  • Fortran 2003: ieee_ intrinsics supported, allowing convenient standard-compliant use of nan, ieee_is_nan, etc.
  • Fortran 2008: Initial coarray support
  • Fortran 2008: error stop in pure procedures, but only without specifying std= (until Gfortran 8 std=f2018). Error code must be constant.

Gfortran 4.9

  • Fortran 2003: allow deferred-length character variables in derived types

Gfortran 4.8

By this release, substantial Fortran 2008 polymorphism support had been initially added, including

  • select type
  • class(*)
  • type(*)
  • assumed rank dimension(..)

Gfortran 4.6

Gfortran 4.6 is the first version of Gfortran basically usable with commonly used code beyond Fortran 95. It is somewhat futile to attempt to use modern Fortran code with Gfortran ≤ 4.6

  • Fortran 2003: deferred-length character variable (not in derived types until 4.9)
  • Fortran 2008: impure elemental support

Gfortran 4.5

  • Fortran 2008: iso_fortran_env real64 etc. added

Gfortran 4.4

Gfortran 4.4 added initial support for polymorphism, but is still very rudimentary and difficult to use command Fortran 2003 techniques with Gfortran 4.4.

  • OpenMP 3

Operating system vs. Gfortran version:

Here are a few common operating systems vs. easily available Gfortran version. CentOS should use devtoolset.

Cygwin

Homebrew

Ubuntu / Debian

  • Ubuntu gfortran repo defaults

  • Ubuntu 19.04 default: gfortran-8, with gfortran-9 also available.

  • Ubuntu 18.04 (EOL April 2023): install gfortran-9 via PPA or Homebrew

  • Ubuntu 18.04 default: gfortran-7

  • Windows Subsystem for Linux default is Ubuntu 18.04.

  • Ubuntu 16.04 (EOL April 2021): install gfortran-9 via PPA or Homebrew

  • Ubuntu 16.04 default: gfortran-5

  • Debian Stretch 9, including Raspberry Pi: gfortran-6

CentOS / RHEL

  • release 8 (EOL 2029): gfortran-8

  • release 7 (EOL 2024) devtoolset-8: gfortran-8

  • release 7 EPEL: gfortran-4.9

  • release 7 default: gfortran-4.8

  • release 6 (EOL Nov 2020) devtoolset-8: gfortran-8

  • release 6 default: gfortran-4.4

CMake

CMake allows switching parameters based on compiler version. This is very useful for modern Fortran programs. We recommend CMake ≥ 3.7 to give more powerful compiler version detection and action syntax (in general, not just for Fortran).

Fortran 2018

Example CMakeLists.txt for Fortran compiler version dependent options.

cmake_minimum_required(VERSION 3.7)
project(MyProject Fortran)


if(CMAKE_Fortran_COMPILER_ID STREQUAL GNU)

  if (UNIX AND NOT APPLE) # just an example for Linux-only option, nothing to do with Fortran standards
    list(APPEND FFLAGS -fstack-protector-all)
  endif()

  if(CMAKE_Fortran_COMPILER_VERSION VERSION_GREATER_EQUAL 8)
    list(APPEND FFLAGS -std=f2018)
  endif()

endif()

add_executable(myprog main.f90)
target_compile_options(myprog PRIVATE ${FFLAGS})

Non-Fortran 2018 workaround

Here we assume that assert.f90 contains error stop in a procedure that’s called from a pure procedure.

cmake_minimum_required(VERSION 3.7)
project(MyProject Fortran)

include(CheckFortranSourceCompiles)
check_fortran_source_compiles("character :: a; error stop a; end"
  f18errorstop SRC_EXT f90)

add_executable(myprog PRIVATE main.f90)

if(f18errorstop)
  target_sources(myprog PRIVATE assert.f90)
else()
  target_sources(myprog PRIVATE assert_old.f90)
endif()

Notes