Search code examples
modulefortrancray

Fortran link error: undefined reference using submodules


The error message:

mod_matrices.o:(.data+0x1790): undefined reference to `allocator_rank_2_sub_'

The module mMatrices (in mod_matrices.f08) calls the function allocator_rank_2_sub which is in a submodule smAllocations (in mod_sub_matrices_allocators.f08). The code worked before breaking the module mMatrices into a module and a submodule.

The module:

module mMatrices
    use mPrecisionDefinitions,  only : ip, rp    
    implicit none

    type :: matrices
        real ( rp ), allocatable :: A ( : , : ), AS ( : , : ), ASAinv ( : , : )
    contains
        private
        procedure, nopass, public :: allocator_rank_2   => allocator_rank_2_sub
        procedure, public         :: construct_matrices => construct_matrices_sub
    end type matrices

    private :: allocator_rank_2_sub
    private :: construct_matrices_sub

    interface
        subroutine allocator_rank_2_sub ( array, rows, cols )
            use mPrecisionDefinitions, only : ip, rp
            real ( rp ), allocatable, intent ( out ) :: array ( : , : )
            integer ( ip ),           intent ( in )  :: rows, cols
        end subroutine allocator_rank_2_sub
    end interface

    contains
        subroutine construct_matrices_sub ( me, ints, mydof, measure )
            ...
                call me % allocator_rank_2 ( me % A, m, mydof )
            ...
        end subroutine construct_matrices_sub
end module mMatrices

The submodule:

submodule ( mMatrices ) smAllocations
    contains    
        module subroutine allocator_rank_2_sub ( array, rows, cols )
            ...
        end subroutine allocator_rank_2_sub
end submodule smAllocations

The compilation via make:

ftn -g -c -r s -o mod_precision_definitions.o mod_precision_definitions.f08
...
ftn -g -c -r s -o mod_matrices.o mod_matrices.f08
...
ftn -g -c -r s -o mod_sub_matrices_allocators.o mod_sub_matrices_allocators.f08
...
ftn -g -c -r s -o lsq.o lsq.f08
ftn -g -o lsq lsq.o --- mod_matrices.o --- mod_precision_definitions.o --- mod_sub_matrices_allocators.o ---
mod_matrices.o:(.data+0x1790): undefined reference to `allocator_rank_2_sub_'
make: *** [lsq] Error 1

The last portion of `makefile'

# Main program depends on all modules
$(PRG_OBJ) : $(MOD_OBJS)

# resolve module interdependencies
...
mod_matrices.o                : mod_precision_definitions.o mod_parameters.o mod_intermediates.o
mod_sub_matrices_allocators.o : mod_matrices.o
...

The machine: Cray XC30

The compiler: Fortran 5.2.82

The question: What needs to be fixed?


The corrected code fragment incorporating @IanH's fix:

interface
    MODULE subroutine allocator_rank_2_sub ( array, rows, cols )
        use mPrecisionDefinitions, only : ip, rp
        real ( rp ), allocatable, intent ( out ) :: array ( : , : )
        integer ( ip ),           intent ( in )  :: rows, cols
    end subroutine allocator_rank_2_sub
end interface

Solution

  • The interface block for allocator_rank_2_sub in the specification part of the module is missing the MODULE prefix. This means that it specifies an external procedure, not the intended separate module procedure. The linker is then complaining that it cannot find such an external procedure.

    Add the MODULE prefix to the subroutine statement in the interface body.