MSBuild如何决定是否需要重建C#库?

当MSBuild针对C#项目文件运行时,它是如何决定是否需要重建库(即调用csc)?

我想(但想确认):

  • 如果没有输出目录,重建(duh :))
  • 如果C#文件已更改,请重建
  • 如果标记为“复制”的包含文件始终更改,则重建
    • 或者它是否足够聪明,不能重建,只是将文件复制到现有输出?
  • 如果标记为copy-if-newer的包含文件已更改,则重建
    • 与上述问题相同

如果查看Microsoft.CSharp.targets(用于编译C#项目的MSBuild文件),CoreCompile目标会定义一组输入和输出。 这些用于执行依赖性检查以查看CoreCompile是否需要运行。 输入列表包括C#文件,资源文件,应用程序图标,强名称密钥文件以及您可以定义的其他自定义输入。

如果您有解决方案并在其上运行MSBuild并启用了诊断日志记录(/ v:diag命令行参数),则如果输出是最新的,您可能会看到此消息:

跳过目标“CoreCompile”,因为所有输出文件都是相对于输入文件的最新文件。

目标文件位于.NET Framework目录( C:\windows\Microsoft.NET\Framework\v3.5 or v4.0.30319 )中。

MSBuild具有内置function。

Target有两个属性, InputsOutputs

每当Input更改或Output较旧或丢失时,都会执行Target

事情是,任何看似合理的启发式都可能不会削减它。 当你要求你的编译器(构建系统)产生输出时,你最好保证输出是你所期望的。

据我所知,MSBuild不会这样做。 它总是重建(从头开始)整个解决方案/项目。 但是,从Visual Studio中调用MSBuild时,临时编译单元将保留在项目的\ obj文件夹中。 清空该文件夹与重建相同。

也就是说,如果编译器或构建系统要重用输出,它将使用实际文件内容的校验和来确定是否可以从其他地方检索已编译的输出。 这基本上是唯一可靠的方法,您可以确定文件是否实际需要从头开始重新编译。 仅供参考,这是由Visual C#编译器而不是MSBuild完成的。

文件系统“上次修改日期”属性与跨系统不一致,因此最终不会用于确定是使用缓存输出构建还是从头开始构建。