Repository navigation
Implement submodules #536
Description
Activity
- addedstdlibIssues related to compiling fortran-lang/stdlibIssues related to compiling fortran-lang/stdlib
on Apr 7, 2024 Features of Submodule :-
-
Provides implementation to interface subroutines/functions of parent module. (Should use same program_unit_t nodes)
-
Interfaces are not needed in submodules — only implementations are written there
-
Can access all the entities (public/private) of Parent Module.
-
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).
-
Parent module can compile without submodule but using its subroutine or function in interface will cause the error.
-
Submodule should always compile after the compilation of parent module as submodule uses modfile (.mod) of parent module for compilation.
Reacted by Pranav, Ondřej Čertík and Harshita Kalani-
For monolithic compilation when we load a module at a
usestatement 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
.modfiles (we can even use.smodextension 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
.modfile 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.modfile 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.modfile 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.
Reacted by Ansh Mehta- For each module load we scan the include paths for submodule
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_16c.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
- Here, we aren't generating LLVM Function for Submodule implementation as its ASR is not loaded in program file.
- 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.
- This problem is not with loading parent module file as in program, we have
usestatement. 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 :-
- We somehow need to force compilation of submodule file before executing program file.
- Or we need to turn on separate compilation flag while compiling submodule file to generate our LLVM Function.
@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.f90andlfortran c.f90then 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.
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.
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.
Reacted by Ansh Mehta
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: