8 Answers
8

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.

RBarryYoung and Dykam are onto something. Microsoft uses internal tool which uses ILDASM to disassemble assemblies, strip all internal/private stuff and method bodies and recompile IL again (using ILASM) into what is called 'dehydrated assembly' or metadata assembly. This is done every time public interface of assembly is changed.

During the build, metadata assemblies are used instead of real ones. That way cycle is broken.

You can do this in Visual studio too though it's quite harsh to too, the basic way is to use #if's and remove the reference using the solution explorer, reversing that in the third step. A other way i'm thinking of is a third project file including the same files but different references. This would work as you can specify the build order.
–
DykamAug 22 '09 at 18:04

I would really like to see that. From what I experimented here, the moment you try to Add Reference, the IDE stops you.
–
Alfred MyersAug 22 '09 at 18:06

I know. But a third project not having that reference AND the #if symbol, and be referenced by the second, which is referenced by the first. No cycle. But the third uses the code of the first and outputs to the first assembly location. an assembly can easily be replaced by another with the same specs. But I think strongnaming can cause a problem in this method.
–
DykamAug 22 '09 at 18:17

It's a little like Srdjan's answer, though a different method.
–
DykamAug 22 '09 at 18:18

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:

Link A without any refs to B.

Link B with refs to A.

Link A, adding in the refs to B.

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.

the theorem is right. However in the .Net world, linking is done dynamic and not a problem. It's the compilation step where this solution is needed.
–
DykamAug 22 '09 at 17:48

Sorry to fix you again :P. But the referencing(linking) at compile time happens in the .Net world, which is everything which is derived from that specific ECMA spec. Thus Mono, dotGnu and .Net. Not Windows itself.
–
DykamAug 23 '09 at 17:47

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.

Not really. There isn't many low level stuff in it , only basic. What made you think it would be low level? The runtime and corlib is low level. Relatively. Still plain C or C++, thought the JIT contains low level stuff.
–
DykamOct 27 '09 at 16:29