Fortran submodule and CMake
Fortran submodule is supported by all popular Fortran compilers. 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 and Meson fully support Fortran submodule
across compilers.
Compilers supporting Fortran submodule
include:
- Gfortran ≥ 6
- Intel oneAPI
- Cray
- IBM XL / OpenXL
- Flang
- NAG
- Nvidia HPC SDK
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.
Insert into CMakeLists.txt
include(CheckSourceCompiles)
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
# save link time, only compile is needed
check_source_compiles(Fortran
"module b
interface
module subroutine d
end subroutine d
end interface
end
submodule (b) c
contains
module procedure d
end
end
program a
end"
f08submod)
if(NOT f08submod)
return() # or make FATAL_ERROR here
endif()
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()
Complete examples of submodule
are provided.