ILRepack is a tool that merges multiple assemblies into a single assembly. This is useful when deploying an application with several dependencies: you can combine all DLLs and the EXE into a single EXE file, making deployment simpler. It is also useful when publishing a NuGet package, as it lets you internalize dependencies you do not want to expose to consumers. For example, if your library uses Newtonsoft.Json only in its internal implementation, you can merge it into your DLL to avoid publishing it as a NuGet dependency. This prevents version conflicts when multiple 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, add the repack target in a file named ILRepack.targets. To merge assemblies, declare all files to combine using <InputAssemblies>. Use MSBuild properties to get the full path of each file.
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 assemblies are not referenced by path here. When building a .NET Standard project, the output directory only contains files generated by the project itself; dependencies are not copied there. This means you cannot use <InputAssemblies Include="$(OutputPath)\Newtonsoft.Json.dll" />. Instead, you must use the DLL path from the NuGet cache. During the build, the ReferencePathWithRefAssemblies property contains the list of DLLs used to compile the project. You can filter this list with a condition to get the full path of a specific DLL. MSBuild can be very powerful 😃
If you are publishing a NuGet package, you may also need to create a custom nuspec file to exclude the dependencies that have been merged using ILRepack.
Do you have a question or a suggestion about this post? Contact me!