.NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖
我們有多種工具可以將程序集合并成為一個。比如 ILMerge、Mono.Merge。前者不可定制、運行緩慢、消耗資源(不過好消息是現在開源了);后者已被棄用、不受支持且基于舊版本的 Mono.Cecil。
而本文介紹用來替代它們的 ILRepack,使用 ILRepack 來合并程序集。
ILRepack 提供了可供你項目使用的 NuGet 包。如果你在團隊項目當中安裝了 ILRepack 的 NuGet 包,那么無論團隊其他人是否安裝了 ILRepack 的工具,都可以使用 ILRepack 工具。這可以避免要求團隊所有成員安裝工具或者將工具內置到項目的源代碼管理中。
要以 NuGet 包的形式來使用 ILRepack,需要首先安裝 ILRepack 的 NuGet 包:
[NuGet Gallery ILRepack](https://www.nuget.org/packages/ILRepack/)
或者直接在你的項目的 csproj 文件中添加?PackageReference:
我現在有一個項目 Walterlv.Demo.AssemblyLoading,這是一個控制臺程序。這個程序引用了一個 NuGet 包 Ben.Demystifier。為此帶來了三個額外的依賴。
- Walterlv.Demo.AssemblyLoading.exe- Ben.Demystifier.dll
- System.Collections.Immutable.dll
- System.Reflection.Metadata.dll
而我們可以使用 ILRepack 將這些依賴和我們生成的主程序合并成一個程序集,這樣分發程序的時候只需要一個程序集即可。
那么,我們現在需要編輯我們的項目文件:
<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net48</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ben.Demystifier" Version="0.1.4" />
<PackageReference Include="ILRepack" Version="2.0.17" />
</ItemGroup>
++ <Target Name="ILRepack">
++ <Exec Command=""$(ILRepack)" /out:$(OutputPath)$(AssemblyName).exe $(OutputPath)$(AssemblyName).exe $(OutputPath)Ben.Demystifier.dll $(OutputPath)System.Collections.Immutable.dll $(OutputPath)System.Reflection.Metadata.dll" />
++ </Target>
</Project>
我們只增加了三行,添加了一個名稱為 ILRepack 的 Target。(注意到項目文件中我有額外引用一個其他的 NuGet 包 Ben.Demystifier,這是為了演示將依賴進行合并而添加的 NuGet 包,具體是什么都沒有關系,我們只是在演示依賴的合并。)在這個 Target 里面,我們使用 Exec 的 Task 來執行 ILRepack 命令。具體這個命令代表的含義我們在下一節介紹 ILRepack 工具的時候會詳細介紹。如果你希望在你的項目當中進行嘗試,可以把后面那些代表程序集的名稱改為你自己項目中依賴程序集的名稱。
現在在編譯的時候使用命令?msbuild /t:ILRepack?就可以完成程序集的合并了。
注意,你普通編譯的話是不會進行 IL 合并的。
如果你希望常規編譯也可以進行 IL 合并,或者說希望在 Visual Studio 里面點擊生成按鈕的時候也能完成 IL 合并的話,那么你還需要增加一個跳板的編譯目標 Target。
我將這個名為?_ProjectRemoveDependencyFiles?的 Target 增加到了下面。它的目的是在?AfterBuild?這個編譯目標完成之后(AfterTargets)執行,然后執行前需要先執行(DependsOnTargets)ILRepack 這個 Target。在這個編譯目標執行的時候還會將原本的三個依賴刪除掉,這樣在生成的目錄下我們將只會看到我們最終期望的程序集 Walterlv.Demo.AssemblyLoading.exe 而沒有其他依賴程序集。
<Project Sdk="Microsoft.NET.Sdk"><PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net48</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Ben.Demystifier" Version="0.1.4" />
<PackageReference Include="ILRepack" Version="2.0.17" />
</ItemGroup>
<Target Name="ILRepack">
<Exec Command=""$(ILRepack)" /out:$(OutputPath)$(AssemblyName).exe $(OutputPath)$(AssemblyName).exe $(OutputPath)Ben.Demystifier.dll $(OutputPath)System.Collections.Immutable.dll $(OutputPath)System.Reflection.Metadata.dll" />
</Target>
++ <Target Name="_ProjectRemoveDependencyFiles" AfterTargets="AfterBuild" DependsOnTargets="ILRepack">
++ <ItemGroup>
++ <_ProjectDependencyFile Include="$(OutputPath)Ben.Demystifier.dll" />
++ <_ProjectDependencyFile Include="$(OutputPath)System.Collections.Immutable.dll" />
++ <_ProjectDependencyFile Include="$(OutputPath)System.Reflection.Metadata.dll" />
++ </ItemGroup>
++ <Delete Files="@(_ProjectDependencyFile)" />
++ </Target>
</Project>
最終生成的輸出目錄下只有我們最終期望生成的程序集:
相比于 ILMerge,ILRepack 的命令行在盡量貼近 ILMerge 的情況下做得更加簡化了。
ilrepack /out:Walterlv.Demo.AssemblyLoading.exe Walterlv.Demo.AssemblyLoading.exe Ben.Demystifier.dll System.Collections.Immutable.dll System.Reflection.Metadata.dll其中,/out?表示最終的輸出程序集的名稱或路徑,后面沒有前綴的參數都是需要合并的程序集的名稱或路徑。這些需要合并的參數中,第一個參數是主程序集,而后續其他的都是待合并的程序集。區別主程序集和其他程序集的原因是輸出的程序集需要有名稱、版本號等等信息,而這些信息將使用主程序集中的信息。
如果希望使用 ILRepack 的其他命令,可以考慮使用幫助命令:
或者直接訪問 ILRepack 的 GitHub 倉庫來查看用法:
gluck/il-repack: Open-source alternative to ILMerge
如果你在使用 ILRepack 合并程序集的過程中出現了缺少依賴的錯誤,例如下面這樣:
Mono.Cecil.AssemblyResolutionException: Failed to resolve assembly: 'xxxxxxxxx'那么你需要做以下兩種事情中的任何一種:
將所有依賴合并;
將依賴加入搜索目錄。
將所有依賴合并指的是將缺少的依賴也一起作為命令行參數傳入要合并的程序集中。
而另一種是增加一個參數?/lib,即添加一個被搜索的依賴程序集的目錄。將這個目錄指定后,則可以正確解析依賴完成合并。而且這些依賴將成為合并后的程序集的依賴,不會合并到程序集中。
ilrepack /lib:D:\Dependencies /out:Walterlv.Demo.AssemblyLoading.exe Walterlv.Demo.AssemblyLoading.exe Ben.Demystifier.dll System.Collections.Immutable.dll System.Reflection.Metadata.dll參考資料
gluck/il-repack: Open-source alternative to ILMerge
原文地址:https://blog.walterlv.com/post/merge-assemblies-using-ilrepack.html
.NET社區新聞,深度好文,歡迎訪問公眾號文章匯總?http://www.csharpkit.com?
總結
以上是生活随笔為你收集整理的.NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Dapper.Common基于Dappe
- 下一篇: 推荐VSCode多语言开发,支持一键JA