Notes on gfortran

-C

Almost every Fortran compiler has a debugging option for run-time array-bounds checking, which does useful checks at the expense of often considerable performance loss, so it should not be used in production versions of code. Almost every Fortran compiler enables this with the option -C. With gfortran, -C affects how the preprocessor treats certain comments. The option for array bounds checking is -fcheck=bounds.

Module File Versioning

gfortran is an increasingly mature and useful member of the Gnu Compiler Collection. Like most other compilers, it is fairly conservative about changing its ABI: object files and libraries compiled with one version of gfortran generally work fine with any newer version.

However, it was far from conservative about changing the format of the module files it produces. It changed them on most major releases until version 8. An incomplete list of compiler version numbers against module file version numbers is:

CompilerModule
versionversion
4.3.2unversioned
4.5.14
4.6.36
4.7.0pre8
4.7.19
4.8.110
6.4.014
7.4.014
8.3.015
9.2.015
10.1.015
11.1.015

This becomes an issue if one attempts to have a central installation of a library and associated module files used by a selection of clients using different versions of gfortran. The C or C++ analogue of library with associated header file will work fine, as the header file may depend on the library version, but not on the compiler version. With gfortran one is liable to see errors such as:

hello.mpi.f90:3.6:

  use mpi
      1
Fatal Error: Cannot read module file 'mpi.mod' opened at (1),
because it was created by a different version of GNU Fortran

One needs to ensure that the module file is created with the same version of the compiler that is being used for the compilation which includes it. This can make installing Fortran libraries on a system with multiple versions of gfortran hard. Whilst one library file is likely to suffice, it is less likely that a single module file will suit all versions.

To determine the version number of a gfortran module file, for early versions the .mod file is simply a text file, and

$ head -1 mpi.mod
GFORTRAN module version '10' created from mpi.f90

suffices. For later versions, the .mod file is gzipped, so one needs

$ zcat mpi.mod | head -1
GFORTRAN module version '14' created from mpi.f90

Run-time Library Versioning

During its long life, gfortran's run-time library, libgfortran, has progressed through different major versions, although considerably fewer versions that the module files.

Compiler versionLibrary version
4.8.13
7.4.04
8.3.05
9.2.05
10.1.05
11.1.05

However, all is not quite as it seems. Even though gfortran versions 8 to 10 share the same major version of their library, sometimes a gfortran 10 compiled program will work with a gfortran 8 library, and sometimes it will not. It can be hard to tell which gfortran versions a particular library is guaranteed to support, but the following helps:

$ strings -a libgfortran.so.5 | grep '^GFORTRAN_[0-9]'
GFORTRAN_8
GFORTRAN_9
GFORTRAN_9.2
GFORTRAN_10
GFORTRAN_10.2

and similarly to see which version an executable is likely to require:

$ strings -a a.out | grep '^GFORTRAN_[0-9]'
GFORTRAN_10
GFORTRAN_8

This code will not run if one's libgfortran.so.5 does not support gfortran 10, and the error will be something like:

./a.out: /usr/lib/x86_64-linux-gnu/libgfortran.so.5: version `GFORTRAN_10' not found (required by ./a.out)

However, some simple codes compiled with gfortran 10 make no use of run-time library features more recent than gfortran 8, and will run with an older libgfortran.so.5. To see which function is causing the problem:

$ strings -a a.out | grep 'GFORTRAN_[0-9]'
GFORTRAN_10
GFORTRAN_8
_gfortran_transfer_real_write@@GFORTRAN_8
_gfortran_transfer_integer_write@@GFORTRAN_8
_gfortran_system_clock_8@@GFORTRAN_8
_gfortran_transfer_character_write@@GFORTRAN_8
_gfortran_os_error_at@@GFORTRAN_10
_gfortran_st_write_done@@GFORTRAN_8
_gfortran_set_options@@GFORTRAN_8
_gfortran_set_args@@GFORTRAN_8
_gfortran_st_write@@GFORTRAN_8

So here the problem is the internal function _gfortran_os_error_at.

This sort of issue is not unique to gfortran. It arises in the Gnu maths library too, as the following code shows.

#include<stdio.h>
#include<math.h>

int main(void){
  double x=1.0;
  printf("e=%lf\n",exp(x));
  return(0);
}

which produces the following

Ubuntu_20.04:$ gcc hello.libm.c -lm

Ubuntu_18.04:$ ./a.out 
./a.out: /lib/x86_64-linux-gnu/libm.so.6: version `GLIBC_2.29' not found (required by ./a.out)

In this case the reason is that the GLIBC 2.29 version of the maths library finally removes support for the deprecated SYSV matherr error handling from exp and exp2, and also from pow, log and log2. So any code calling one of these five functions will suffer from this issue.