- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Hi,
I have several modules, each of which is stored in a separate file. Each module contains a number of routines which 'use' data or routines from the other modules. I'm finding that regardless of how I include these files in my main source code, it can't compile.
Consider this simple example. In 'fileA.f90' I have this,
MODULE A
REAL:: varA
CONTAINS
SUBROUTINE MULTIPLY(result)
USE B
REAL:: result
result = varA * varB
END SUBROUTINE
END MODULE
.... and in 'fileB.f90' I have this,
MODULE B
REAL:: varB
CONTAINS
SUBROUTINE ADD(result)
USE A
REAL:: result
result = varA + varB
END SUBROUTINE
END MODULE
and in my 'main.f90' file I might have
PROGRAM MAIN
INCLUDE 'fileA.f90'
INCLUDE 'fileB.f90'
REAL:: answer
CALL ADD(answer)
CALL MULTIPLY(answer)
END PROGRAM
In order for the compiler to main.exe it first needs A.mod B.mod. Now, in order to compile module A into A.mod, the compiler must have access to B.mod. However, B.mod can't be created until A.mod exists!
How do I resolve this problem ?
I have several modules, each of which is stored in a separate file. Each module contains a number of routines which 'use' data or routines from the other modules. I'm finding that regardless of how I include these files in my main source code, it can't compile.
Consider this simple example. In 'fileA.f90' I have this,
MODULE A
REAL:: varA
CONTAINS
SUBROUTINE MULTIPLY(result)
USE B
REAL:: result
result = varA * varB
END SUBROUTINE
END MODULE
.... and in 'fileB.f90' I have this,
MODULE B
REAL:: varB
CONTAINS
SUBROUTINE ADD(result)
USE A
REAL:: result
result = varA + varB
END SUBROUTINE
END MODULE
and in my 'main.f90' file I might have
PROGRAM MAIN
INCLUDE 'fileA.f90'
INCLUDE 'fileB.f90'
REAL:: answer
CALL ADD(answer)
CALL MULTIPLY(answer)
END PROGRAM
In order for the compiler to main.exe it first needs A.mod B.mod. Now, in order to compile module A into A.mod, the compiler must have access to B.mod. However, B.mod can't be created until A.mod exists!
How do I resolve this problem ?
Link Copied
7 Replies
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
This sort of circular dependency will give dependency analyzers fits. The most appropriate solution is to put variables varA and varB in a module C which is USEd from A and B.
Also, you should not be using INCLUDE here. Use the USE statement.
Also, you should not be using INCLUDE here. Use the USE statement.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Thanks Steve,
I see the sense in your solution, but surely this limits the benefits of using modules in the first place.
If I were to create a large code which could logically be split up into a number of components, it would be sensible to separate them out into modules. Obviously these components will have to speak to each other at some point and hence it would make sense to create a number of interfacing routines to allow this to happen. In my model I 'contain' these routines within each module (which may be the source of the problem). However, if this model were to contain only a small number of components, surely it could contain many of these circular dependencies.
Is there no way of predefining these troublesome function calls as one would in C/C++ headers?
I see the sense in your solution, but surely this limits the benefits of using modules in the first place.
If I were to create a large code which could logically be split up into a number of components, it would be sensible to separate them out into modules. Obviously these components will have to speak to each other at some point and hence it would make sense to create a number of interfacing routines to allow this to happen. In my model I 'contain' these routines within each module (which may be the source of the problem). However, if this model were to contain only a small number of components, surely it could contain many of these circular dependencies.
Is there no way of predefining these troublesome function calls as one would in C/C++ headers?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
No, I don't see that it limits the benefits. If you want the C way, then use INCLUDE and INTERFACE blocks, but that's a step back to the 1970s, in my view.
There are a number of ways to organize things so that you don't have circular dependencies. In your case, it might make more sense to put the routines in the same module rather than separate modules, if they have to call each other.
There are a number of ways to organize things so that you don't have circular dependencies. In your case, it might make more sense to put the routines in the same module rather than separate modules, if they have to call each other.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Don't worry, I don't intend to move back to the 70's. I totally agree with you regarding include statements and interface blocks. I will try to find a neater way of partitioning the code into modules.
My code was originally contained in asingle file. These problems only arose when I split it into a number of separate files (the source code itself was identical). What does the compiler do differently when it uses multiple source files which would lead to this problem?
Thanks !
My code was originally contained in asingle file. These problems only arose when I split it into a number of separate files (the source code itself was identical). What does the compiler do differently when it uses multiple source files which would lead to this problem?
Thanks !
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The compiler itself doesn't care about anything except that the .mod file for any module referenced is already there when it compiles the USE. But if compiling module A depends on module B having been compiled, and module B depends on module A, there's no way to satisfy the compiler on this. It also will cause any build dependency analyzer to have fits.
There are ways to "fake out" the compiler by declaring one of the variables with the EXTERN attribute and an ALIAS that has the properly decorated external name of the module variable. I really, really don't recommend you go this route.
There are ways to "fake out" the compiler by declaring one of the variables with the EXTERN attribute and an ALIAS that has the properly decorated external name of the module variable. I really, really don't recommend you go this route.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I do not agree with the next statement:
"If I were to create a large code which could logically be split up into a number of components, it would be sensible to separate them out into modules."
I have seen before the idea to put all files into modules, but I think thatit is not sensible to use this method when you want to split up a large program.
I think it is sensible to split up a large program in functional parts. These functional parts should be programmed as routines (subroutines or functions). It is an other point where you put thse routines.
In my opinion, you could can do one of the following:
- Put each routine in a separate file of which the file name is directly related to the routine name (e.g. routine xxx in file xxx.90)
- Collect some functional relatedroutines (short one's) in one file with a name related to the function
- Put some functional related routines in a module after the CONTAINS-statement.
I always use a mix of the three possibilities in one program.
I don't prefer option 3, because all routines which use the module (by calling "use module-name") will be re-compiled when you modify one of the routines in the module. Option 3 is needed when you use for example module procedures. Further I use module only for declarations of variables that are used in various routines.
Guus
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
In my experience, I see two ways to solve this problem :
1 - Separate A and B modules into data and functions modules
"file a_data.f90"
MODULE A_DATA
REAL:: varA
END MODULE
"file a.f90"
MODULE A
USE A_DATA
CONTAINS
SUBROUTINE MULTIPLY(result)
USE B_DATA
REAL:: result
result = varA * varB
END SUBROUTINE
and so on.
2 - If A and B modules are cross dependent, think about merge them
into one AB module
1 - Separate A and B modules into data and functions modules
"file a_data.f90"
MODULE A_DATA
REAL:: varA
END MODULE
"file a.f90"
MODULE A
USE A_DATA
CONTAINS
SUBROUTINE MULTIPLY(result)
USE B_DATA
REAL:: result
result = varA * varB
END SUBROUTINE
and so on.
2 - If A and B modules are cross dependent, think about merge them
into one AB module
Reply
Topic Options
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page