.NET 使用 ILRepack 合并多个程序集(替代 ILMerge),避免引入额外的依赖

我们有多种工具可以将程序集合并成为一个。比如 ILMerge、Mono.Merge。前者不可定制、运行缓慢、消耗资源(不过好消息是现在开源了);后者已被弃用、不受支持且基于旧版本的 Mono.Cecil。

而本文介绍用来替代它们的 ILRepack,使用 ILRepack 来合并程序集。



ILRepack 提供了可供你项目使用的 NuGet 包。如果你在团队项目当中安装了 ILRepack 的 NuGet 包,那么无论团队其他人是否安装了 ILRepack 的工具,都可以使用 ILRepack 工具。这可以避免要求团队所有成员安装工具或者将工具内置到项目的源代码管理中。

要以 NuGet 包的形式来使用 ILRepack,需要首先安装 ILRepack 的 NuGet 包:

  • [NuGet GalleryILRepack](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="&quot;$(ILRepack)&quot; /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="&quot;$(ILRepack)&quot; /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>

最终生成的输出目录下只有我们最终期望生成的程序集:

640?wx_fmt=png


相比于 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'

640?wx_fmt=png

那么你需要做以下两种事情中的任何一种:

  1. 将所有依赖合并;

  2. 将依赖加入搜索目录。

将所有依赖合并指的是将缺少的依赖也一起作为命令行参数传入要合并的程序集中。

而另一种是增加一个参数 /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

640?wx_fmt=jpeg

原文地址:https://blog.walterlv.com/post/merge-assemblies-using-ilrepack.html

.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com 
640?wx_fmt=jpeg

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/315457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

4G的小程序与5G的Chromium OS?

提到桌面操作系统&#xff0c;Windows 与 macOS 自然是家喻户晓&#xff0c;稍微有点 IT 知识的人也会知道 Linux&#xff0c;而 Fuchsia 和鸿蒙&#xff08;方舟&#xff09;则还在积极开发中&#xff0c;除了这几大类比较热门的&#xff0c;当前还有一大潜力股 Chrome OS&…

P3605 [USACO17JAN]Promotion Counting P dfs序

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 这个题可以用各种姿势a掉&#xff0c;树启和线段树合并都可以&#xff0c;比较无脑。下面给一个解决这种问题比较巧妙的做法。 考虑暴力怎么写&#xff0c;我们先将每个点的权值离散化一下…

推荐VSCode多语言开发,支持一键JAVA

哈喽大家周一好&#xff01;好久不见鸭&#xff0c;最近在看一本书&#xff0c;很好&#xff0c;《人类简史》&#xff0c;适合夏日星空&#xff0c;仰观宇宙之大?这个专题是“做贡献”&#xff0c;也是作为软粉&#xff0c;打算一直推广微软自己的东西&#xff0c;上一次还是…

思维--找规律--Codeforces Round #645 (Div. 2) c题

C. Celex Update 题目大意&#xff1a;给出两点的坐标&#xff0c;找出不同的路径的总数&#xff08;路径数字总和不同&#xff09; 思路&#xff1a;根据观察向下走比向右走的增加幅度加1&#xff0c;所以在第i步 向下 对sum的影响是 n-i1 所以最小数字为12。。。。y&#xf…

分布式Redis的分布式锁 Redlock

引言之前自己在用redis来实现分布式锁的时候都是基于单个Redis实例&#xff0c;也就是说Redis本身是有单点故障的&#xff0c;Redis的官方文档介绍了一种"自认为"合理的算法&#xff0c;Redlock来实现分布式Redis下的分布式锁。Martin Kleppmann写了一篇文章分析Redl…

双指针--Codeforces Round #645 (Div. 2) d题

D. The Best Vacation 题目大意&#xff1a; 算出连续x天最多的拥抱&#xff0c;一个月第i号就有i个拥抱 思路&#xff1a;双指针&#xff0c;扫描过去&#xff08;每个月每个月的计算&#xff0c;最后超出的部分再一天一天算&#xff09; 代码 &#xff1a; #include<cstd…

从CLR GC到CoreCLR GC看.NET Core对云原生的支持

内存分配概要前段时间在园子里看到有人提到了GC学习的重要性&#xff0c;很赞同他的观点。充分了解GC可以帮助我们更好的认识.NET的设计以及为何在云原生开发中.NET Core会占有更大的优势&#xff0c;这也是一个程序员成长到更高层次所需要经历的过程。在认识GC的过程中&#x…

一张图带你了解 Insider Dev Tour 2019中国技术大会

点击阅读原文&#xff0c;前往微软Insider Dev Tour 全球官网

Codeforces Round #606 (Div. 2, based on Technocup 2020 Elimination Round 4) 构造

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给nnn个数&#xff0c;让你构造一个尽可能大的矩阵&#xff0c;其中每个点所在的行和列都不含相等元素。 思路&#xff1a; 假设构造的答案矩阵大小为ababab且a<ba<ba<b&#xff0c;那么我们可以…

.NET项目迁移到.NET Core操作指南

这篇文章&#xff0c;汇集了大量优秀作者写的关于".NET迁移到.NET Core"资料文章以及微软官方教程文档。是我在迁移公司框架项目到.NET Core和.NET Standard时遇到的问题&#xff0c;并将相关资料整理成这篇文章。记录如何一步一步把项目迁移到.NET Core。在此感谢这…

Educational Codeforces Round 88 D. Yet Another Yet Another Task(巧枚举)

cf地址 **题目大意&#xff1a;**一个序列&#xff0c;你可以选择一个子段&#xff0c;要求去掉子段最大值后的和最大&#xff0c;求出这个最大值 **思路&#xff1a;**a[i]的范围比较小&#xff0c;可以通过枚举最大值&#xff0c;再找到最大值可以辐射的区间。经典套路了。…

Codeforces Round #607 (Div. 2) E. Jeremy Bearimy dfs + 思维

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你2∗k2*k2∗k个点的一棵树。定义GGG为任选kkk组不同的点&#xff0c;每组点的距离和的最小值。定义BBB为任选kkk组不同的点&#xff0c;每组点的距离和的最大值。让你求出GGG和BBB。 思路&#xff1a; …

EF Core 3 的 40 个中断性变更

为了修复 Entify Framework Core 中许多已发现的缺陷&#xff0c;微软在 EF Core 3 中引入了 40 个中断性变更。我们可以在微软文档中查看完整的中断性变更列表&#xff0c;本文仅列举几个主要的点。客户端查询为了突破 EF Core SQL 生成器的限制&#xff0c;默认只在客户端执行…

Codeforces Round #646 (Div. 2) E(贪心,bfs)

Codeforces Round #646 (Div. 2) E 题目大意&#xff1a; 给一棵树&#xff0c;每个节点有三个权值 A,B,C, (B,C为0或1)&#xff0c;每次你可以花费 A[u] *k的代价让A子树中的任意 k 个节点交换彼此的 B &#xff0c;问让所有节点的 BC 至少花费多少代价。 思路&#xff1a; …

联手微软,Docker公司将推出Docker Desktop for WSL 2

微软最新推出的 WSL 2 在架构方面发生了重大的变化&#xff1a;它提供了一个在轻量级 VM 中运行的真正 Linux 内核。使用真正的 Linux 内核意味着可以在 Windows 上运行 ELF64 Linux 二进制文件。对 Docker 来说绝对是利好消息&#xff0c;因为这意味着 Linux 版本的 Docker 可…

Educational Codeforces Round 88 (Rated for Div. 2) E(数学)

Educational Codeforces Round 88 (Rated for Div. 2)E 题目大意: 给你n&#xff0c;k(1<k<n<5e5)&#xff0c;从1到n中选k个数组成一个严格递增序列&#xff0c;如果对任何正整数&#xff0c;依次模上这k个数&#xff0c;无论这k个数如何排列得到的答案都相同&#…

HAProxy 2.0发布,长期支持版本

HAProxy 2.0 发布了。HAProxy 是一个使用 C 语言编写的自由及开源软件&#xff0c;其提供高可用性、负载均衡以及基于 TCP 和 HTTP 应用的代理&#xff0c;支持虚拟主机&#xff0c;它是免费、快速并且可靠的 Web 负载均衡解决方案。包括 GitHub、Bitbucket、Stack Overflow、R…

Codeforces Round #651 (Div. 2) D

D. Odd-Even Subsequence 题目大意&#xff1a;在a数组中 保留k个数字&#xff0c;如何代价最小的多少。 代价的算法 具体看题意&#xff1a;就是k数组中 min{max{奇数下标}&#xff0c;max{偶数下标}} 解题思路&#xff1a;贪心加二分&#xff0c;二分全部的答案&#xff08…

CF1042E Vasya and Magic Matrix 期望dp + 推公式

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 思路&#xff1a; 将矩阵中的数放到数组里排序&#xff0c;就是一个比较明显的期望dpdpdp了。 定义f[i]f[i]f[i]表示从第iii个出发的期望得分&#xff0c;所以转移方程也比较好写了&#xff1a;f[i]∑(f[j](…

C#并发编程之异步编程(一)

写在前面C#5.0中&#xff0c;对异步编程进行了一次革命性的重构&#xff0c;引入了async和await这两个关键字&#xff0c;使得开发人员在不需要深刻了解异步编程的底层原理&#xff0c;就可以写出十分优美而又代码量极少的代码。如果使用得当&#xff0c;你可以写出具有并行化并…