Mergin', mergin', mergin', Though the GC's purgin'

by Ivan Hamilton 12/10/2007 6:36:00 PM

Call me old-school, but one thing that I miss in all this new fangled .NET world is the neat single EXE solution. If you grew up with C object or Pascal unit files, then you might miss the ability to combine pre-compiled code into the target file under .NET.

Static linking it's called, but it's fallen terrifically out of fashion in these days of dynamic linking with DLLs and shared objects.

Mono has a linker project that aims to produce the minimal possible set of functions that a program might require to run (as opposed to the full libraries). It creates a set of reduced assemblies that can fulfill the needs of the program.

That's part of the way... I like the reduction in code size through linking, but I also want a single file solution (mainly because I'm too lazy to think about multiple files).

There's tool over at Microsoft Research, ILMerge, which can combine multiple assemblies into one. But it's proprietary, so usage is restricted and source is unavailable... meaning no derived tools can be created.

Enter MonoMerge, a tool that takes a set of assemblies, and merges them in a single one. But it appears that it's been abandoned. What's a geek to do?

I had a look at this tool and it appeared good enough during a simple test. A little more testing, and it started to fall apart. There appears to be two areas where the code falls down: name clashes & generics.

If two assemblies had private classes with matching names (like the ubiquitous <PrivateImplementationDetails>), then all code would incorrectly refer to only one of the classes. This would result in either an inability to resolve members during merging, or resolving to a similarly named member in the wrong class! This is a real problem as the compiler will often use such classes for array initializers or caching dictionaries used in switch statements. I originally tried to make a few small changes to the existing code to add class renaming support, and while this partially worked... a complete implementation along those lines would just scatter if/else statements throughout the code. It also didn't help resolve the generics issue.

Generics were a problem because in resolving MethodReferences equality was judged upon the ToString() result of MethodReferences. This causes problems because two different calls can share the same ToString() signature. A simple example:

    public class CalledGenClassClass<U>{

        public static void CalledMethodMethod(){}

    }

    public class CalledGenMethodClass{

        public static void CalledMethodMethod<V>(){}

    }

    public class GenMethodClass{

        public static void DemoMethod<T>(){

            CalledGenMethodClass.CalledMethodMethod<T>();

            CalledGenClassClass<T>.CalledMethodMethod();

        }

    }

    public class GenClassClass<T>{

        public static void DemoMethod(){

            CalledGenMethodClass.CalledMethodMethod<T>();

            CalledGenClassClass<T>.CalledMethodMethod();

        }

    }

We've got four calls, happening here. A generic method & generic class call, each using a generic method & generic class parameter. The problem is both calls have the same ToString() signature from a Cecil point of point (CalledGenMethodClass::CalledMethodMethod<T>() & CalledGenClassClass`1<T>::CalledMethodMethod()). Which is fine, but the parameter T is only valid within the scope of the body calling the reference, you can't use it outside of a method body, because T might mean something different.

In IL these signatures differ using the (!) notation:
GenMethodClass.DemoMethod: CalledGenMethodClass::CalledMethodMethod<!T>() & CalledGenClassClass`1<!T>::CalledMethodMethod()
GenClassClass.DemoMethod: CalledGenMethodClass::CalledMethodMethod<!!T>() & CalledGenClassClass`1<!!T>::CalledMethodMethod()

I originally tried to change Cecil to return !T or !!T in ToString(), but then realised the notation wasn't the solution. There would still be a deeper issue of resolving references.

I set off to find a better way to resolve MemberReferences...

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.NET

Related posts

Comments

Add comment


 

biuquote
Loading



Powered by BlogEngine.NET 1.3.1.30
Original theme by Mads Kristensen

About the author

Name of author Ivan Hamilton
"My inner nerd can beat up your inner nerd."

E-mail me Send mail

Adsense

Calendar

<<  April 2018  >>
MoTuWeThFrSaSu
2627282930311
2345678
9101112131415
16171819202122
23242526272829
30123456

View posts in large calendar

Recent comments

Tags

None

    Entropy

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2018

    Sign in