Fortran 2008 Submodule and CMake

The Fortran 2008 submodule feature has been enabled in virtually all popular Fortran compilers. CMake ≥ 3.12 likewise has full support for Fortran submodule. While designed as a way to better manage public/private exposure of variables in large Fortran modules, submodules can also be used to seamlessly switch in/out advanced functionality.

For example, the GEMINI 3-D ionospheric model was created with raw binary file I/O. Since we had already written an object-oriented HDF5 interface, we integrated HDF5 file I/O into GEMINI. To help ensure a smooth transition with seamless fallback to raw binary if HDF5 wasn’t available, we used Fortran submodule with CMake. The user would call file_read and file_write subroutines with the same name, regardless of whether HDF5 was enabled. CMake would switch in submodule files depending on whether HDF5 was working or not.

Requirements

Fortran submodule requires adequate support from the Fortran compiler, and from the build system. CMake ≥ 3.12 fully supports Fortran submodule whether the submodule is in the same file as the module or distinct files. CMake 3.13 added bugfixes for Fortran submodule.

Complilers supporting Fortran 2008 submodule

  • Gfortran ≥ 6
  • Intel ≥ 2016
  • Cray
  • IBM XL
  • Flang ≥ 6
  • PGI ≥ 18.10

Notes:

  • Flang and PGI: currently have a bug with submodule if user-defined types are passed to the submodule procedures and the submodule is in a different file than the module.
  • CMake at least through 3.13 has a bug with PGI and Flang, only when submodule is in a different file than module. CMake works for other compilers for this case.

submodule supporting coming soon

  • NAG Fortran compiler submodule support anticipated in spring 2019

CMake

Rather than maintain a compiler feature table, in general we create simple test programs and verify that they compile–all automatically handled within CMake.

  1. create minimal.f90 containing:
     module b
     interface
     module subroutine d
     end subroutine d
     end interface
     end
    
     submodule (b) c
     contains
     module procedure d
     end
     end
    
     program a
     end
    
  2. insert into CMakeLists.txt
    file(READ minimal.f90 mincode)
    include(CheckFortranSourceCompiles)
    check_fortran_source_compiles(${mincode} f2008submod SRC_EXT f90)
                                    
    if(NOT f2008submod)
      return()  # or make FATAL_ERROR here
    endif()
    
  3. To selectively enable program functionality using submodule, in CMakeLists.txt (this example is for HDF5:
    add_library(io io.f90)
       
    if(USE_HDF5)
       target_sources(io PRIVATE hdf5.f90)
    else()
       target_sources(io PRIVATE raw.f90)
    endif()
    

A complete example of submodule is provided.

Tags:

Categories:

Comments

Written by Michael Hirsch, Ph.D. //