In the .NET BCL there are circular references between:
System.dll
andSystem.Xml.dll
System.dll
andSystem.Configuration.dll
System.Xml.dll
andSystem.Configuration.dll
Here's a screenshot from .NET Reflector that shows what I mean:
How Microsoft created these assemblies is a mystery to me. Is a special compilation process required to allow this? I imagine something interesting is going on here.
I guess it could be done by starting with an acyclic set of assemblies and using ILMerge to then coalesce the smaller assemblies into logically related groups.
Technically, it's possible that these were not compiled at all, and assembled by hand. These are low level libraries, after all.
Well, I've never done it on Windows, but I have done it on a lot of the compile-link-rtl environments that served as the practical progenitors for it. What you do is first make stub "targets" without the cross-references then link, then add the circular references, then re-link. The linkers generally do not care about circular refs or following ref chains, they only care about being able to resolve each reference on it's own.
So if you have two libraries, A and B that need to reference each other, try something like this:
Dykam makes a good point, It's compile, not link in .Net, but the principle remains the same: Make your cross-referenced sources, with their exported entry points, but with all but one of them having their own references to the others stubbed out. Build them like that. Then, unstub the external references and rebuild them. This should work even without any special tools, in fact, this approach has worked on every operating system that I have ever tried it on (about 6 of them). Though obviously something that automates it would be a big help.
It can be done the way Dykam described but Visual Studio blocks you from doing it.
You'll have to use the command-line compiler csc.exe directly.
csc /target:library ClassA.cs
csc /target:library ClassB.cs /reference:ClassA.dll
csc /target:library ClassA.cs ClassC.cs /reference:ClassB.dll
One possible approach is to use conditional compilation (#if) to first compile a System.dll that doesn't depend on those other assemblies, then compile the other assemblies, and at last recompile System.dll to include the parts depending on Xml and Configuration.
I can only tell how the Mono Project does this. The theorem is quite simple, though it gives a code mess.
They first compile System.Configuration.dll, without the part needing the reference to System.Xml.dll. After this, they compile System.Xml.dll the normal way. Now comes the magic. They recompile System.configuration.dll, with the part needing the reference to System.Xml.dll. Now there's a successful compilation with the circular reference.
In short: