注意到每次编译完之后,你的 dll 或者 exe 是不一样的吗?本来这并没有什么大不了的,但大家都知道数字和鹅厂的安全软件遍布在我们大(tiān)陆(cháo)地区的大量电脑上,它们的查杀策略是——凡是不认识的一律是病毒木马;于是每次不一样的编译很容易引起它们的警告——真不想每次都把编译后的样本提交给它们存档入库。
确定性编译
于是有一天意外地发现了 Roslyn 的确定性构建。
方法是在 csproj 文件中加入 <Deterministic/>
标记。
<Project>
<PropertyGroup>
<Deterministic>true</Deterministic>
</PropertyGroup>
</Project>
然后重新生成 dll 或 exe,多生成几次(每次都重新生成),会发现每次验证文件的 Hash 值都是一样的。
但是,一旦我们去掉这个标记,再验证 Hash 值,就开始改变了,而且每次都不一样。
不确定的编译
是什么导致了没有加此标记时每次编译都不一样呢?最少有三个:
- MVID:当初微软在制定 CLI 标准时就说每次编译都应该在 PE 头生成新的 Id(很多工具都直接使用了 guid)
- PDB ID:一个跟新生成的 PDB 文件匹配的 GUID 标识符
- 时间戳:每次编译都要把当前时间加上
当然,如果你的版本号使用了 1.0.*
这样的动态版本号,那么每次编译还会新增一个构建号。