Geeks With Blogs
John Blumenauer's Blog .NET Development and Community Nuggets

A little Background

For quite some time now, it’s been possible to merge multiple .NET assemblies into a single assembly using ILMerge in Visual Studio 2008.  This is especially helpful when writing wrapper assemblies for 3rd-party libraries where it’s desirable to minimize the number of assemblies for distribution.  During the merge process, ILMerge will take a set of assemblies and merge them into a single assembly.  The resulting assembly can be either an executable or a DLL and is identified as the primary assembly.

Issue

During a recent project, I discovered using ILMerge to merge assemblies containing lambda expressions in Visual Studio 2010 is resulting in invalid primary assemblies.  The code below is not where the initial issue was identified, I will merely use it to illustrate the problem at hand.

In order to describe the issue, I created a console application and a class library for calculating a few math functions utilizing lambda expressions.  The code is available for download at the bottom of this blog entry.

MathLib.cs

using System;

namespace MathLib
{
    public static class MathHelpers
    {
        public static Func<double, double, double> Hypotenuse =

            (x, y) => Math.Sqrt(x * x + y * y);


        static readonly Func<int, int, bool> divisibleBy = (int a, int b) => a % b == 0;

        public static bool IsPrimeNumber(int x)
        {
            {

                for (int i = 2; i <= x / 2; i++)

                    if (divisibleBy(x, i))
                        return false;

                return true;

            };
        }

    }
}

Program.cs

using System;
using MathLib;

namespace ILMergeLambdasConsole
{
    class Program
    {
        static void Main(string[] args)
        {
            int n = 19;

            if (MathHelpers.IsPrimeNumber(n))
            {
                Console.WriteLine(n + " is prime");
            }
            else
            {
                Console.WriteLine(n + " is not prime");
            }

            Console.ReadLine();
        }
    }
}

Not surprisingly, the preceding code compiles, builds and executes without error prior to running the ILMerge tool.

 

ILMerge Setup

In order to utilize ILMerge, the following changes were made to the project.

  1. The MathLib.dll assembly was built in release configuration and copied to the MathLib folder.  The following folder hierarchy was used for this example: image 
  2. The project file for ILMergeLambdasConsole project file was edited to add the ILMerge post-build configuration.  The following lines were added near the bottom of the project file: 
      <Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">
        <Exec Command="&quot;..\..\lib\ILMerge\Ilmerge.exe&quot; /ndebug /out:@(MainAssembly) 
          &quot;@(IntermediateAssembly)&quot; @(ReferenceCopyLocalPaths->'&quot;%(FullPath)&quot;', ' ')" />
        <Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
      </Target>
    
  3. The ILMergeLambdasConsole project was modified to reference the MathLib.dll located in the MathLib folder above.
  4. ILMerge and ILMerge.exe.config was copied into the ILMerge folder shown above.  The contents of ILMerge.exe.config are:
    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <startup useLegacyV2RuntimeActivationPolicy="true">
        <requiredRuntime safemode="true" imageVersion="v4.0.30319" version="v4.0.30319"/>
      </startup>
    </configuration>
    

Post-ILMerge

After compiling and building, the MathLib.dll assembly will be merged into the ILMergeLambdasConsole executable.  Unfortunately, executing ILMergeLambdasConsole.exe now results in a crash.  The ILMerge documentation recommends using PEVerify.exe to validate assemblies after merging.  Executing PEVerify.exe against the ILMergeLambdasConsole.exe assembly results in the following error:

   image

Further investigation by using Reflector reveals the divisibleBy method in the MathHelpers class looks a bit questionable after the merge.

image   

Prior to using ILMerge, the same divisibleBy method appeared as the following in Reflector:

image

It’s pretty obvious something has gone awry during the merge process.  However, this is only occurring when building within the Visual Studio 2010 environment.  The same code and configuration built within Visual Studio 2008 executes fine.  I’m still investigating the issue.  If anyone has already experienced this situation and solved it, I would love to hear from you.  However, as of right now, it looks like something has gone terribly wrong when executing ILMerge against assemblies containing Lambdas in Visual Studio 2010.

RESOLUTION

After some correspondence with Mike Barnett from Microsoft, he suggested using the /targetplatform option instead of the ILMerge.exe configuration file.

Ex.

>ILMerge.exe /targetplatform:v4,c:\Windows\Microsoft.NET\Framework\v4.0.30319 /out:foo.exe Program.exe MathLib.dll

I added the /targetplatform option to my project file target section:

  <Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">
    <Exec Command="&quot;..\..\lib\ILMerge\Ilmerge.exe&quot; /targetplatform:v4,c:\Windows\Microsoft.NET\Framework\v4.0.30319 
      /ndebug /out:@(MainAssembly) &quot;@(IntermediateAssembly)&quot; @(ReferenceCopyLocalPaths->'&quot;%(FullPath)&quot;', ' ')" />
    <Delete Files="@(ReferenceCopyLocalPaths->'$(OutDir)%(DestinationSubDirectory)%(Filename)%(Extension)')" />
  </Target>

After adding this to the project file and deleting my ILMerge configuration file, everything worked fine, including the verification by PEVerify.

Updated Solution Files ILMergeLambdaExpressionUpdated

Thanks Mike!

Posted on Tuesday, June 15, 2010 12:15 AM | Back to top


Comments on this post: Is Merging Assemblies Containing Lambdas with ILMerge in VS2010 not Working? - UPDATED

# re: Is Merging Assemblies Containing Lambdas with ILMerge in VS2010 not Working? - UPDATED
Requesting Gravatar...
Congrats! I know this one was giving you a hard time.
Left by Adam Tolley on Jun 15, 2010 2:30 PM

Your comment:
 (will show your gravatar)


Copyright © John Blumenauer | Powered by: GeeksWithBlogs.net