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:
Compiler | Module |
---|---|
version | version |
4.3.2 | unversioned |
4.5.1 | 4 |
4.6.3 | 6 |
4.7.0pre | 8 |
4.7.1 | 9 |
4.8.1 | 10 |
6.4.0 | 14 |
7.4.0 | 14 |
8.3.0 | 15 |
9.2.0 | 15 |
10.1.0 | 15 |
11.1.0 | 15 |
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 version | Library version |
---|---|
4.8.1 | 3 |
7.4.0 | 4 |
8.3.0 | 5 |
9.2.0 | 5 |
10.1.0 | 5 |
11.1.0 | 5 |
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.