Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
28488 Discussions

Modules and separate compilation, duplicate symbol error

woodbird
Beginner
529 Views

 

Consider the following, I have an interface file, say interface.fi as below,

module foo_type
    type bar
    end type bar

end module foo_type

module foo
    use foo_type

    interface
        subroutine sub(var)
            use foo_type
            type(bar) var
        end subroutine sub
    end interface
end module foo

And there are multiple source files use the models in this file, say pr.f90

include "interface.fi"

program prg
    use foo
    type(bar) b
    call sub(b)
end program prg

and another sub.f90

include "interface.fi"

subroutine sub(var)
    use foo
    type(bar) var
end subroutine sub

Now consider I compile them as below,

	ifort -c sub.f90
	ifort -c prg.f90
	ifort -o prg sub.o prg.o

And I get the error 

duplicate symbol _foo_type._ in:
    sub.o
    prg.o
duplicate symbol _foo._ in:
    sub.o
    prg.o

It appears that both translation unit generates symbols for the module foo_type and foo. If I only include the interface file in only one source file. And in the Makefile make sure that it is compiled first, or just compile it first to generate models and do not include it in only source files. Then everything works fine. This is ok for small project where write a Makefile manually is not too much a trouble. But in other build systems, say, CMake for a larger program, I often has to write a custom command just to make sure that certain module files are generated first.

In addition, it appears that using gfortran there is no such problem. Is there a solution that I can just include the interface file wherever its members are used and still compile successfully, without going into the trouble to make sure there is only one instance of the modules being included?

0 Kudos
5 Replies
mecej4
Honored Contributor III
529 Views

The F95 and F2003 languages do not allow an interface-to-self, but that is what you are providing when you write "use foo" in in sub.f90.

There is also a bit of self-deception resulting from naming the first file "interface.fi", when the file contains not only the interface but also a definition of the type "bar". The "include" directive in pr.f90, etc., creates multiple instances of module "foo" to appear in the object files.

0 Kudos
Steven_L_Intel1
Employee
529 Views

NB: "Interface to self" has been debated among the standards committee, but was ultimately rejected. As mecej4 says, it's not allowed by the standard. gfortran may choose to support it as an extension. The multiple definitions of the module are simply an error in your program.

0 Kudos
jimdempseyatthecove
Honored Contributor III
529 Views

Your program will compile and run of you delete the 'include "interface.fi"' and the use to self

The "use foo" is sufficient in the external source files (assuming path to foo.mod is in your project include path).

Jim Dempsey

0 Kudos
JVanB
Valued Contributor II
529 Views

use foo in subroutine sub need not be nonconforming. In fact, there is an idiom available for subroutine sub to generate code to check the interface specification given for itself while requesting the optimizer to not generate any code for it:

include "interface.fi"

subroutine sub(var)
    use foo
    use foo, only: self=>sub
    type(bar) var
    if(.FALSE.) then
       BLOCK
          procedure(self), pointer :: p
          p=>sub
       END BLOCK
    end if
end subroutine sub

Unfortunately, ifort generates a spurious error for the above, even when sub is declared recursive:

sub.f90(10): error #8191: The procedure target must be a procedure or a procedur
e pointer.   
          p=>sub
-------------^

 

0 Kudos
jimdempseyatthecove
Honored Contributor III
529 Views

RO and woodbird, et all

The use of:   include "interface.fi"

in multiple source files, where the contents of interface.fi declares the module is in error as this can lead to multiple declarations of the module, with potentially different definitions (e.g. two different versions of your interface.fi in different paths).

You can USE the .mod file multiple times, but you cannot (ought not) multiply define a module (even if identical). In this way Fortran differs from C++'s #include (with member functions, and inline code).

I generally place my interfaces, alone in a separate file that generates a .mod file. This is kept separate from the code, as you might in a module with data + code in a contains section. The reason being, on large solutions this cuts down on the build times. interfaces seldom change, while data and/or code change more frequently. No need to recompile a source file when the interface does not change, but the called routine code has changed.

Jim Dempsey

0 Kudos
Reply