Merging assemblies using ILRepack

ILRepack is a tool that allows you to merge multiple assemblies into a single assembly. This can be useful when you deploy an application that has a few dependencies. In this case, you can merge all the dll and the exe into a single exe file, so it's easier to deploy it. It's also useful if you create a NuGet package. In this case, it allows to remove the dependencies that you don't want to expose to your consumers. For instance, if your library depends on Newtonsoft.Json in a private method, you can merge this library into your dll to avoid exposing the NuGet package as a dependency of your NuGet package. This can prevent some problems if multiple NuGet packages depend on different versions of Newtonsoft.Json.

Using ILRepack to merge assemblies as an MSBuild task

First, you need to install the NuGet package ILRepack.MSBuild.Task (GitHub).

<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />

  ...

  <ItemGroup>
    <PackageReference Include="ILRepack.MSBuild.Task" Version="1.0.9" />
  </ItemGroup>
</Project>

Then, you can add the repack target in your csproj file. You should run ILRepack only on Release configuration because it increases the build time and complexify the debugging of your application. To merge assemblies you have to declare all the files you want to combine using the <InputAssemblies>. You should use MSBuild properties to get the full path of the files.

<Project>
  ...

  <!-- Merge only on Release configuration -->
  <Target Name="AfterBuild" Condition="'$(Configuration)' == 'Release'">

    <!-- List of assemblies to merge, you must start with the main dll/exe, so you can use SameAsPrimaryAssembly later -->
    <ItemGroup>
      <InputAssemblies Include="$(TargetPath)" /> <!-- Output file of the project -->
      <InputAssemblies Include="$(OutputPath)\Newtonsoft.Json.dll" />
    </ItemGroup>

    <!-- ILRepack task -->
    <ILRepack
        Parallel="true"
        Internalize="true"
        InternalizeExclude="@(DoNotInternalizeAssemblies)"
        InputAssemblies="@(InputAssemblies)"
        TargetKind="SameAsPrimaryAssembly"
        OutputFile="$(TargetPath)" />

  </Target>
</Project>

Merging assemblies in a .NET Standard project

When you build a .NET Standard project, the output only contains the file generated by the project. The dependencies are not copied to the output directory. This means you can't use <InputAssemblies Include="$(OutputPath)\Newtonsoft.Json.dll" />. Instead you must use the path of the dll in the NuGet directory.

During the build, the property ReferencePathWithRefAssemblies is set with the list of dll used to build. You can use this list with a condition to get the full path of a specific dll. Yep, MSBuild can be very powerful 😃

Here's an example:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="ILRepack.MSBuild.Task" Version="1.0.9" />
    <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
  </ItemGroup>

  <Target Name="ILRepack" AfterTargets="Build">
    <!-- List of assemblies to merge -->
    <ItemGroup>
      <InputAssemblies Include="$(TargetPath)" /> <!-- Output file of the project -->
      <InputAssemblies Include="@(ReferencePathWithRefAssemblies)" Condition="'%(filename)' == 'Newtonsoft.Json'" />
    </ItemGroup>

    <!-- ILRepack task -->
    <ILRepack
        Parallel="true"
        Internalize="true"
        InternalizeExclude="@(DoNotInternalizeAssemblies)"
        InputAssemblies="@(InputAssemblies)"
        TargetKind="SameAsPrimaryAssembly"
        OutputFile="$(TargetPath)" />

  </Target>

</Project>

Note that if you are publishing a NuGet package, you may need to create a custom nuspec file to remove the dependencies that are merged using ILRepack.

Leave a reply