Skip to content

Instantly share code, notes, and snippets.

@scivision
Last active September 11, 2026 21:19
Show Gist options
  • Select an option

  • Save scivision/0b6254c7fa1562e880634e46ca865da2 to your computer and use it in GitHub Desktop.

Select an option

Save scivision/0b6254c7fa1562e880634e46ca865da2 to your computer and use it in GitHub Desktop.

Fortran Module and Submodule compiler file formats

Shows the Fortran module version information from various Fortran compilers.

cmake --workflow default

Fortran module file naming is arbitrarily defined by each compiler vendor.

Windows

7-Zip is used to extract the GZip files from Gfortran. In general Microsoft Coreutils is useful and needed here.

winget install --id 7zip.7zip -e
winget install --id=Microsoft.Coreutils -e
cmake_minimum_required(VERSION 3.19)
project(mod_files LANGUAGES Fortran)
enable_testing()
include(CheckCompilerFlag)
set(tgt dummy)
set(submod define_pi)
set(moddir ${CMAKE_CURRENT_BINARY_DIR})
add_library(${tgt} OBJECT mod.f90)
# doesn't have to be OBJECT - we're just demonstrating that linking isn't needed to make module files.
set_property(TARGET ${tgt} PROPERTY Fortran_MODULE_DIRECTORY ${moddir}) # this is the default anyway, but for clarity
find_program(head NAMES head PATHS $ENV{PROGRAMFILES}/coreutils REQUIRED)
set(cmd2 "")
set(scmd2 "")
if(CMAKE_Fortran_COMPILER_ID STREQUAL "GNU")
set(modfile ${moddir}/${tgt}.mod)
set(submodfile ${moddir}/${tgt}.smod)
if(UNIX)
find_program(gzip NAMES gunzip gzip REQUIRED)
set(cmd1 ${gzip} -cd ${modfile})
set(scmd1 ${gzip} -cd ${submodfile})
elseif(WIN32)
find_program(7zip NAMES 7z PATHS $ENV{PROGRAMFILES}/7-Zip REQUIRED)
set(cmd1 ${7zip} e -so ${modfile})
set(scmd1 ${7zip} e -so ${submodfile})
endif()
set(cmd2 ${head} -n1)
set(scmd2 ${cmd2})
elseif(CMAKE_Fortran_COMPILER_ID MATCHES "LLVMFlang|NVHPC")
set(modfile ${moddir}/${tgt}.mod)
set(submodfile ${moddir}/${tgt}-${submod}.mod)
set(cmd1 ${head} -n1 ${modfile})
set(scmd1 ${head} -n1 ${submodfile})
elseif(CMAKE_Fortran_COMPILER_ID STREQUAL "IntelLLVM")
set(dump_flag -switch:fe_module_dump)
check_compiler_flag(Fortran "${dump_flag}" _dump_ok)
target_compile_options(${tgt} PRIVATE $<$<BOOL:${_dump_ok}>:${dump_flag}>)
set(modfile ${moddir}/${tgt}.mod)
set(moddump ${moddir}/${tgt}.mod_dmp)
set(submodfile ${moddir}/${tgt}@${submod}.smod)
set(submoddump ${moddir}/${tgt}@${submod}.smod_dmp)
if(_dump_ok)
set(cmd1 ${head} -n10 ${moddump})
set(scmd1 ${head} -n10 ${submoddump})
else()
find_program(od NAMES od PATHS $ENV{PROGRAMFILES}/coreutils REQUIRED)
set(cmd1 ${od} -An -N4 -d ${modfile})
set(scmd1 ${od} -An -N4 -d ${submodfile})
endif()
endif()
add_test(NAME MetaModule
COMMAND ${CMAKE_COMMAND} "-Dcmd1=${cmd1}" "-Dcmd2=${cmd2}" -P ${CMAKE_CURRENT_SOURCE_DIR}/read_mod.cmake)
if(scmd1)
add_test(NAME MetaSubmodule
COMMAND ${CMAKE_COMMAND} "-Dcmd1=${scmd1}" "-Dcmd2=${scmd2}" -P ${CMAKE_CURRENT_SOURCE_DIR}/read_mod.cmake)
endif()
if(_dump_ok)
set_property(TEST MetaModule PROPERTY REQUIRED_FILES ${moddump})
if(TEST MetaSubmodule)
set_property(TEST MetaSubmodule PROPERTY REQUIRED_FILES ${submoddump})
endif()
else()
set_property(TEST MetaModule PROPERTY REQUIRED_FILES ${modfile})
if(TEST MetaSubmodule)
set_property(TEST MetaSubmodule PROPERTY REQUIRED_FILES ${submodfile})
endif()
endif()
file(GENERATE OUTPUT .gitignore CONTENT "*")
{
"version": 6,
"configurePresets": [
{
"name": "default",
"binaryDir": "build"
}
],
"buildPresets": [
{ "name": "default", "configurePreset": "default" }
],
"testPresets": [
{
"name": "default",
"configurePreset": "default",
"output": {
"outputOnFailure": true,
"verbosity": "verbose"
},
"execution": {
"noTestsAction": "error",
"timeout": 10
}
}
],
"workflowPresets": [
{
"name": "default",
"steps": [
{ "type": "configure", "name": "default" },
{ "type": "build", "name": "default" },
{ "type": "test", "name": "default" }
]
}
]
}
module dummy
implicit none
interface
module real function set_pi()
end function
end interface
contains
real function tau()
tau = 2*set_pi()
end function tau
end module dummy
submodule (dummy) define_pi
implicit none
contains
module procedure set_pi
set_pi = 4*atan(1.0)
end procedure
end submodule
set(_p
COMMAND_ECHO STDOUT
COMMAND_ERROR_IS_FATAL ANY)
if(NOT cmd2)
execute_process(COMMAND ${cmd1} ${_p})
else()
# pipe command
execute_process(
COMMAND ${cmd1}
COMMAND ${cmd2}
${_p})
endif()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment