Gfortran and .smod files

I’ve recently noticed that gfortran (13.1.0) seems to be creating many .smod files when compiling a big project. I don’t recall this being the case in the past, and this project doesn’t contain any submodules. Can anyone share insights into why these files are being generated – and should they play any role in the dependencies in my makefile?

me, too with gFortran 10.2
I just started with SUBMODULEs and only have file to create a generic for m_c() and indeed my …mod/ has
m_c_mod.smod and m_c_mod@m_c_funcs/smod

However, there are 7 more .smod

What is that about?

Maybe a dependency of the project contains them, and they were fetched using CMake, fpm, or some other custom script?

Yes. Submodule depends on the parent modules.

For example if you have:

! foo.f90
module foo
   interface
      module subroutine hello()
      end subroutine
   end interface
end module
! foo_sm.f90
submodule (foo) foo_sm
contains
   module procedure hello
      print *, "hello from a submodule"
   end procedure
end submodule

your Makefile should probably contain at least:

foo.o: foo.f90
   $(FC) $(FCFLAGS) -c $< 

foo_sm.o: foo_sm.f90
   $(FC) $(FCFLAGS) -c $< 

# Submodule depends on parent module
foo_sm.o: foo.o

With gfortran at least, compiling foo.f90 will generate three files, foo.o, foo.mod, and foo.smod. Compiling the submodule, foo_sm.o and foo@foo_sm.smod are created.

It is valid (albeit usually useless) to define a submodule even if there is nothing in the module implying that one would need to exist. I.e.

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

And so the dependencies for such a project would look something like

mod.o: mod.f90
mod.mod: mod.f90
mod.smod: mod.f90
submod.o: submod.f90 mod.smod
mod@submod.smod: submod.f90 mod.smod
main.o: main.c
main: main.o mod.o submod.o

I don’t think that’s true. C1412 (of Fortran 2018) says:

The ancestor-module-name shall be the name of a nonintrinsic module that declares a separate module procedure

And with your example, I get this error from gfortran 12.2.0:

f951: Fatal Error: Module file ‘mod.smod’ has not been generated, either because the module does not contain a MODULE PROCEDURE or there is an error in the module.

This might help explain why gfortran generates .smod files even when there are no submodules. There seems to be a .smod generated for modules that can have submodules so gfortran can perform that check.

How could you check that code if it is invalid? :slight_smile:
The last declaration should read integer :: const = 42

But more seriously. If there is no module procedure in the master module, no .smod file is generated by gfortran, either 12.2.0 or 13.2.0. So this claim:

does not seem to hold.

$ gfortran-13 -c mod.f90    # corrected code :)
$ ls mod*
mod.f90  mod.mod  mod.o

My mental compiler failed me there, missed the parameter :: part. I.e.

module mod
  implicit none
  private
  public :: const
  integer, parameter :: const = 42
end module

This one applies to my example too:

C1807 A procedure defined in a submodule shall not have a binding label unless its interface is declared in the ancestor module.

But, the following example would satisfy the constraints, though it would be useless.

module mod
  interface
    module subroutine foo
    end subroutine
  end interface
contains
  module procedure foo
  end procedure
end module
submodule(mod) submod
contains
  subroutine unreachable
  end subroutine
end submodule

I didn’t mean to imply that a .smod was generated for every module, just that it can happen regardless of whether submodules are present. For example:

$ cat mod.f90
module mod
  interface
    module subroutine foo
    end subroutine
  end interface
end module
$ gfortran -c mod.f90
$ ls mod*
mod.f90   mod.mod   mod.o     mod.smod

Well, but with such a module interface containing “module subroutine” which is not defined in the module itself, requires a submodule to be present (eventually, in order to build working executable). Also, if foo were defined in the module mod, the interface would not be needed at all.

Do you know if CMake also encodes dependencies between module and submodules this way when generating Makefiles?

A few times I’ve tried to use multiple targets in Make rules:

mod.o mod.mod mod.smod: mod.f90
submod.o mod@submod.smod: submod.f90 mod.smod
main: main.c mod.o submod.o

It quickly becomes unreadable if you have directories involved, or if you want the modules to be placed elsewhere (out-of-source build). Also the labor of tracking which files contains modules, submodules, programs, or external procedures is tedious and unrewarding.

For small projects I still do it sometimes, but once I reach about ten files or recognize that more configuration is needed, or that third-party dependencies will be used, I usually switch over to CMake.

I’m not sure. I abandoned Make when it seemed like it didn’t support multiple targets in a rule (I know now that it does), and rather than learn CMake decided to write my own. I had one that used Rake and Ruby at one point, then that used Shake and Haskell, which eventually made its way into the initial implementation of fpm.

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

Don’t you think the whole system would be easier to maintain if .(s)mod filenames started always with the basename (minus ext) of the source file name where the (sub)modules are defined? Say, mod2.f90 file with amod and bmod modules and bsub submodule to bmod would generate mod2@amod.mod, mod2@bmod.mod, mod2@bmod.smod and mod2@bmod@bsub.smod.

I think that would make it harder for the compiler when it’s processing USE statements. When the compiler sees use foo it looks for for foo.mod to get information about the module. If the .mod file name was based on the source file name, any .mod file could be the one needed.

Yes, keep in mind that the module name and file name can be different, plus, one file can define several modules (I don’t say it’s a good idea, but it’s allowed).