Skip to content

Instantly share code, notes, and snippets.

@scivision
Last active January 11, 2024 20:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scivision/ed173f22f2071d717265d7206884f3a8 to your computer and use it in GitHub Desktop.
Save scivision/ed173f22f2071d717265d7206884f3a8 to your computer and use it in GitHub Desktop.
Cyclical Fortran dependencies are not supported: https://gitlab.kitware.com/cmake/cmake/-/issues/25584

Cyclical Fortran module dependencies are not supported by CMake or Meson. The code should be restructured to avoid cyclical module dependencies.

This does work:

gfortran mod_b.f90 mod_a.f90 main.f90

CMake

cmake -Bbuild
cmake --build build
ninja: build stopped: dependency cycle: mod_a.mod -> mod_b.mod -> mod_a.mod.

also fails with Make

make[2]: Circular CMakeFiles/main.dir/mod_b.f90.o <- CMakeFiles/main.dir/mod_a.mod.stamp dependency dropped.
[ 25%] Building Fortran object CMakeFiles/main.dir/mod_b.f90.o
f951: Fatal Error: Module file 'mod_a.mod' has not been generated, either because the module does not contain a MODULE PROCEDURE or there is an error in the module.
compilation terminated.

Meson

meson setup build
meson compile -C build
[1/5] Module scanner.
ninja: build stopped: dependency cycle: main.p/mod_a@impl.smod -> main.p/mod_b@impl.smod -> main.p/mod_a@impl.smod.
cmake_minimum_required(VERSION 3.12...3.29)
project(mods LANGUAGES Fortran)
if(CMAKE_GENERATOR MATCHES "Ninja")
execute_process(COMMAND ${CMAKE_MAKE_PROGRAM} --version
OUTPUT_VARIABLE ninja_version OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
message(STATUS "CMake ${CMAKE_VERSION} CMAKE_GENERATOR ${CMAKE_GENERATOR} ${ninja_version}")
add_executable(main main.f90 mod_a.f90 mod_b.f90)
!! main.f90
program run
use mod_a
use mod_b
implicit none
print *, "b + a = ", add_b(value_a())
print *, "a + b = ", add_a(value_b())
end program run
project('mods', 'fortran',
meson_version : '>=0.57.0'
)
main = executable('main', sources: ['main.f90', 'mod_a.f90', 'mod_b.f90'])
!! mod_a.f90
module mod_a
implicit none
private
public :: value_a, add_b
interface
module function value_a() result(res)
integer :: res
end function
module function add_b(a) result(res)
integer, intent(in) :: a
integer :: res
end function
end interface
end module mod_a
!> mod_a_impl.f90
submodule (mod_a) impl
use mod_b
implicit none
contains
module function value_a() result(res)
integer :: res
res = 1
end function
module function add_b(a) result(res)
integer, intent(in) :: a
integer :: res
res = a + value_b()
end function
end submodule impl
!! mod_b.f90
module mod_b
implicit none
private
public :: value_b, add_a
interface
module function value_b() result(res)
integer :: res
end function
module function add_a(b) result(res)
integer, intent(in) :: b
integer :: res
end function
end interface
end module mod_b
!> mod_b_impl.f90
submodule (mod_b) impl
use mod_a
implicit none
contains
module function value_b() result(res)
integer :: res
res = 2
end function
module function add_a(b) result(res)
integer, intent(in) :: b
integer :: res
res = b + value_a()
end function
end submodule impl
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment