为什么ASP.NET编译器在每次构建时都重新构建所有二进制文件?

11

当我使用aspnet_compiler重新编译我的项目(asp.net,c#)时,即使没有进行任何代码更改,重新构建的二进制文件也会发生变化。

我明白这是因为每次构建都会生成一个新的模块版本ID(GUID)来区分不同的构建;另一个相似的问题谈到了这个问题:Can i specify the module version id (MVID) when building a .net assembly?

上面链接的问题似乎表明,重新构建项目,并使二进制文件与相同未更改的代码的先前构建匹配的方法不存在。好吧,没问题,我理解了 - 但是为什么所有的二进制文件都被重新构建呢?

根据文档(http://msdn.microsoft.com/en-us/library/ms229863(v=vs.80).aspx),我认为除非指定-c作为参数,否则aspnet_compiler应该只重建实际需要重建的那些二进制文件(由于代码更改)。我是否误解了或者可能漏掉了什么?

我正在使用的aspnet_compiler参数:

aspnet_compiler -f -u -fixednames -nologo -v / -p .\myproject\ .\mybuild\
请注意,这个问题只会在WebSite项目中出现,而不是Web Application项目(它们编译方式不同)。即使您创建一个没有功能的WebSite项目和页面,并且在构建之间从未打开或更改过它,这个问题仍然会出现。
反编译生成的二进制文件并没有显示任何差异。比较两个“相同”的构建的二进制文件时,每次都会在相同部分显示小的差异 - 我认为这可能与随机构建GUID有关。我没有找到避免这种构建之间变化的方法。

2
我对aspnet_compiler并不熟悉,我的想法可能完全不正确,但你可能需要检查一下源文件的时间戳。我曾经遇到过类似于你所描述的问题,尽管使用的是不同的编译器。最终发现有一个源文件的时间戳在未来,因此编译器一直认为二进制文件已经过期。 - 500 - Internal Server Error
是的,必须检查时间戳以确保未注意到的微小更改(空格、注释等)强制重新编译。对我有用的指南是:http://blogs.msdn.com/b/jamesche/archive/2007/09/27/automating-aspnet-compiler-in-visual-web-developer.aspx。 - gsscoder
2个回答

2
请查看Eric Lippert的这篇优秀回答,了解C#编译器如何进行多次编译源代码。尽管功能相同,但你的构建与之前的构建不同可能有很多原因。
  • 编译器用IL等效物替换特殊语言功能,例如using块
  • 编译器对您的代码进行许多优化,每次迭代可能会产生略微不同的输出。
  • 编译器必须为匿名方法名称创建具体名称,每次编译它们都不同
  • 还有许多其他原因,您可以使用反汇编器轻松找到
请查看这些反汇编器并反汇编和反编译您的库或可执行文件以获得更好的理解。
http://ilspy.net/http://www.telerik.com/products/decompiler.aspx

这并没有解决我的问题(我不确定它是否可解决),但我仍然很感激这个答案;Eric Lippert提供的链接答案是一篇好文章。 - devlop

0

我发现在许多情况下,特别是在我的项目引用了同一解决方案中的其他项目的情况下,使用aspnet_compiler会导致完整的重新构建,这往往很难解释。(尽管有几次我调查时确实存在“更改”,即使它们对任何内容都没有真正影响,如空格、注释等的更改)

我还遇到了许多Visual Studio插件的问题,这些插件可以操纵制表符和其他空格、实际项目文件等。尽管这些更改对于我们人类来说没有明显的变化,但编译器看了一眼就会去“我看到了一个变化!重新构建所有东西!!!”。

不确定我的答案是否有所帮助,但我建议禁用插件,运行编译器,然后再运行编译器,看看会发生什么...


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接