Skip to content

Implement submodules #536

Description

@certik

Original issue: https://gitlab.com/lfortran/lfortran/-/issues/694

Current status: they parse to ASR, but as separate modules, and then they compile to LLVM as unrelated functionality, so the interface in the parent module does not have an implementation and fails at linking. A simple test was added in https://gitlab.com/lfortran/lfortran/-/merge_requests/1736:

$ lfortran submodule_03.f90
Undefined symbols for architecture arm64:
  "___module_submodule_03_mod_f", referenced from:
      _main in a.out.tmp.o
ld: symbol(s) not found for architecture arm64

Activity

  1. added
    stdlibIssues related to compiling fortran-lang/stdlib
    on Apr 7, 2024
  2. AnshMehta1 commented on Jun 25, 2025

    @AnshMehta1
    Member

    Features of Submodule :-

    1. Provides implementation to interface subroutines/functions of parent module. (Should use same program_unit_t nodes)

    2. Interfaces are not needed in submodules — only implementations are written there

    3. Can access all the entities (public/private) of Parent Module.

    4. Functions/subroutines present in Submodule can only be used if its present in Module interface. (We won't get compilation error if module interface doesn't have function/subroutine present in Submodule).

    5. Parent module can compile without submodule but using its subroutine or function in interface will cause the error.

    6. Submodule should always compile after the compilation of parent module as submodule uses modfile (.mod) of parent module for compilation.

  3. certik commented on Jul 10, 2025

    @certik
    ContributorAuthor

    For monolithic compilation when we load a module at a use statement in the main program (and recursively) we need to also load any submodules. Some paths forward:

    • For each module load we scan the include paths for submodule .mod files (we can even use .smod extension to make it easier) and use the parent module name to find those and load those
    • We store the information for each parent module which submodules it has, either by modifying the parent module .mod file or storing this separately in a file somehow.
    • The user can tell us explicitly when compiling the main program that there is a submodule, for example by adding the submodule.mod file on the command line; then we simply load it. In cmake build system we'll have to add these extra options when compiling the main program, whether listing the .mod file or by dedicated option like --add-submodule my_submodule.mod.

    I like the last option the most. We can start with that, and later on we can investigate if some combination of the previous two options could be better.

  4. AnshMehta1 commented on Jul 24, 2025

    @AnshMehta1
    Member

    Submodules in monolithic compilation aren't working.
    For eg.

    a.f90

    module mod_separate_compilation_16
        implicit none
    
        interface
            module subroutine map_open_entry(key)
                integer, intent(inout) :: key
            end subroutine map_open_entry
        end interface
        
    end module mod_separate_compilation_16

    b.f90

    submodule(mod_separate_compilation_16) submod_separate_compilation_16
        implicit none
    contains
    
        module subroutine map_open_entry(key) ------------------------------> LLVM Function is not generated for this
            integer, intent(inout) :: key
            integer, parameter :: i = 1
            key = i
        end subroutine map_open_entry
    
    end submodule submod_separate_compilation_16

    c.f90

    program separate_compilation_16
        use mod_separate_compilation_16
    
        implicit none
    
        integer :: key = 5
        call map_open_entry( key )
    
        print *, key
        if (key /= 1) error stop
    end program
    1. Here, we aren't generating LLVM Function for Submodule implementation as its ASR is not loaded in program file.
    2. When we are trying to load submodule in program file, its causing issue in CMAKE as, their order of compilation is not fixed and if program executes without executing submodule file, then we will get error.
    3. This problem is not with loading parent module file as in program, we have use statement. By this, CMAKE internally generates a dependency to compile module file first. But for submodule, we don't have anything like this to generate any dependency in CMAKE.

    Solutions :-

    1. We somehow need to force compilation of submodule file before executing program file.
    2. Or we need to turn on separate compilation flag while compiling submodule file to generate our LLVM Function.
  5. certik commented on Jul 24, 2025

    @certik
    ContributorAuthor

    @AnshMehta1 in this example, can you provide exactly how you are compiling it?

    For example if you do: lfortran -c a.f90, lfortran -c b.f90 and lfortran c.f90 then I would expect it to work, and everything should load.

    This seems like a cmake bug. It might be that cmake fundamentally only works with separate compilation, so indeed you might need to just use it there, or fix cmake.

    But if you don't use cmake, then the above should work with monolithic compilation.

  6. AnshMehta1 commented on Jul 24, 2025

    @AnshMehta1
    Member

    For example if you do: lfortran -c a.f90, lfortran -c b.f90 and lfortran c.f90 then I would expect it to work, and everything >should load.

    Yes, if we compile this way then, it would definitely work. Its only a problem for cmake. I don't think, we can fix cmake as it develops dependencies and compiles files internally. So, if we use cmake with separate compilation by default (gfortran also does the same), then we need to compile complete stdlib only using separate compilation.

  7. certik commented on Jul 24, 2025

    @certik
    ContributorAuthor

    We need to be able to compile it both ways, but if cmake and submodules are both used, then indeed separate compilation is the only approach that currently works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    stdlibIssues related to compiling fortran-lang/stdlib

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions