Blacklisting Compilers

From Docswiki
Jump to navigation Jump to search

Some compiler versions just don't work with our code. This might be due to a bug in the compiler, or maybe the compiler version is too old and doesn't include the features we need. If you've been debugging an issue and you're sure that it's the compiler's fault and not your's, you might like to ensure that no one else uses that compiler version and sees the same issue. CMake has the ability to check the compiler version and error out during configuration if the compiler is blacklisted.

Detecting the compiler version

Unfortunately, unlike with C or C++, CMake will not magically detect the version in use: we have to work it out for it. The first step is running the version information command for the compiler, currently:

$ gfortran --version
$ ifort --version
$ pgf90 --version
$ nagfor -V

Internally, the command is run with a line like

execute_process(COMMAND "${CMAKE_Fortran_COMPILER}" "--version" OUTPUT_VARIABLE GCC_VERSION)

which might run gfortran --version and store the result in the variable GCC_VERSION. Note that the nagfor command currently sends its output to the error stream rather than the output stream, cos, why not? That produces several lines of text, including somewhere the version number. We use a regex match in CMake to get the version number out:

string(REGEX MATCH "[0-9]+(\\.[0-9]+)+" CMAKE_Fortran_COMPILER_VERSION ${GCC_VERSION})

The regex pattern is '[0-9]+(\.[0-9]+)+', which means 'one or more digits, followed by (a literal full stop followed by one or more digits) one or more times'. So 7.3.0 will match, as will 17.1, but 4. and 173 will not. This is what version numbers currently look like, but may need to be adjusted in the future. Note that \ is a special character in CMake strings and needs to be escaped to get a literal \ in the regex pattern. If a matching pattern appears multiple times, only the first is selected.

Additionally, nagfor has a build number, which is necessary to fully specify the version. This is matched with the regex pattern '[0-9][0-9][0-9]+', that is the first 3 or more digit number. The '{3,}' notation for '3 or more' doesn't seem to work. This is currently sufficient, but might have issues later. Internally, the build number is concatenated with the version, so nag 6.1 build 6116 become version 6.1.6116 for the following tests.

Blacklisting Compilers

Once the version number is found, banning certain versions is simple. A separate list is maintained for each compiler. The version number, stored in CMAKE_Fortran_COMPILER_VERSION is compared against the banned version number and a fatal error is issued if it matches, aborting the configuration. We also issue a waring reminding users they need to reconfigure if they have module loaded a new compiler.

# Ban 6.1.6109 as it has a problem with its preprocessor 
if (CMAKE_Fortran_COMPILER_VERSION VERSION_EQUAL 6.1.6109)
    message(WARNING "If you have run a 'module load', the configuration must be wiped and rerun.")
    message(FATAL_ERROR "nagfor version 6.1.6109 is disallowed due to a known preprocessor bug.")
endif()

Here we see that version 6.1.6109 is banned for nagfor and a short explanation is given. As well as VERSION_EQUAL for a precise match, VERSION_LESS and VERION_GREATER are also available. Although if we have a need to use VERSION_GREATER we probably have bigger problems.

To add a new ban, find the list for the appropriate compiler in CMakeLists.txt, then copy the above example, changing the condition and version number as necessary. Make sure to add a helpful comment and error message so users know what's gone wrong. Also update the list below.

Current Blacklist

GCC

Require not less than 4.7.4. Older version do not support some of the Fortran 2003 features used in ALIGN.

NAG

Require not 6.1.6109. This version has a preprocessor bug that leads to truncation of long lines.

Intel

No current requirements.

PGI

No current requirements.