繁体   English   中英

Visual Studio 重建未修改的项目

[英]Visual Studio Rebuilds unmodified projects

因此,正如标题所述,我现在有一个 VS2010 解决方案,其中包含大约 50 个项目。 如果我对没有任何引用的“顶级”项目进行更改,那么 VS 仍然会重建所有 50 个项目。 我正在运行没有任何附加组件的 Visual Studio 2010 Ultimate。 我正在使用 ILMerge 将所有项目合并到一个文件中。

我通过检查较低级别 dll 的时间戳来验证这一点,并看到它们确实被重建了,即使它们的代码没有被触及。

我已阅读以下所有回复和评论:

Visual Studio 2008 不断重建

Visual Studio 不断构建一切

我的解决方案中出现了奇怪的 VS2010 构建故障

在 Visual Studio 中重建 C# 项目的原因

但他们中的大多数只是提供关于卸载项目以加快构建时间的建议,但没有具体的修复方法。 我试图弄清楚为什么 VS 认为这些依赖项目需要重建而不需要重建并修复它。

我打开了“工具 > 选项 > 项目和解决方案 > 构建和运行 > 仅构建启动项目和运行依赖项”,但没有任何效果。

此外,如果我只是重建一个只有 8 个(内)直接依赖项的“中级”项目,那么即使没有调用 ILMerge 并且没有修改任何依赖项目,它仍然会构建所有 8 个项目。

感谢大家提供的任何见解。

添加

为了测试一些建议,我从头开始创建了一个新的 WinForms 项目。 然后,我在该解决方案中创建了两个新项目。 我将两个“最低级别”项目中的所有代码和资源(不是项目文件)复制到两个全新的项目中(我通过将文件和文件夹从资源管理器拖放到 Visual Studio 中的项目中来做到这一点)。

最低的项目,我们称之为B ,没有引用任何其他项目。 下一个项目A仅引用了B。 因此,一旦我将所需的 .NET 和外部程序集引用添加到项目中,就会构建解决方案。

然后我有了新的 WinForm 项目参考A并进行了完整构建。 所以参考链是:

WinForm -> A -> B

然后我修改了WinForm并进行了标准构建 (F6)。 和以前一样,Visual Studio 重建了所有三个项目。

在对项目B中的源文件进行一些系统性删除后,我发现如果我删除了我的Resources.Designer.csResources.resx (并注释掉了使用这些资源的.Properties.Resources对象的代码),那么修改WinForm将不再重建整个解决方案,只会重建WinForm

Resources.resxResources.Designer.cs添加回项目B (但将引用的代码注释掉,以便没有使用资源)将重新引入完整的构建行为。

为了查看我的资源文件是否已损坏,我再次删除了它们,然后创建了一个新文件(通过项目属性 -> 资源)并重新添加了与以前相同的资源,即单个 Excel 文件。 使用此设置,仍然会进行完全重建。

然后我删除了单个资源,但将资源文件留在了项目B中。 即使没有添加资源,但资源文件仍在项目中,也会发生完整的(不需要的)重建。

似乎只是将资源文件添加到 (.NET 3.5) 项目将导致 Visual Studio 2010 始终重建该项目。 这是错误还是预期/预期的行为?

再次感谢大家!

打开工具 - 选项,选择项目和解决方案 - 在树中构建和运行,然后将“MSBuild 项目构建输出详细程度”设置为诊断。 这将输出构建项目的原因,即

项目“ReferencedProject”不是最新的。 项目项“c:\some.xml”的“复制到输出目录”属性设置为“始终复制”。

或者

项目“MyProject”不是最新的。 输入文件 'c:\ReferencedProject.dll' 在输出文件 'c:\MyProject.pdb' 之后被修改。

在这种情况下,修复方法是仅在更新时复制 some.xml。

构建前和构建后事件也可以触发构建。

虽然我认为这不是一个解决方法,但它是一种适用于我的情况的解决方法......

我最初在 50 个项目中大约有 5 个项目包含Resources部分。 这些项目总是会被重建,因此他们所依赖的任何东西也会被重建。 这 5 个项目中的一个是其他 48 个项目引用的“基础”级库,因此我的项目的 96% 每次都会重新构建,即使它不需要它。

我的解决方法是使用依赖注入、接口和专用的“资源”项目。 我没有让这 5 个项目引用它们自己的Resources对象,而是在每个项目中创建了一个接口来提供所需的资源。 然后,需要这些资源的类将需要在构造函数中创建它们的过程中传入该接口(构造函数注入)。

然后,我创建了一个单独的“资源”项目,该项目具有正常的实际资源部分。 该项目仅包含资源本身,以及通过接口提供这些资源所需的每个接口的类。 该项目将引用具有资源依赖关系的所有其他项目并实现项目所需的接口。

最后,在我没有任何引用的“顶级”项目中(以及实际构建 exe 和我的组合根所在的位置),我引用了“资源”项目,连接了 DI,然后我们就走了。

这意味着每次只会重建两个项目(“资源”和“顶级”),如果我进行部分构建(Shift-F6),那么它们根本不会被重建。

同样,这不是一个很好的解决方法,但是每次构建需要大约 3 分钟才能构建 48 个项目,因此我每天因不必要的重建而损失 30 到 90 分钟。 重构花了一些时间,但我认为这是一项不错的投资。

这是一个简化的图表。 请注意,为了减少混乱,没有显示从 Main.exe 到Main.exeProj2的依赖Proj1

解决方案示意图

通过这种设计,我可以在不触发完全重建的情况下构建Proj1Proj2 ,因为它们对Resources部分没有任何依赖关系。 只有Main知道Resources的实现。

当一个项目有一个实际上并不存在的文件时,就会发生这种情况。
该项目无法确定文件是否已更改(因为它不存在),因此它会重新构建。

只需查看项目中的所有文件,然后搜索附近没有可扩展箭头的文件。

我在 VS 2015 中遇到了同样的问题。

对我来说诀窍是:

  1. 一个项目在其他项目箱中引用自己的副本(魔术,是的)。 当切换到诊断构建输出(在构建选项中)然后尝试从项目层次结构的顶部一个一个地构建项目时,可以找到这种东西 - 如果您看到即使没有任何更改也可以重建的项目然后看到它参考。
  2. 我已将所有项目中的所有“始终复制”文件更改为“如果更新则复制”。 基本上,在所有 .csproj 文件中,将<CopyToOutputDirectory>Always</CopyToOutputDirectory>替换为<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
  3. 然后,我使用此 powershell 脚本禁用了 NTFS 隧道,如本文所述:

New-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "MaximumTunnelEntries" -Value 0 -PropertyType "DWord"

之后我需要重建,它现在似乎工作。

在我的情况下,罪魁祸首是将引用的 dll 的“复制本地”设置设置为 true,而“复制到输出目录”将文件设置为始终复制。

对于 .Net Core 项目,上述所有解决方案均无效。 我找到了解决方案。 如果您使用的是 Visual Studio 2019:

  1. 两次构建解决方案
  2. 打开Tools -> Options -> Projects and Solutions -> SDK-Style Projects -> Logging Level -> Verbose
  3. 清除输出窗口
  4. 构建您的启动项目
  5. 检查输出窗口。 所有以FastUpToDate开头的字符串
  6. 您会发现一些项目项使您的项目不是最新的。
  7. 修复这些问题并从步骤 1 重试。如果您的修复正确,您将实现Build: 0 succeeded, 0 failed, {n} up-to-date, 0 skipped in last string of build output。

MSBuild 团队正在这里收集有关调查构建增量问题的文档: https ://github.com/Microsoft/MSBuild/wiki/Rebuilding%20when%20nothing%20changed

更新链接: https ://github.com/dotnet/msbuild/blob/main/documentation/wiki/Rebuilding-when-nothing-changed.md

根据您的观察,听起来您的项目以一种不明显的方式表达了对其他项目的依赖关系。 孤立的依赖项可能会保留在项目文件中,而不会在 UI 中显示。 您是否在文本编辑器中打开了一个行为不端的项目文件? 检查解决方案构建依赖项?

如果您无法发现任何东西,请尝试从头开始重新创建您的一个项目,以查看新项目是否出现相同的问题。 如果干净的项目正确构建,您将知道您在某处表达了不需要的依赖项。 据我所知,这些必须在项目文件或解决方案文件中,除非您有 makefile 或其他不寻常的构建步骤。

通过增加构建日志的详细程度,我终于找到了另一个我很难找到的罪魁祸首。

在某些情况下,MSBuild 会在输出文件夹中查找vc120.pdb ,如果此文件不存在,它将重新构建整个项目。 即使您禁用了调试符号生成,也会发生这种情况。

此处的解决方法是启用调试符号并生成此文件,然后再次禁用该设置而不删除 PDB 文件。

我遇到了同样的问题,结果证明这与几个项目有关,这些项目在他们自己的输出目录中具有对 dll 的复制本地引用。

找到这一点的关键是为构建输出设置诊断输出,但还要知道要在日志中查找什么。 搜索:“不是最新的”是关键。

这是VS2010总是重建解决方案的答案?

通过更改项目文件、清理解决方案、手动删除所有 bin 文件夹、重新启动 Visual Studio 并重建所有内容来解决此问题。

我和你有同样的问题。 我发现它来自一些已删除的文件。 当我从项目中删除文件时,问题就消失了。 问候。

对于此类构建问题,将 MSBuild 输出详细程度设置为“诊断”确实是必要的第一步。 大多数情况下,重新构建的所述原因足以采取行动,但有时 MSBuild 会错误地声称某些文件已修改并需要复制。

如果是这种情况,您需要禁用 NTFS 隧道或将输出文件夹复制到新位置。 这里有更多的话。

另一个经常发生的问题是,当您的解决方案中的某些项目具有未来的修改标记时。 如果您将时钟调快,然后将时钟设置为正确的时间,就会发生这种情况。 我在安装 Linux 时发生了这种情况。

在这种情况下,您可以使用 git bash 递归地触摸所有文件(是的,在 Windows 中):

find . -exec touch {} \;

从 Visual Studio 2015 升级到 2017 时,我遇到了 Visual Studio 重建项目的问题,我添加了这个答案是为了让那些可能遇到类似问题的人受益,因为它似乎没有在任何地方记录。

就我而言,问题在于解决方案中的所有项目都具有相同的中间输出路径 (obj)。 文件 GeneratedInternalTypeHelper.cs 由包含 XAML 的所有项目生成。 直到 Visual Studio 2015,构建过程显然没有检查此文件的文件日期,因此没有出现问题。 使用 VS2017 会检查此文件的文件日期,并且因为构建过程中的后续项目将覆盖它(具有相同的内容),所以较早的项目将重新构建,重新触发以后的构建,无限。

在这种情况下的解决方案是确保所有项目都有不同的中间输出目录,这将使问题消失。

在我的情况下(混合 C#、C++/CLI 和本机 C++ 解决方案),即使没有任何改变,一些 C++ 项目正在重新链接。 我花了很长时间试图弄清楚发生了什么。 最后,我从“命令行”选项中发现,PDB 输出路径(选项 /Fd)无法处理文件夹设置 $(IntDir)。 我删除了它 - 一个空值将正确执行默认值 - 我的问题消失了。

正如其他人所注意到的,一个可能的原因是 CopyToOutputDirectory 设置为 Always。 这可以通过应用下面的 powershell 脚本在所有项目文件中同时修复:

$folder = "C:\My\Solution\Folder"
$csvFiles = Get-ChildItem $folder *.csproj -rec
foreach ($file in $csvFiles)
{
    (Get-Content $file.PSPath -Encoding UTF8 -Raw) |
    Foreach-Object { $_ -replace "<CopyToOutputDirectory>Always</CopyToOutputDirectory>", "<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>" } |
    Set-Content $file.PSPath -Encoding UTF8 -NoNewline
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM