il-repack icon indicating copy to clipboard operation
il-repack copied to clipboard

Merging identical types into one

Open deniszykov opened this issue 6 years ago • 6 comments

Currently when some dependency is merged twice ILRepack will duplicate and rename same types.

        A
      +   +
    B      C  <- cause duplication
   +
 C 

Ideally, I would like that one type would be discarded and the references to it would be replaced. I understand that this is a big feature request so I offer my help and time:

  1. I could write whole feature and PR it (cost me a some time to get into ILRepack pipelining code).
  2. Write "comparison" code for TypeDefinitions and wait until you embed it.
  3. Just wait :)

deniszykov avatar Jun 27 '18 14:06 deniszykov

Can you clarify what you mean by same types ? Because if the letters in your drawing are assemblies, then merging A+B+C will rebind/internalize all B references to C.

Maybe you want to consider types with same name but different assembly to be re-mapped ?

gluck avatar Jun 27 '18 14:06 gluck

I know that the same references are resolved. My example would merge fine, if merged with one pass. But there 2 passes:

  1. B+C
  2. A + B

For example there is nice hash library "Hashy", every one is using "Hashy" and because it is really small it is embedded with ILRepack with /internalize flag. I develop my "BigApp" and choose 10 different libraries and each has embedded "Hashy" (because it is small and every one likes it). I merge all of them into my BigApp.dll and now has 10 copies of "Hashy" inside my merged assembly.

For real life example, SharpZipLib sometimes embedded.

deniszykov avatar Jun 27 '18 14:06 deniszykov

Ok, assuming you're confident all the versions of C involved are identical, you may pass /allowdup:Hashy.* so that every type under that namespace will be 'merged into one' (which probably causes a mess if they are different, but should be a no-op if they are identical).

But maybe that doesn't work for you for some reason ?

gluck avatar Jun 27 '18 15:06 gluck

Wow, I didn't know about this feature :)

If you point me to right source code file I will write "mess check" in code and PR it.

I want "safe" merge. And maybe some granularity of merging. Not only exact match but partial match too. Or match by "footprint", not only name. For example if one type is subset of another type (like product of IL stripping by linker) they could be merged.

deniszykov avatar Jun 27 '18 15:06 deniszykov

All the magic ✨ happens in RepackImporter.cs, e.g. while importing a type we check if it's already been imported (by name). DuplicateTypeAllowed can be confusing and means "do we expect this type(s) to appear multiple times in the assemblies so we merge them together" (default behavior is to dedup/rename with unique names).

The existing risk with this approach is that the comparison method used to check if a method already exists seems ... unreliable ...

But please have a look and enjoy 🎉

gluck avatar Jun 27 '18 15:06 gluck

Thanks! 👍

deniszykov avatar Jun 27 '18 15:06 deniszykov

Does /union do what you want?

Doubt it does the deep diffing, it's not smart (I think?)

KirillOsenkov avatar Jan 07 '24 03:01 KirillOsenkov

/allowdup helped me that time but I'm still thinking on implementing

Write "comparison" code for TypeDefinitions

and add /allowdup=exactmatch feature. I will close issue for now, and will try to allocate time for PR.

deniszykov avatar Jan 08 '24 10:01 deniszykov