Submodules and Private Procedures

Hmm… I don’t think you’re doing anything wrong here. It seems to me that it’s a gfortran bug in relation to enforcing encapsulation at the object level (maybe others in the forum might correct me and point you in a different direction).

These are the symbols from the a_mod.f90 file you provided:

$ gfortran -c a_mod.f90 && nm ./a_mod.o
0000000000000000 t __a_mod_MOD_do_something
                 U _gfortran_st_write
                 U _gfortran_st_write_done
                 U _gfortran_transfer_character_write

Notice the lowercase “t” before the symbol __a_mod_MOD_do_something, which means the symbol is in the text section but local to the object file.

If I make do_something (explicitly) public in the a_mod.f90, then I get:

$ gfortran -c a_mod.f90 && nm ./a_mod.o
0000000000000000 T __a_mod_MOD_do_something
                 U _gfortran_st_write
                 U _gfortran_st_write_done
                 U _gfortran_transfer_character_write

Notice the uppercase “T” before the symbol, which means the symbol is in the text section and it’s global.

So, gfortran seems to try to enforce encapsulation at the object level, and that makes the linking step fail when submodules are involved —but it’s probably fine for other scenarios.

Using ifx, the split code you provided compiles and runs without issue:

$ ifx -c ./a_mod.f90 ./b_submod.f90 ./test.f90 
$ ifx -o test ./test.o ./b_submod.o ./a_mod.o
$ ./test 
 doing something

So ifx is not trying to enforce encapsulation at the object level:

$ ifx -c a_mod.f90 && nm ./a_mod.o
0000000000000000 T a_mod._
0000000000000010 T a_mod_mp_do_something_
                 U for_write_seq_lis
0000000000000000 r strlit
1 Like