Gfortran and .smod files

I though it would be instructive to see how Ninja approaches the module dependency situation, as one of the CMake backends.

For Brad’s example,

! mod.f90
module mod
  implicit none
  private
  public :: const, show_it
  interface
    module subroutine show_it() bind(c)
    end subroutine
  end interface
  integer, parameter :: const = 42
end module
! submod.f90
submodule(mod) submod
    implicit none
contains
  subroutine show_it() bind(C)
    print *, const
  end subroutine
end submodule
// main.c
extern void show_it();
int main() {
  show_it();
}

the Ninja build script would look as follows:

# build.ninja
ninja_required_version = 1.1

fflags = -Wall
cflags = -Wall

fc=gfortran-13
cc=gcc-13

# Rule declarations
rule fcompile
    command = $fc $fflags -o $out -c $in
rule ccompile
    command = $cc $cflags -o $out $in -lgfortran

# Build edges
build mod.o: fcompile mod.f90 || graph.dd
    dyndep = graph.dd
build submod.o: fcompile submod.f90 || graph.dd
    dyndep = graph.dd
build main: ccompile main.c mod.o submod.o

default main
# graph.dd
ninja_dyndep_version = 1
build mod.o | mod.mod mod.smod: dyndep
build submod.o | mod@submod.smod: dyndep | mod.smod 

In practice the graph.dd file would be generated by a fscan tool that would analyze the source tree for modules and dependencies between them in a preliminary pass. This is what CMake does, and I think a ninja backend for fpm would be a great project. I suppose one could also try to modify makedepf90 (but it’s missing submodule parsing, and probably lacks a few other things), FF08Depends by Ian Harvey, or LFortran. Having this built in to the compiler would be ideal though (no need to install two separate tools).

The ninja tool is then invoked as follows:

/ninja_test$ ninja -v   # -v for verbose output
[1/3] gfortran-13 -Wall -o mod.o -c mod.f90
[2/3] gfortran-13 -Wall -o submod.o -c submod.f90
[3/3] gcc-13 -Wall -o main main.c mod.o submod.o -lgfortran