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

How to have multiple definitions of a subroutine in Intel Fortran

Ahmed_A_2
Beginner
2,186 Views


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?

0 Kudos
36 Replies
Steven_L_Intel1
Employee
1,347 Views
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.
0 Kudos
Ahmed_A_2
Beginner
1,347 Views
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
0 Kudos
Liang_W_
Beginner
1,347 Views
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.
0 Kudos
Steven_L_Intel1
Employee
1,347 Views
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.
0 Kudos
Liang_W_
Beginner
1,347 Views
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.
0 Kudos
Ahmed_A_2
Beginner
1,347 Views
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
0 Kudos
Steven_L_Intel1
Employee
1,347 Views
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.
0 Kudos
Ahmed_A_2
Beginner
1,347 Views
`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
0 Kudos
Liang_W_
Beginner
1,347 Views
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.
0 Kudos
Liang_W_
Beginner
1,347 Views
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.
0 Kudos
Steven_L_Intel1
Employee
1,347 Views
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.
0 Kudos
Ahmed_A_2
Beginner
1,347 Views
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
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,347 Views
>>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
0 Kudos
Steven_L_Intel1
Employee
1,347 Views
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.
0 Kudos
Ahmed_A_2
Beginner
1,347 Views
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
0 Kudos
Steven_L_Intel1
Employee
1,347 Views
Compounding the problem here is that the caller of ADD is in the library and in the same source file as ADD.
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,347 Views
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
0 Kudos
jimdempseyatthecove
Honored Contributor III
1,347 Views
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
0 Kudos
JVanB
Valued Contributor II
1,347 Views
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.
0 Kudos
Liang_W_
Beginner
1,189 Views
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.
0 Kudos
Reply