How to have multiple definitions of a subroutine in Intel Fortran

How to have multiple definitions of a subroutine in Intel Fortran

How can I use a static library in a Intel Fortran Project and at the same time, include some of the library subroutines in other parts of the project with some changes? In other words, in the case that I have two definitions of the same subroutine, How can I ask the program to use the subroutine that is included in the project rather than the same subroutine in the library?

37 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Normally this would "just work". As long as the library routine you are overriding isn't included in the same object module as something else you're pulling in, the linker will ignore the library version. If that's not the case and you're getting linker errors for duplicate definitions, you can add /force:multiple to the Linker > Command Line property page. (Note, Linker, not Fortran).

Does this help? If not, please describe in more detail what you are trying to do and what goes wrong.

Retired 12/31/2016

I have done exactly the same , and got a warnings :

'ATIFLib.lib(AtifM.obj) : warning LNK4006: _CONT510 already defined in Atsurface.obj; second definition ignored'
Debug\Contactone.exe : warning LNK4088: image being generated due to /FORCE option; image may not run

I think this means that IntelFortran did recognize the existence of CONT510 subroutine sharing the same name with the one in the library and the one in the library seems to be replaced with the new one. But it is not the case, cause I wrote a 'pause' in the CONT510 subroutine I have and it was not called , and is still using the one in the library. I hope i made is clear

Hi, Mr. Lionel
I actually came across the same problem and do not know how to solve it. Looking forward to your reply.
Many thanks.

It is not "Intel Fortran" that is the issue here - it is the linker that resolves references. All of the definitions in your sources would be used before any from the library. If you can construct a case that shows this is not happening, please attach a ZIP of the project that shows this. If you are getting the multiple definition error, then there is a reference in the library that is causing the duplicate name to be pulled in.

Retired 12/31/2016

Hi, Mr. Lionel
The attached please find the .zip file. All the file was created by visual studio 2010 (Parallel Studio XE 2011 with VS2010)
In this folder you could find a project folder called NEWLIBTEST there is a small subroutine 'SUB.for' and the library 'Lib1.lib'. The 'Lib1.lib' was created by 'Source1.for'.
I took the advice that use force option under linker. The results should be 2*5*5=50, but it remains still 7.
Thanks for your help.

Attachments: 

AttachmentSize
Downloadapplication/zip libtest.zip826.48 KB

Hi Mr. Lionel
I have already tested the project that Liang attached and the problem is much clear in this example . It seems that the project recognized that there is two definitions for the ADD subroutine , it is still using the one in the library not the one I added in the project. Your reply will be appreciated
Many Thanks

In Liang's example, all of the routines in the library are from a single source file, which means they'll all be in a single object module. The main program calls MAINTEST, from the library. When the linker pulls in MAINTEST it also sees ADD in that module and resolves it there, even though there is an ADD in the project.

To fix this, put each of the routines in a separate file - or at least the ones you want to override.

Retired 12/31/2016

`Hi
I have did exactly what you recommend ,where i put the ADD subroutine in a separate file . But I still Have the same problem , the project still call the subroutine in the library not the one i added. Could you please check that.
Many Thanks
Ahmed

Hi, Mr. Lionel and Ahmed
I tried to separate the ADD routines from the library which means using two source files to build the library one is source1 and the other is source2. You could find that in the attached file,Ahmed. And now I could replace the ADD using the one in the project.
I also have a question, Mr, Lionel, that the size of the library generated by Intel Fortran is much larger than that created by PowerStation and I don't know why. Thanks for your kind help.

Attachments: 

AttachmentSize
Downloadapplication/zip separate.zip826.42 KB

But I think this property is not quite convenient for our work. Cause every time when we would like to modify a routine in the library we have to separate it from library first and then rebuild the library. Actually in PowerStation we do not have to do such kind of things. We created the library using one source file in Powerstation and the only thing we should do is to use the "force" option under "link" tab and the subroutine in the project will automatically replace the one in the library. I was wondering if IntelFortran could do the same thing. Thanks.

One possible difference is that the Intel compiler does automatic inlining of procedures in the same source file - this would probably explain the difference.

I can't comment on the size of the library - unless you're comparing a debug build, perhaps.

Retired 12/31/2016

Thanks Liang for your clarification. Exactly Mr Lionel this way of creating the library will not work with us, We would like to have your answer if we could create the library using one source file and enforce the project to use the subroutines I added as user subroutines , as exactly we can do in Power station.
your reply will be appreciated
many Thanks
Ahmed

>>only thing we should do is to use the "force" option under "link" tab and the subroutine in the project will automatically replace the one in the library
This is a Linker issue, not Intel Fortran issue. The linker on Windows is provided by Microsoft.

You might consider using (requiring) your FORTRAN program to use interfaces. Then, in your interface declaration, attribute the conflicting subroutine name to use a different link name

INTERFACE SUBROUTINE happy(i)
!DEC$ ATTRIBUTES STDCALL, DECORATE, ALIAS:'OtherName' :: happy
INTEGER i
END SUBROUTINE
END INTERFACE

Jim Dempsey

I looked at this closer and do not see any way to prevent ADD from being resolved from the same file where the call was made. This appears to be controlled by the linker - the compiler can't do anything about it. You will have to move ADD to a separate source file. Once you do this, you won't need /force anymore.

Retired 12/31/2016

Hi Mr. Dempsey
We Do Appreciate your contribution. But could you please explain more what you mean by attribute the conflicting subroutine name to use a different link name. and really it will be very kind from you to look closely at the example we have and apply your solution on it.
Many Thanks
Ahmed

From my understanding of your situation you currently have a library where one .obj (of potentially several .obj's in the library) contains multiple functions. One of these functions you wish to replace with other code using the same function name, however, your code is also dependent of other functions contained within the .obj contained in the library containing that .obj and potentially other .obj's. The Linker will load any (but not necessarily all) .obj contained within a library which has a reference made to any of its externals (and which are not already defined).

One way to correct this is to rename your functions (AhmedADD) but this may not be practical or convienent.
A different way is to seperate the sources of the seperate functions such that you compile to seperate .obj files then Lib into one .lib file. And code your replacement function using the same name (ADD). Then let the linker substitute your function for all calls using ADD. This too may be unaccepible when functions contained within the .lib (or elsewhere) need to call the library's version of ADD and not your substitution for ADD.

To resolve this I believe the best way is to declare a generic interface, not normally used to define an internal name for an external subroutine/function

Assume you have

SUBROUTINE ADD(A,B,C)
A = B + C
call TestBounds(A) ! your diagnostic subroutine
END SUBROUTINE ADD

However this name conflicts with a library subroutine name, now you want to selectively use (replace) the call to the library ADD with a call to your ADD.

! SubstituteFunctions.f90
MODULE SubstituteFunctions
INTERFACE ADD
SUBROUTINE AhmedADD(A, B, C)
REAL :: A, B, C
END SUBROUTINE AhmedADD
END INTERFACE
... ! Other subroutine/functions follow
END MODULE SubstituteFunctions

--------------------------
! YourCode.f90
SUBROUTINE YourCode(...
USE SubstituteFunctions
...
CALL ADD(SUM, X, Y)
...
END SUBROUTINE YourCode

Jim Dempsey

Compounding the problem here is that the caller of ADD is in the library and in the same source file as ADD.

Retired 12/31/2016

I forgot to mention, it is assumed you will supply "AhmedADD.f90" with the appropriate subroutine.

>>Compounding the problem here is that the caller of ADD is in the library and in the same source file as ADD.

Then this clearly calls for the replacement of the contents of ADD or seperation of ADD into seperate source.

An alternate way might be to use a procedure pointer that is initialized to the .LIB ADD routine but reset to the alternate routine.
The procedure pointer could be declared as ADD in the module but not given EXTERNAL attribute. Then only subroutine/function USEing the module would reference the module declared ADD procedure pointer as opposed to the library EXTERNAL ADD subroutine/function.

Jim Dempsey

Why won't this work?
1) Put the subroutine ADD that you really want to invoke in a module.
2) USE the module in the program unit where you really want to invoke it.
3) Give the subroutine a different linker name with !DEC$ ATTRIBUTES ALIAS
Even step 3 above seems unnecessary because a module procedure already has a different linker name.
If the module won't be available at the time the prospective caller is compiled, you could still write out an interface block with a different linker name as specified in 3 above. I don't think you are reduced to LoadLibrary/GetProcAddress/C_F_PROCPOINTER to get this to work.

Hi, Mr. Lionel
To separate the subroutines into a different source file did work for our examples, but when the library containing thousands routines that calling each other the we could not separate each calling statement and each subroutine. So, I was wondering if there is any settings that we could do in the linking part to overcome this problem. Thanks for your answer.

Hi Mr. Lionel and Mr Dempsey
many Thanks for your help .Actually, to separate between the subroutine and the its call statement in the library(put them in different sources when we create the library) will be impossible in case of big library that we have . So could you please do that by setting the linking properties of the project , which will be more convenient and easy .
Many thanks
Ahmed Khalil

Sorry, Ahmed, there's no way to do that.

Retired 12/31/2016

Hi, I would appreciate that if you could send us an example of this.
Actually, I am still not quite clear about the steps.
Thanks.
Quote:

Why won't this work?
1) Put the subroutine ADD that you really want to invoke in a module.
2) USE the module in the program unit where you really want to invoke it.
3) Give the subroutine a different linker name with !DEC$ ATTRIBUTES ALIAS
Even step 3 above seems unnecessary because a module procedure already has a different linker name.
If the module won't be available at the time the prospective caller is compiled, you could still write out an interface block with a different linker name as specified in 3 above. I don't think you are reduced to LoadLibrary/GetProcAddress/C_F_PROCPOINTER to get this to work.

Hi Mr. Dempsey
I have tired your method with the simple project we have here and it works fine but with our project that has very big library it does not work it gives me some error, are there any conditions this way will work only or it can work with any project.
Many Thanks
Ahmed

Hi Mr. Lionel
But power station was allowing that option( forcing the user subroutines) very easy without the need to separate between the subroutines and its calls(to be in two sources to while creating the library), there no option in Intel Fortran to do the same. Actually this option is very fundamental in our work and we are trying now to convert from power station to Intel Fortran. Could I know please your suggestions. your reply will be appreciated
Many thanks

I compiled the 3 included files as:
ifort add.for source1.for sub.for
Output was:
CALLED HERE ADD NEW 50.0000000000000
2 5 50.0000000000000
THIS IS THE MAIN

Attachments: 

AttachmentSize
Downloadtext/plain source1.txt629 bytes
Downloadtext/plain sub.txt284 bytes
Downloadtext/plain add.txt217 bytes

Quote:

Ahmed A. wrote:

Hi Mr. Dempsey
I have tired your method with the simple project we have here and it works fine but with our project that has very big library it does not work it gives me some error, are there any conditions this way will work only or it can work with any project.
Many Thanks
Ahmed

What is the error message? Is it compiler or linker error message? You have a working simple example, what design changes exist between the simple example and the full library? Jim Dempsey

Hi Mr. Dempsey
This is the error I just got when I applied to anther project , I made sure that every thing is The same as I did in the simple project the subroutine that I would like to replace is SPLNDT while the errors I got are
Error 2 Compilation Aborted (code 1)
Error 1 error #6401: The attributes of this name conflict with those made accessible by a USE statement. [SPLNDT]
Do I have to include all the arguements and the dimensions and the common blocks associated with each subroutine in the new substitution module
Many Thanks
Ahmed

Hi, thanks very much for your answer.
That means I have to create a library that containing the module.
How could I leave the 'USE ADDMOD' in the source1.txt and then create the library. So that I could modify other subroutines in the same way.
Quote:

I compiled the 3 included files as:
ifort add.for source1.for sub.for
Output was:
CALLED HERE ADD NEW 50.0000000000000
2 5 50.0000000000000
THIS IS THE MAIN

Hi Mr. Lionel
I would like to hear you suggestion about this problem this is essential problem we have , does any upgrading versions for inlet fortran will be helpful to simplify this, and also I'm facing a problem in the size of the debugging that intel fortran created compared to the one i had from power ststion , I'm wondering if there is any configurations that we can change to reduce the size of the library as we can. Your reply will be appreciated
Many Thanks
Ahmed

>>Error 1 error #6401: The attributes of this name conflict with those made accessible by a USE statement. [SPLNDT]
>>Do I have to include all the arguements and the dimensions and the common blocks associated with each subroutine in the new substitution module

Only the calling arguments (and calling conventions if present) must be declared.

Your error is likely one of two

a) The module with the interface for SPLNDT has an interface that is not the same as the subroutine SPLNDT and SPLNDE is USE-ing this module. (Keep USEing the module but fix your interface)

b) You have multiple USE module with declaration of interface for SPLNDT. Assuming one of these is the USE for your general subroutines, e.g. ADD SUB, MUL, DIV and assume you wish to replace ADD

USE YourReplacements ! with ADD
USE YourLibrary, ONLY : SUB, MUL, DIV

Or try

USE YourReplacements ! with ADD
USE YourLibrary, ADDdontUse = ADD

Jim Dempsey

*** ADDdontUse *EqualSign*GreaterThanSign* ADD

Ahmed, I don't know of any reasons why the library should be significantly larger. Please show me the compiler options you are using - in Visual Studio these can be found under the project property Fortran > Command Line.

Retired 12/31/2016

Hi Mr. Lionel
I would like to hear your suggestion about the linking problem ,this is essential problem we have , and actually the two suggested ways can not be applied in general case, where to separate between the subroutine and its calls is impossible for us otherwise we have to put each subroutine in a source file when we create the library, and the second method that Mr. Dempsey suggested , is also not practical for us as the user will not be able to change the module we have in the library , so we have to repeat that for each subroutine and this not convenient. does any upgrading versions for inlet fortran will be helpful to simplify this, or what do you recommend us to do in this case. As I told you we are converting from power station to Intel fortran.
Many Thanks
Ahmed

Hi
"One possible difference is that the Intel compiler does automatic inlining of procedures in the same source file - this would probably explain the difference."

As this problem come from the Intel fortran automatic inlining , there is any way to disable or enable this automatic inlining or any other options that we can control the inlining.
Many Thanks
Ahmed Khalil

Hi, I think we could solve another problem instead to implement the same function. For example, we have a 'A.lib' file and this file contains "subroutine ADD", as we could not get access to the library or it is not easy to modify this library. Shall we build another static library with this "A.lib" file and "Source2.for" in which there is a subroutine called subroutine ADD. How can we replace the one in the library using the new one through some specific settings?
Thanks,Liang

Leave a Comment

Please sign in to add a comment. Not a member? Join today