Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
New Contributor I

Multiple SUBMODULES generate a linking error with CVF (/iface:cvf)

I am now attempting to incorporate the useful feature of submodules in my projects. The feature works as expected when the compiler options are set to default values. However, when using /iface:cvf (a necessity in my application) and when multiple submodules in separate files refer to the same parent module, a number of link errors appear as shown below. Is CVF not allowed as a compilation option in this case?

Example

Parent module is M and stored in File 1. It invokes module subroutines A1 and A2 defined in submodule A stored in File 2. It also invokes module subroutines B1 and B2 defined in submodule B stored in File 3.

Error fatal error LNK1169: one or more multiply defined symbols found Debug\Test_submodules.exe
Error error LNK2005: _M already defined in submodule_B.obj submodule_A.obj
0 Kudos
17 Replies
Highlighted
Valued Contributor II

It will be easier for people

It will be easier for people to help you if you can post a small self-contained source file (or set of files), so that we can compile and link them to reproduce the issue. Of course, it may be that your description is sufficient, but it will take additional time to construct the source and it may be that there is some subtlety that gets lost that way.

0 Kudos
Highlighted
Black Belt

Sub-modules did not exist in

Sub-modules did not exist in Fortran 95 (which, with some extensions, is what CVF supported); so, it is debatable as to what /iface:cvf should do for procedures in sub-modules.

It may be that the routines that you "must" call using the CVF convention are all external procedures, in which case you can specify the CVF calling convention explicitly for only those procedures, using DEC$ directives as needed.

The problem statement should explain what kind of CVF compatibility is required -- are the routines in the modules to be called from code (in, say, VB/VBA) using CVF linkage, or the other way? What about module data -- is it to be accessible and shared? All these questions need to be settled since the problems are not over when an EXE/DLL is successfully built -- the EXE/DLL has to work correctly!

0 Kudos
Highlighted
Black Belt

Normal procedures, when

Normal procedures, when compiled with /iface:cvf, generate two entry points. One with the @n suffix for STDCALL and one without. The second is needed when you pass a procedure as an actual argument (and there is no explicit interface.) It would not astonish me if the Intel support for submodules failed to take this into account.

Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
New Contributor I

Thanks for all the

Thanks for all the informative responses. I must admit that although I am an experienced Fortran programmer for over 20 years, when I moved to Intel Fortran in 2005 or so, I did not understand the CVF option then and continue not to do so. Many of the legacy programs developed as far back as 1994 that I use to date do not compile without this option. I will describe these problems in a separate thread since I do want to resolve these issues. As a result, I am not able to explain explictly why CVF option is needed. I am posting the submodule example next.

0 Kudos
Highlighted
New Contributor I

The following is a step-by

The following is a step-by-step account of the issues I am facing along with a description of the example problem:

1. Module M is a parent module. It references module subroutines A1 and A2 defined in a separate file as submodule (M) A. It also references module subroutines B1 and B2 defined in a separate file as submodule (M) B. This is a simple example that was set up to understand the submodule functionality. Finally, module M is called in a main program. These files are attached to this post.

2. Case 1: When the above project is set up in MSVS2017 with IVF 18.0.1.156 [IA-32], it works correctly with no issues with the four separate files (main.f90, module_M.f90, submodule_A.f90, submodule_B.f90) when the default settings are used i.e. Fortran -> External Procedures -> Calling Convention -> Default.

3. Case 2: When the calling convention is changed to CVF (/iface:cvf), the following errors appear:

Error fatal error LNK1169: one or more multiply defined symbols found Debug\TestSM_IVFForum.exe
Error error LNK2005: _M already defined in submodule_A.obj submodule_B.obj
 
4. Case 3: If I remove submodule_B.f90 from the project and remove the calls to module procedures B1 and B2, the project runs with no errors even with the CVF option enabled. Hence, I am led to believe the problem appears only when THERE ARE MULTIPLE SUBMODULES CONTAINED IN SEPARATE FILES AND CVF OPTION IS ENABLED.
 
5. Case 4: If all of these files are combined into one file with the routine appearing in the following sequence (module_M, submodule_A, submodule_B, main) and the CVF option is enabled, once again the project runs correctly.
 
Hence, these errors seem to be related to the use of multiple files containing submodules and the CVF option enabled.
0 Kudos
Highlighted

Does Case 2 fail in Debug

Does Case 2 fail in Debug build? IOW with IPO off

Jim Dempsey

0 Kudos
Highlighted
Valued Contributor III

Quote:avinashs wrote:

avinashs wrote:

The following is a step-by-step account of the issues I am facing along with a description of the example problem: ..

Hence, these errors seem to be related to the use of multiple files containing submodules and the CVF option enabled.

@avinashs,

You need to provide a reproducible case, what you have shown is insufficient - see below of a situation with your exact code but which works with Intel Fortran 18.0.1 as well as /IFACE:CVF option:

C:\Temp>type module_M.f90

module M

  interface

     module subroutine A1()
     end subroutine A1

     module subroutine A2()
     end subroutine A2

     module subroutine B1()
     end subroutine B1

     module subroutine B2()
     end subroutine B2

  end interface

contains

  subroutine test()
    call A1()
    call A2()
    call B1()
    call B2()
    read *
  end subroutine

  subroutine P()
    print *, 'visit from parent'
  end subroutine P

end module M

C:\Temp>ifort /c /iface:cvf module_M.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R
) 64, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


C:\Temp>ifort /c /iface:cvf submodule_A.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R
) 64, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


C:\Temp>ifort /c /iface:cvf submodule_B.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R
) 64, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


C:\Temp>ifort /c /iface:cvf main_submodule_test.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on Intel(R
) 64, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


C:\Temp>link /out:main.exe /subsystem:console main_submodule_test.obj module_M.o
bj submodule_A.obj submodule_B.obj
Microsoft (R) Incremental Linker Version 14.14.26433.0
Copyright (C) Microsoft Corporation.  All rights reserved.


C:\Temp>main.exe
 In A1
 visit from parent
 In A2
 visit from parent
 In B1
 visit from parent
 In B2
 visit from parent
x

C:\Temp>

 

0 Kudos
Highlighted
New Contributor I

@FortranFan: Thanks for your

@FortranFan: Thanks for your prompt and informative response. I tried compiling from the command line as you have done and still get the errors. The same error occurs with MSVS2017. Could this be a compiler installation or version issue?

E:\Temp>ifort /c /iface:cvf module_M.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


E:\Temp>ifort /c /iface:cvf submodule_A.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


E:\Temp>ifort /c /iface:cvf submodule_B.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


E:\Temp>ifort /c /iface:cvf main_submodule_test.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


E:\Temp>link /out:main.exe *.obj
Microsoft (R) Incremental Linker Version 14.15.26729.0
Copyright (C) Microsoft Corporation.  All rights reserved.

submodule_B.obj : error LNK2005: _M already defined in submodule_A.obj
LINK : fatal error LNK1561: entry point must be defined

E:\Temp>

 

0 Kudos
Highlighted
Valued Contributor III

Quote:avinashs wrote:

avinashs wrote:

.. I tried compiling from the command line as you have done and still get the errors ..

@avinashs,

Retry with the following:

  1. Delete ALL object (OBJ) files in your E:\temp folder,
  2. Ensure all your source (f90) files, especially submodule_B.f90 file, in your E:\temp folder are the same as what you have attached in Quote #6 above,
  3. Explicitly specify the files during the linker step instead of the wildcard spec: i.e., use the command <link /out:main.exe /subsystem:console main_submodule_test.obj module_M.obj submodule_A.obj submodule_B.obj>
0 Kudos
Highlighted
New Contributor I

@FortranFan Tried all of the

@FortranFan Tried all of the above but the same error persists.

E:\Temp>ifort /c /iface:cvf module_M.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


E:\Temp>ifort /c /iface:cvf submodule_A.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


E:\Temp>ifort /c /iface:cvf submodule_B.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


E:\Temp>ifort /c /iface:cvf main_submodule_test.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32, Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


E:\Temp>link /out:main.exe /subsystem:console main_submodule_test.obj module_M.obj submodule_A.obj submodule_B.obj
Microsoft (R) Incremental Linker Version 14.15.26729.0
Copyright (C) Microsoft Corporation.  All rights reserved.

submodule_B.obj : error LNK2005: _M already defined in submodule_A.obj
main.exe : fatal error LNK1169: one or more multiply defined symbols found

 

0 Kudos
Highlighted
Valued Contributor III

Quote:avinashs wrote:

avinashs wrote:

..Tried all of the above but the same error persists ..

Ok, I can reproduce the issue now, it happens with IA-32 (32-bit target).  My earlier attempt was with Intel 64 (64-bit target) which works fine.  if I recall correctly, /IFACE:CVF option also makes use of STDCALL calling convention on IA-32 and separately I remember running into issues with SUBMODULEs in Intel Fortran in connection with STDCALL convention.  So it's possible these things are related (?).

You should submit a support request with Intel OSC (https://supporttickets.intel.com/?lang=en-US) on this issue; refer to this thread in it.

0 Kudos
Highlighted
New Contributor I

@FortranFan: Thanks for your

@FortranFan: Thanks for your efforts. I tried the IA-64 target and was able to get it to work. My next goal is to be able to move away from /iface:cvf completely since it seems to  have a number of compatibility issues. ex. Intel MKL does not work with 64-bit targets when /iface:cvf option is active. Hence, I converted many projects back to 32-bit from 64-bit but now submodules are not working.

0 Kudos
Highlighted
Black Belt

You used Intel 64, not IA-64.

You used Intel 64, not IA-64. IA-64 is for Intel Itanium processors and this hasn't been supported in the compilers for several years now.

Please do report the problem to Intel using the link FortranFan mentioned.

Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
Valued Contributor III

Quote:avinashs wrote:

avinashs wrote:

.. My next goal is to be able to move away from /iface:cvf completely since it seems to  have a number of compatibility issues. ex. Intel MKL does not work with 64-bit targets when /iface:cvf option is active. Hence, I converted many projects back to 32-bit from 64-bit but now submodules are not working.

Not sure how and why Intel MKL fails to work with 64-bit targets when /IFACE:CVF option is employed.  You should try to put together a reproducer case with Intel MKL like you have done with SUBMODULEs and submit it to Intel support at least.

And yes, try to move away from IFACE:CVF if possible.  Generally the need for this option is consistency and/or backward-compatibility of libraries with applications making use of them such as Microsoft's VBA (e.g, Excel spreadsheet environment).  Under such circumstances, you can apply some of the principles of "design by contract" and mark the interfaces in own's code with the apps such as those in VBA with the required attributes using Intel compiler directives.  With your sample code in Quote #6, should your subroutine TEST represent such an interface, mark it with !DIR$ ATTRIBUTES CVF and you might get your code to work like so:

C:\Temp>type module_M.f90

module M

  interface

     module subroutine A1()
     end subroutine A1

     module subroutine A2()
     end subroutine A2

     module subroutine B1()
     end subroutine B1

     module subroutine B2()
     end subroutine B2

  end interface

contains

  subroutine test()
  !dir$ attributes cvf :: test  !<-- Note the Intel compiler directive
    call A1()
    call A2()
    call B1()
    call B2()
    read *
  end subroutine

  subroutine P()
    print *, 'visit from parent'
  end subroutine P

end module M

C:\Temp>ifort /c /standard-semantics module_M.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32,
Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


C:\Temp>ifort /c /standard-semantics submodule_A.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32,
Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


C:\Temp>ifort /c /standard-semantics submodule_B.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32,
Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


C:\Temp>ifort /c /standard-semantics main_submodule_test.f90
Intel(R) Visual Fortran Intel(R) 64 Compiler for applications running on IA-32,
Version 18.0.1.156 Build 20171018
Copyright (C) 1985-2017 Intel Corporation.  All rights reserved.


C:\Temp>link /out:main.exe /subsystem:console module_M.obj submodule_A.obj submo
dule_B.obj main_submodule_test.obj
Microsoft (R) Incremental Linker Version 14.14.26433.0
Copyright (C) Microsoft Corporation.  All rights reserved.


C:\Temp>main
 In A1
 visit from parent
 In A2
 visit from parent
 In B1
 visit from parent
 In B2
 visit from parent
x

C:\Temp>

 

0 Kudos
Highlighted
New Contributor I

@FortranFan: As we agreed, it

@FortranFan: As we agreed, it is best for me to move away from CVF now in 2018. I started with MS Fortran Compiler in 1995, then moved to DEC, then Compaq in 2000, then HP Compaq in 2002, then completely to Intel in 2005-2008. The /iface:cvf started with Intel and prior to that I never had to touch the compiler settings - all the codes worked straight out of the box with default settings with several compilers. In fact, the same codes worked on Unix with f77 and gcc compilers. Then with Intel, there were failures if /iface:cvf was not used, which I never understood. As you correctly point out, I will present examples to show the issues in separate threads.

With regard to Intel MKL + CVF + Intel 64 (thanks for the correction @Steve Lionel), this is a known issue: see for example 

https://software.intel.com/en-us/mkl-windows-developer-guide-compiling-an-application-that-calls-the...

However, the option /iface:nomixed_str_len_arg option, which if not enabled causes MKL to fail in Intel 64, causes problems in all my other subroutines that accept character(len = *) arguments with the default setting. So it is not MKL per se but how the change of settings affects other subroutines.

I should definitely be more proactive and contribute these examples to the IVF forum, which has been so helpful since I joined in 2003.

 

0 Kudos
Highlighted
Black Belt

MKL used to supply a library

MKL used to supply a library variant compatible with CVF. That went away several years ago.

Steve (aka "Doctor Fortran") - https://stevelionel.com/drfortran
0 Kudos
Highlighted
Black Belt

The entry point that the

The entry point that the linker complains about (32-bit, with /iface:cvf) is a stub that may be needed in some cases of building applications that use submodules. The routine at that multiply-defined entry point (_M.) is, for the test codes that you provided, just one byte long, and contains a RET instruction. Furthermore, it is never called from any of the other routines. The "multiple definition" bug should be fixed but, in the interim, you may be able to get by with the linker /FORCE option (use with caution, test the EXE well before letting others use it).

I see no need for /iface:cvf in anything that you have described in this thread (other than to expose bugs in the compiler tools). 

0 Kudos