- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I am attempting to learn about and use modules and submodules as part of modernizing a very large FORTRAN 77 project and have run into the following linking error that I cannot figure out:
I attempted to create a small sample that would replicate the problem, but of course this sample compiled fine. This is the sample showing the module and submodules that I am trying to set up:
Main Program File:
PROGRAM MODTEST
USE DYNAMICS_DATA
IMPLICIT NONE
INTEGER(4) IDUM(1)
IDUM = 0
CALL DYN_IN(IDUM)
STOP
END
Module File:
MODULE DYNAMICS_DATA
!
IMPLICIT NONE
!
INTERFACE
MODULE SUBROUTINE ASSEM_TIME_HIST(LINIT, ILINEAR, TBEG, TEND,
$ TINC, NTER, INITIALD, ISTEP, TLAST, NTOTAL,
$ MAX_MODE, RAL1, RAL2, IGDAMP, *)
INTEGER(4), INTENT(IN) :: LINIT
INTEGER(4), INTENT(IN) :: ILINEAR
INTEGER(4), INTENT(INOUT) :: INITIALD
INTEGER(4), INTENT(INOUT) :: ISTEP
INTEGER(4), INTENT(OUT) :: NTOTAL
INTEGER(4), INTENT(IN) :: NTER
INTEGER(4), INTENT(IN) :: MAX_MODE
INTEGER(4), INTENT(IN) :: IGDAMP
REAL(8), INTENT(IN) :: TBEG, TEND, TINC
REAL(8), INTENT(INOUT) :: TLAST
REAL(8), INTENT(OUT) :: RAL1, RAL2
END SUBROUTINE ASSEM_TIME_HIST
END INTERFACE
!
CONTAINS
!
SUBROUTINE DYN_IN(IDUM)
INTEGER(4), INTENT(OUT) :: IDUM(1)
INTEGER(4) ILINEAR, LINIT, MAX_MODE, NTER
INTEGER(4) :: ISTEP = 0
INTEGER(4) :: INITIALD = 0
INTEGER(4) :: NTOTAL = 0
INTEGER(4) :: IGDAMP = 0
REAL(8) TBEG, TEND, TINC, TLAST
REAL(8) RAL1, RAL2
!
IDUM(1) = 1
CALL ASSEM_TIME_HIST(LINIT,ILINEAR,TBEG,TEND,TINC,NTER,
$ INITIALD, ISTEP, TLAST, NTOTAL,
$ MAX_MODE, RAL1, RAL2, IGDAMP, *9930)
9930 RETURN
END SUBROUTINE DYN_IN
END MODULE DYNAMICS_DATA
Submodule1 file:
SUBMODULE (DYNAMICS_DATA) TIMEHISTORY_DATA
IMPLICIT NONE
INTERFACE
MODULE SUBROUTINE WIL_THE_NON(TBEG, TEND, TINC, NTER, MDISP,
$ AK, AM, KM, KUL, AC, D, THETA,
$ ND, NS, NT, NBW,
$ TOLERANCE, MAXITER, MINITER, ASSEMITER, RELAXATION,
$ RAL1, RAL2, KSW,
$ INITIALD, ISTEP, TLAST, NTOTAL)
INTEGER(4), INTENT(IN) :: ND, NS, NT
INTEGER(4), INTENT(IN) :: NBW
INTEGER(4), INTENT(IN) :: NTER
INTEGER(4), INTENT(IN) :: MAXITER, MINITER, ASSEMITER
INTEGER(4), INTENT(IN) :: MDISP(1,12)
INTEGER(4), INTENT(OUT) :: NTOTAL
INTEGER(4), INTENT(OUT) :: KSW(1)
INTEGER(4), INTENT(INOUT) :: INITIALD
INTEGER(4), INTENT(INOUT) :: ISTEP
REAL(8), INTENT(IN) :: TBEG, TEND, TINC
REAL(8), INTENT(IN) :: TOLERANCE
REAL(8), INTENT(IN) :: AM(1)
REAL(8), INTENT(IN) :: AK(1)
REAL(8), INTENT(IN) :: RAL1, RAL2
REAL(8), INTENT(OUT) :: D(1)
REAL(8), INTENT(OUT) :: THETA
REAL(8), INTENT(OUT) :: AC(1)
REAL(8), INTENT(OUT) :: KM(1)
REAL(8), INTENT(INOUT) :: KUL(1)
REAL(8), INTENT(INOUT) :: RELAXATION
REAL(8), INTENT(INOUT) :: TLAST
END SUBROUTINE WIL_THE_NON
END INTERFACE
!
CONTAINS
!
MODULE SUBROUTINE ASSEM_TIME_HIST(LINIT, ILINEAR, TBEG, TEND,
$ TINC, NTER, INITIALD, ISTEP, TLAST, NTOTAL,
$ MAX_MODE, RAL1, RAL2, IGDAMP, *)
INTEGER(4), INTENT(IN) :: LINIT
INTEGER(4), INTENT(IN) :: ILINEAR
INTEGER(4), INTENT(INOUT) :: INITIALD
INTEGER(4), INTENT(INOUT) :: ISTEP
INTEGER(4), INTENT(OUT) :: NTOTAL
INTEGER(4), INTENT(IN) :: NTER
INTEGER(4), INTENT(IN) :: MAX_MODE
INTEGER(4), INTENT(IN) :: IGDAMP
REAL(8), INTENT(IN) :: TBEG, TEND, TINC
REAL(8), INTENT(INOUT) :: TLAST
REAL(8), INTENT(OUT) :: RAL1, RAL2
RETURN
END SUBROUTINE ASSEM_TIME_HIST
END SUBMODULE TIMEHISTORY_DATA
Submodule2 file:
SUBMODULE (DYNAMICS_DATA:TIMEHISTORY_DATA) NONLINEAR
IMPLICIT NONE
CONTAINS
!
MODULE SUBROUTINE WIL_THE_NON(TBEG, TEND, TINC, NTER, MDISP,
$ AK, AM, KM, KUL, AC, D, THETA,
$ ND, NS, NT, NBW,
$ TOLERANCE, MAXITER, MINITER, ASSEMITER, RELAXATION,
$ RAL1, RAL2, KSW,
$ INITIALD, ISTEP, TLAST, NTOTAL)
INTEGER(4), INTENT(IN) :: ND, NS, NT
INTEGER(4), INTENT(IN) :: NBW
INTEGER(4), INTENT(IN) :: NTER
INTEGER(4), INTENT(IN) :: MAXITER, MINITER, ASSEMITER
INTEGER(4), INTENT(IN) :: MDISP(1,12)
INTEGER(4), INTENT(INOUT) :: INITIALD
INTEGER(4), INTENT(INOUT) :: ISTEP
INTEGER(4), INTENT(OUT) :: NTOTAL
INTEGER(4), INTENT(OUT) :: KSW(1)
REAL(8), INTENT(IN) :: TBEG, TEND, TINC
REAL(8), INTENT(IN) :: TOLERANCE
REAL(8), INTENT(INOUT) :: RELAXATION
REAL(8), INTENT(INOUT) :: TLAST
REAL(8), INTENT(IN) :: AM(1)
REAL(8), INTENT(IN) :: AK(1)
REAL(8), INTENT(IN) :: RAL1, RAL2
REAL(8), INTENT(OUT) :: D(1)
REAL(8), INTENT(OUT) :: THETA
REAL(8), INTENT(OUT) :: AC(1)
REAL(8), INTENT(OUT) :: KM(1)
REAL(8), INTENT(INOUT) :: KUL(1)
END SUBROUTINE WIL_THE_NON
END SUBMODULE NONLINEAR
I searched the solution for DYNAMICS_DATA to make sure it was not duplicated somewhere and cleaned and rebuilt the solution multiple times with no success. Does anyone have any idea on what else I can do to find the cause of the linker error LNK2005?
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Dear Bill, I put your code into a VS solution and your code builds fine, if and only if I remove the obsolete alternate return (this * in parameter list) for PSXE2020u2 (19.1.2, Windows OS). The formal use of submodules is fine as far as I see. I don't know if the alternate return causes the issues. I found no switch for ifort to accept this feature, but that means not, that it does't exist. Maybe it just does not work with submodules. Anyways, alternate return should be avoided IMHO, if you are modernizing.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Maybe helpful, the VS solution as zip.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In reply to the OP, I find the structure rather strange particularly nesting submodule with a submodule. The main point of submodules over modules is that it separates the interfaces from the routine so that you avoid dependencies and hence build cascades. The common implementation is a module with (maybe) some global data and a set of interfaces only. The submodules then have contained the routines only. Routines that are only called from within the same submodule do not need interfaces as they are known within that submodule.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I took your ZIP file and built it with the current compiler version (19.1.2). It linked without error.
There's nothing wrong with nesting submodules, and it can be useful.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi Steve, I've removed the alternate return from the interfaces of the original thread opener's code and converted it to free format. Bill might has encountered a different link error.
Has you tried to comment these lines in? It was not linking for me with alternate return. Since it's an obsolete feature, I would not expect, that this is tested with submodules nor would I think one should use alternate return in submodules.
But maybe it's still supported by ifort with an additional switch...
e.g.
MODULE SUBROUTINE ASSEM_TIME_HIST(LINIT, ILINEAR, TBEG, TEND,
$ TINC, NTER, INITIALD, ISTEP, TLAST, NTOTAL,
$ MAX_MODE, RAL1, RAL2, IGDAMP, *)
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
"There's nothing wrong with nesting submodules, and it can be useful." Steve I would agree with that but I didn't say is was wrong. It did think it was odd (strange) within the context of the example used which seems overly complicated and more difficult to follow (IMO). The whole module /submodule structure only has one routine used externally and that one doesn't make use of submodule functionality at all.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I had missed that the zip wasn't Bill's original code. I took Bill's code as-is (after fixing the issues caused by pasting fixed-form code directly into the forum) - it compiled and linked without error using compiler 19.1.2.
I must admit that the combination of nested submodules and alternate return gives me the shivers....
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks for all of the replies. The actual source code in these subroutines is thousands of lines long (contained in single files), which is why I am trying to split them up. I copied and pasted the interfaces and module subroutine calls into the sample code but this modified code unfortunately does not produce the linker error. I left the alternate return in for now as it does not seem to be the cause of the problem, although I realize it is obsolete. I have struggled for hours trying to figure out how DYNAMICS_DATA can be defined twice. If I remove DYNAMICS_DATA from the SUBMODULE (DYNAMICS_DATA:TIMEHISTORY_DATA) NONLINEAR statement I get the expected error #8765 Error in opening the compiled ancestor module file [TIMEHISTORY_DATA]. I am hoping that perhaps someone may have run into this as well previously and may have some ideas on where to look for the cause of the error. Would the problem more likely be within MODULE DYNAMICS_DATA or within SUBMODULE TIMEHISTORY_DATA?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
One way is to have a module with all the interfaces and only interfaces, no contains section. You can then have as many submodules of that module as you want they can all see the interfaces and there are no conflicts. That structure is also quite easy to follow. If you have a submodule routine that uniquely calls some helper routines put them all in the same submodule, they will be a subroutine/functions rather than "module subroutine/function" as no external interface is needed and they will all see implict interfaces to each other within that submodule. Personally I don't like lots of separate files I tend to have a lot of routines of the same tribe in a single submodule file and only have sibling submodules if it gets to more than say 10000 lines of code.
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page