dotnet / ILMerge

ILMerge is a static linker for .NET Assemblies.
MIT License
1.23k stars 170 forks source link

Description of cause of error ILMerge.Merge: The assembly 'Foo' was not merged in correctly. It is still listed as an external reference in the target assembly. #31

Open davidhunter22 opened 6 years ago

davidhunter22 commented 6 years ago

I recently ran into the error "ILMerge.Merge: The assembly 'Foo' was not merged in correctly. It is still listed as an external reference in the target assembly." There are a few references to this on the web but none I found helpful. Anyway after some debugging fun I found the following to be the cause, at least in my case. Imagine you have three assemblies with the folowing dependencies

A -> B -> C
A -> C

You then try to ILMerge just assemblies A and C to produce a merged assembly AC. ILMerge will find the reference of C in B and regard it as an external reference to an assembly for the merged AC. However C is one of the assemblies which you are trying to ILMerge so at the end of the merge process it produces the message "ILMerge.Merge: The assembly 'C' was not merged in correctly. It is still listed as an external reference in the target assembly."

This makes a lot of sense you can't both merge and not merge assembly C. The problem is that the error is not very clear. My general feeling is that in a assembly dependency DAG if you try to merge two assemblies you must merge all intermediate assemblies between them. In the above eample the means assembly B. Ideally there would be an initial step in ILMerge which constructed the DAG and complained in some obvious way.

At a minimum it would be good to mention assembly B in th error so "ILMerge.Merge: The assembly 'C' was not merged in correctly. It an external reference in assembly B which is not being merged and is referenced by assembly A which is". I looked at changing the code to do this but don't understand it well enough at least so far.

Note this explains why the suggestion here https://stackoverflow.com/questions/1807652/ilmerge-dll-assembly-not-merged-in-correctly-still-listed-as-an-external-refer to use /closed worked, adding /closed implicitly adds assembly B to the assemblies you are trying to merge.

benlabbeus commented 3 years ago

This is a great point and should be noted. I also noticed that despite that error, the assembly actually did merge while also included as an external assembly. Used ILDASM to see this.