Merging assemblies using ILRepack

 
 
  • Gérald Barré

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 removing 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.Lib.MSBuild.Task (GitHub).

csproj (MSBuild project file)
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  ...

  <ItemGroup>
    <PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.16" />
        <PackageReference Include="Newtonsoft.Json" Version="12.0.1" PrivateAssets="all" />
  </ItemGroup>

  ...

</Project>

Then, you can add the repack target in a file named ILRepack.targets. 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.

csproj (MSBuild project file)
<?xml version="1.0" encoding="utf-8" ?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

    <Target Name="ILRepacker" AfterTargets="Build" Condition="'$(Configuration)' == 'Release'">
        <ItemGroup>
            <InputAssemblies Include="$(TargetPath)"/>
            <InputAssemblies Include="@(ReferencePathWithRefAssemblies)" Condition="'%(filename)' == 'Newtonsoft.Json'" />
        </ItemGroup>

        <ILRepack
            AllowDuplicateResources="false"
            DebugInfo="true"
            Internalize="true"
            InputAssemblies="@(InputAssemblies)"
            OutputFile="$(TargetPath)"
            Parallel="true"
            TargetKind="SameAsPrimaryAssembly" />
    </Target>
</Project>

Note that I do not reference assemblies using their path, because 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. So, you cannot know the full path of the dll. 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 😃

Final note: 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.

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee💖 Sponsor on GitHub