Circular Dependencies Between Libraries

B

barias

Although circular dependencies are something developers should normally
avoid, unfortunately they are very easy to create accidentally between
classes in a VS project (i.e. circular compile-time dependencies). But
then I started wondering how "easy" it would be to similarly make a
NON-RUNTIME circular dependency between (implicitly linked) DLLs.
Indeed authors like John Lakos, who focus on compile/link-time
dependencies (not run-time), tell us to avoid such circular
dependencies between "packages" (i.e. libraries). But to my surprise,
evidently it isn't possible to create a circular library dependency
even if you try...

Tonight I tried to make a circular dependency by creating two Win32
console DLLs in a new VC++ solution, and attempted to make both have a
(implicit link) dependency on the other. But no matter how I tried, in
the end I always got a linker error about missing symbols - because DLL
'A' needed the type library of DLL 'B', which did not exist yet because
DLL 'B' needed the type library of DLL 'A'. A similar problem occurred
if I made both projects just static libraries (instead of DLLs).

In the end, I concluded that to make the circular dependency I would
need to involve some kind of externalized interface descriptions - such
as IDL (e.g. CORBA?). But if I used IDL in that fashion, I figure I
would end up with something that is more akin to circular runtime
dependency rather than a non-runtime dependency (and even then, it may
no longer qualify as truly circular).

Can anyone give me an example of how DLLs (or even static LIBs) can get
involved in a circular dependency? I'm scrutinizing this topic because
authors like Robert Martin or John Lakos ("Large Scale C++") talk about
how "packages" (aka libraries) should be forced away from cyclical
dependencies. Well, why make all that effort of preaching against
circular package/library dependencies, if its not even possible to make
such circular dependencies in the first place?
 
G

Gavin Deane

Although circular dependencies are something developers should normally
avoid, unfortunately they are very easy to create accidentally between
classes in a VS project (i.e. circular compile-time dependencies). But
then I started wondering how "easy" it would be to similarly make a
NON-RUNTIME circular dependency between (implicitly linked) DLLs.
Indeed authors like John Lakos, who focus on compile/link-time
dependencies (not run-time), tell us to avoid such circular
dependencies between "packages" (i.e. libraries). But to my surprise,
evidently it isn't possible to create a circular library dependency
even if you try...

Tonight I tried to make a circular dependency by creating two Win32
console DLLs in a new VC++ solution, and attempted to make both have a
(implicit link) dependency on the other. But no matter how I tried, in
the end I always got a linker error about missing symbols - because DLL
'A' needed the type library of DLL 'B', which did not exist yet because
DLL 'B' needed the type library of DLL 'A'. A similar problem occurred
if I made both projects just static libraries (instead of DLLs).

In the end, I concluded that to make the circular dependency I would
need to involve some kind of externalized interface descriptions - such
as IDL (e.g. CORBA?). But if I used IDL in that fashion, I figure I
would end up with something that is more akin to circular runtime
dependency rather than a non-runtime dependency (and even then, it may
no longer qualify as truly circular).

Can anyone give me an example of how DLLs (or even static LIBs) can get
involved in a circular dependency? I'm scrutinizing this topic because
authors like Robert Martin or John Lakos ("Large Scale C++") talk about
how "packages" (aka libraries) should be forced away from cyclical
dependencies. Well, why make all that effort of preaching against
circular package/library dependencies, if its not even possible to make
such circular dependencies in the first place?

VC++, Windows programming, IDL, DLLs are all off-topic here. However,
if you can formulate your question as a pure C++ question
http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.9
http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.8
then you should get some help. Alternatively, if your question is
specific to Windows, try asking in one of the Windows programming
groups suggested in FAQ 5.9.

Gavin Deane
 
A

Alf P. Steinbach

* (e-mail address removed):
Can anyone give me an example of how DLLs (or even static LIBs) can get
involved in a circular dependency? I'm scrutinizing this topic because
authors like Robert Martin or John Lakos ("Large Scale C++") talk about
how "packages" (aka libraries) should be forced away from cyclical
dependencies. Well, why make all that effort of preaching against
circular package/library dependencies, if its not even possible to make
such circular dependencies in the first place?

Circular dependencies are possible (in practice) for all kinds of
modules created in C++.

Start by creating two functions foo and bar that depend on each other:

<file foo.cpp>
void bar();
void foo() { bar(); }
</file foo.cpp>

<file bar.cpp>
void foo();
void bar() { foo(); }
</file bar.cpp>

Now compile these files separately: you have circularly dependent object
files.

Create a static library from each: you have circularly dependent static
libraries.

Create a DLL from each: you have circularly dependent DLLs (of course,
how to create such DLLs is off-topic in this group, which is about the
C++ language, so for specific tool usage ask in appropriate group).
 
G

Greg

Can anyone give me an example of how DLLs (or even static LIBs) can get
involved in a circular dependency? I'm scrutinizing this topic because
authors like Robert Martin or John Lakos ("Large Scale C++") talk about
how "packages" (aka libraries) should be forced away from cyclical
dependencies. Well, why make all that effort of preaching against
circular package/library dependencies, if its not even possible to make
such circular dependencies in the first place?

Since dynamic libraries are a subject of active interest and
development in the C++ standard, I would say that dynamic libraries are
not entirely off-topic. At any rate this question is easily answered:
It is certainly possible to build mutually dependent libraries. The
trick is simply to build one library against a stub library version of
the other.

Greg
 
N

Noah Roberts

Although circular dependencies are something developers should normally
avoid, unfortunately they are very easy to create accidentally between
classes in a VS project (i.e. circular compile-time dependencies). But
then I started wondering how "easy" it would be to similarly make a
NON-RUNTIME circular dependency between (implicitly linked) DLLs.
Indeed authors like John Lakos, who focus on compile/link-time
dependencies (not run-time), tell us to avoid such circular
dependencies between "packages" (i.e. libraries). But to my surprise,
evidently it isn't possible to create a circular library dependency
even if you try...

Tonight I tried to make a circular dependency by creating two Win32
console DLLs in a new VC++ solution, and attempted to make both have a
(implicit link) dependency on the other. But no matter how I tried, in
the end I always got a linker error about missing symbols - because DLL
'A' needed the type library of DLL 'B', which did not exist yet because
DLL 'B' needed the type library of DLL 'A'. A similar problem occurred
if I made both projects just static libraries (instead of DLLs).

In the end, I concluded that to make the circular dependency I would
need to involve some kind of externalized interface descriptions - such
as IDL (e.g. CORBA?). But if I used IDL in that fashion, I figure I
would end up with something that is more akin to circular runtime
dependency rather than a non-runtime dependency (and even then, it may
no longer qualify as truly circular).

Can anyone give me an example of how DLLs (or even static LIBs) can get
involved in a circular dependency? I'm scrutinizing this topic because
authors like Robert Martin or John Lakos ("Large Scale C++") talk about
how "packages" (aka libraries) should be forced away from cyclical
dependencies. Well, why make all that effort of preaching against
circular package/library dependencies, if its not even possible to make
such circular dependencies in the first place?

We had one where one lib required the header of the other and then
there was a solid dependency the other way. I fixed that one.

We also have some sort of funky cyclic dependency solved by compiling
one into the exe and loading the other. I'll fix that one eventually.
 
B

barias

Start by creating two functions foo and bar that depend on each other:
Now compile these files separately: you have circularly dependent object
files.

Create a static library from each: you have circularly dependent static
libraries.

The simplistic version you describe here, isn't possible. As soon as
you try to link either one of these seperate object files, you will get
a linker error. As another poster pointed out, between two libs 'A'
and 'B', you'd have to make some kind of "3rd party" stub library -
such as 'BStub', and have 'A' link against that.

But using that kind of approach hearkens back to using something like
IDL (which, when compiled, produces lib stubs - at least it does in the
case of CORBA). As such, it is actually "difficult" to produce a
circular dependency, people don't "accidentally" use IDL in scenarios
like this...
 
I

Ivan Vecerina

:> Start by creating two functions foo and bar that depend on each
other:
: >
: > Now compile these files separately: you have circularly dependent
object
: > files.
: >
: > Create a static library from each: you have circularly dependent
static
: > libraries.
:
: The simplistic version you describe here, isn't possible. As soon as
: you try to link either one of these seperate object files, you will
get
: a linker error. As another poster pointed out, between two libs 'A'
: and 'B', you'd have to make some kind of "3rd party" stub library -
: such as 'BStub', and have 'A' link against that.
:
: But using that kind of approach hearkens back to using something like
: IDL (which, when compiled, produces lib stubs - at least it does in
the
: case of CORBA). As such, it is actually "difficult" to produce a
: circular dependency, people don't "accidentally" use IDL in scenarios
: like this...

What you are facing is just a limitation of the tool chain you are
using (or of your understanding of it).
There is no need for such a thing as IDL or Corba. In your case it
might be enough to comment-out the contents of the function body
of either library to make a first compile. Then uncomment the code,
rebuild that library, and you're done.

Again, as others pointed out, the specifics of how to do this on
the platform you are using are out of topic here.
 
A

Alf P. Steinbach

* (e-mail address removed):
The simplistic version you describe here, isn't possible.

T:\> type con >foo.cpp
void bar();
void foo() { bar(); }
^Z

T:\> type con >bar.cpp
void foo();
void bar() { foo(); }
^Z

T:\> cl /GX /GR /c foo.cpp bar.cpp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

foo.cpp
bar.cpp
Generating Code...

T:\> lib foo.obj /out:foo.lib
Microsoft (R) Library Manager Version 7.10.3077
Copyright (C) Microsoft Corporation. All rights reserved.


T:\> lib bar.obj /out:bar.lib
Microsoft (R) Library Manager Version 7.10.3077
Copyright (C) Microsoft Corporation. All rights reserved.


T:\> dir /b *.lib
bar.lib
foo.lib

T:\> type con >main.cpp
void foo();
int main()
{
foo();
}
^Z

T:\> cl /GX /GR main.cpp foo.lib bar.lib
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 13.10.3077 for 80x86
Copyright (C) Microsoft Corporation 1984-2002. All rights reserved.

main.cpp
Microsoft (R) Incremental Linker Version 7.10.3077
Copyright (C) Microsoft Corporation. All rights reserved.

/out:main.exe
main.obj
foo.lib
bar.lib

T:\> dir /b *.exe
main.exe

T:\> _


As soon as
you try to link either one of these seperate object files, you will get
a linker error.

Will I?

As another poster pointed out, between two libs 'A'
and 'B', you'd have to make some kind of "3rd party" stub library -
such as 'BStub', and have 'A' link against that.

Do I really have to?

But using that kind of approach hearkens back to using something like
IDL (which, when compiled, produces lib stubs - at least it does in the
case of CORBA). As such, it is actually "difficult" to produce a
circular dependency, people don't "accidentally" use IDL in scenarios
like this...

Sorry, that's techo-babble.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top