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

MSBuild如何决定是否需要重建C#库?,c#,visual-studio,compiler-construction,msbuild,C#,Visual Studio,Compiler Construction,Msbuild,在针对C#项目文件运行MSBuild时,它如何决定是否需要重建库(即调用csc) 我想(但我想确认): 如果没有输出目录,则重新生成(duh:) 如果C#文件已更改,请重新生成 如果标记为“复制”的包含文件始终已更改,请重新生成 或者不重建文件,而只是将文件复制到现有输出,这是否足够聪明 如果包含的标记为copy If newer的文件已更改,请重新生成 问题同上 问题是,任何听起来似乎合理的启发都可能无法解决问题。当你要求你的编译器(构建系统)生成一个输出时,你最好保证输出是你所期望

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

我想(但我想确认):

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

问题是,任何听起来似乎合理的启发都可能无法解决问题。当你要求你的编译器(构建系统)生成一个输出时,你最好保证输出是你所期望的

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

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


文件系统“last modified date”属性在跨系统中不一致,因此最终不会用于确定是使用缓存输出生成还是从头生成。

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

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

正在跳过目标“CoreCompile”,因为 所有输出文件都是最新的 关于输入文件


目标文件位于.NET Framework目录(
C:\windows\Microsoft.NET\Framework\v3.5或v4.0.30319
)中。MSBuild具有内置功能

有两个属性,
输入
输出


无论何时
Input
更改或
Output
较旧或缺少
目标
都会执行。

我想这可以解释依赖项检查如此缓慢的原因。。关于编译器使用校验和的说法,你有参考资料吗?我可能有点冒险,我不确定我是如何得出这个结论的。我能找到的唯一参考是:它清楚地表明这些校验和是由调试器使用的,而不是编译器或MSBuild。在这一点上我可能错了。。。