Friday, May 01, 2009

Real Incremental Build - Part 4 – Compare Assemblies using ILDASM

Part 1 – for motivation.
Part 2 – Plan for getting only new/updated files.
Part 3 – Out of the box Incremental build with Team Build.

In last part we succeed getting only new/updated files except binaries which were regenerated also no actual change was made to their code – because some reference in their dependency tree was changed.

We want only real updated assemblies.

Again, the trivial solution doesn’t work:

If you try to compare each assembly with its equivalent in the original build you’ll find that each time you build a project, the assembly is different! (even if no code was changed)

Here comes ILDASM (MSIL Disassembler) to the rescue.

This tool takes and assembly (either DLL or EXE) and can create a text file containing all structure and actual IL code of the file.

If you compare 2 disassembled files which should be identical you’ll probably see the following different lines:

  1. Time-date stamp
    This parameter is regenerated each time – so it will be different every time.
  2. MVID
    This is a generated GUID – Regenerated each time.
  3. .ver
    Lines with .ver arr declarations of the specific version of referenced assemblies.
    Those lines would be changed if some referenced assemblies has changed their versioning.
    This happens due to the use of * in the AssemblyVersion attribute in AssemblyInfo.cs
    You need to decide whether this is a breaking change from your point of view – or not.
    In my case – we don’t work with Signed DLLs, and I don’t mind what is the specific version. 
  4. PrivateImplementationDetails

    I don’t know for sure what that means, but from my experience it changed without any real change happened.

    Those lines happen to be changed.

So here the actual process:

  1. You iterate through all the remaining files.
  2. If the file’s extension is either .dll or .exe – you run ILDASM on this file, . Those are the parameters I used, but to tell the truth – I haven’t investigate them much:

    ildasm.exe  assemblyFileName /OUT=out.txt  /ALL /RAWEH  /SOURCE /LINENUM /CAVERBAL /NOBAR /UTF8 /TYPELIST

    Run it second time for the original assembly file too.
  3. Compare the 2 output files (I just iterate through the lines in both files) and ignore the changes which have been described above. (Time-date stamp, MVID, etc.)

    I would jump to the next line which doesn’t contain “WARNING:” in case I meet such a line.
    This is because I have seen cases were only one of the assemblies contained such a line, and then it will break you comparison if you not jump to the next valid line.
  4. If the files are equal – delete the assembly from the drop location.

The result of this procedure is: Diff package containing only new/updated files

Easy it was, wasn’t it?

No comments: