1

Our current solution is a mixed C++ Fortran application in Visual Studio 2013, with approximately 40 projects of each.

Although we can build the solution just fine, we are getting about 6000 warnings - a vast majority of which are LNK4006 warnings, where a function is being "duplicated":

warning LNK4006: _XXXXXXXXXXX@8 already defined in project1.lib(module1.obj); second definition ignored project2.lib(module1.obj)   

The common thread is that the functions that are being duplicated are defined in Fortran modules - many of which are just interfaces to C++ functions:

MODULE mINTERFACES

USE ISO_C_BINDING

INTERFACE
    INTEGER(4) FUNCTION GetLastErrorCode [C, ALIAS: '_GetLastErrorCode'] (index)

        USE ISO_C_BINDING

        INTEGER(C_SIZE_T), INTENT(IN) :: index
    END FUNCTION GetLastErrorCode
END INTERFACE

END

Since these modules are used across many Fortran projects, each project has an independent version of the interface function - hence the duplication.

This all makes perfect sense, but my question is: can I just ignore the warnings (i.e. exclude them in the project configuration)? I can't see any obvious way to restructure our code to remove the warnings, and I was under the impression that putting these interfaces in a module was good practice...

Mike Sadler
  • 1,750
  • 1
  • 20
  • 37
  • 1
    What kind of syntax is the `[C, ALIAS: '_GetLastErrorCode'] ` ? And how do you define the function in C++? Do you use `extern "C"`? – Vladimir F Героям слава Apr 28 '16 at 16:17
  • 1
    That's a Microsoft Powerstation extension for C interoperability. The combination of syntax for a compiler that has been dead for two decades, with Fortran 2003's ISO_C_BINDING is doing my head in. – IanH Apr 28 '16 at 23:32
  • 1
    Visual Studio doesn't come with a Fortran compiler. Which specific Fortran product are you using? Such an interface block should only result in a symbol reference, not a definition. From the error message you appear to have the same object code in multiple libraries - i.e. you have compiled module1.f90 twice or more - is that the case? – IanH Apr 28 '16 at 23:43
  • We're using Intel Composer 2013, SP1. The C functions are declared with 'extern "C"' and cdecl, and the interface block makes them compatible. We've also got plenty of instances of C functions declared with 'extern "C"' and stdcall, and these can be called directly from Fortran. – Mike Sadler Apr 29 '16 at 07:28
  • 2
    It is not just the interface blocks, though - there are other functions declared within the modules, along with their bodies, and these also get the 'duplication' warning. – Mike Sadler Apr 29 '16 at 07:30
  • And to the last point, the module.f90 files appear in several different projects, as they form the mechanism for the Fortran section of the program to share data. So you might have a module mENVIRONMENT containing a value for 'density', and this module is included in several different projects - all of which can get and set the 'density' value. – Mike Sadler Apr 29 '16 at 07:34
  • 1
    (I see this question on the Intel forum now too.) You should not be including the module source code into multiple projects of the same program. That will create multiple definitions, and depending on other details, may well be problematic. One project alone should compile the source code for the module, other projects should just reference the compiled mod file. Within the Intel Fortran integration in Visual Studio this is easy enough to set up by having the other projects "depend" on the project with the module source. – IanH May 05 '16 at 10:25
  • Thanks, @IanH. I guess that means that the definition of a complete function within a MODULE (which is included in several projects) is a no-no. The way they're being used at the moment is like a "proto-singleton", with the MODULE containing the [static] data, and a number of 'accessors' in the same file. These accessors need to be defined elsewhere, I guess. – Mike Sadler May 05 '16 at 13:32
  • It doesn't explain why the interface blocks are also being reported as duplicates. From Steve Lionel's reply on the Intel forum (https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/628995), it seems like we're using an obsolete interface definition, so I'm going to have to try and update a few of those and see where I get to. – Mike Sadler May 05 '16 at 13:34
  • 1
    I would update your source to the standard syntax for C interoperability. Those interface blocks aside, you should not need to change your Fortran source - what you need to change is your project structure. Having accessor functions in a module that are accessed from multiple projects is very common, but the module (any program unit, for that matter) should only be compiled once. I'll post an example in a reply to the question on the Intel forum later today. – IanH May 05 '16 at 20:53
  • Thank you, @IanH. I've been looking around for a clear definition of the new syntax - is that described here: https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/275071#comment-1548440 the standard? It looks the same but with all the qualifiers removed: the specification of cdecl, name binding, etc. – Mike Sadler May 06 '16 at 10:53

1 Answers1

1

My thanks to all those who've commented constructively in this thread - but also to @IanH and Steve Lionel who have helped in the Intel forum thread at https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/628995.

In Short

(And this is my own judgement and nobody else's) In this particular case the warnings were superfluous BUT if you disable them you would miss any new warnings which could be important. IMHO this means that you shouldn't disable the warning.

The Long Answer

The warnings were coming from two sources:

  1. A convention had grown up to use a module to contain "global" data, but to access this through "accessor functions" which were defined in the same files as the modules. This meant that when the modules were included in many different projects, the accessor functions were compiled multiple times.
  2. Several of these modules contained C interface blocks (which is good practice), but for functions which returned strings, the paradigm was used as described in Creating a FORTRAN interface to a C function that returns a char*. Although the interface blocks themselves didn't raise a duplication warning, the secondary functions which converted the C pointer to a Fortran string did.

A solution could have been to extract all of these accessor functions and secondary interface routines into separate files and only compile them once BUT this would have taken weeks.

Thanks to @IanH, he pointed out that you could obviate this by defining all of the modules in a separate project, and then (in Visual Studio) just sett all of the projects to to depend on this new "shared modules" project (using Build Dependencies-->Project Dependencies). This now compiles without the warnings; VS's "Entire Solution" search now only finds each routine once; and it probably compiles a lot faster! All in all, a win.

Community
  • 1
  • 1
Mike Sadler
  • 1,750
  • 1
  • 20
  • 37