关于msbuild:如何避免<Compile> 和<EmbeddedResource> 之外的文件更改时Visual Studio 增量构建不运行?

How to avoid that Visual Studio incremental build does not run when files outside <Compile> and <EmbeddedResource> are changed?

我有一个 VS2017 csharp 项目,.csproj 文件如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<Project Sdk="Microsoft.NET.Sdk">

    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
    </PropertyGroup>
 
    <ItemGroup>
        <MyItem Include="file.dat" />
    </ItemGroup>

    <PropertyGroup>
        <PrepareResourcesDependsOn>
            $(PrepareResourcesDependsOn);
            MyCompileTarget
         </PrepareResourcesDependsOn>
        <CoreCompileDependsOn>
            $(CoreCompileDependsOn);
            MyCompileTarget
        </CoreCompileDependsOn>
    </PropertyGroup>

    <Target Name="MyCompileTarget" Inputs="@(MyItem)" Outputs="@(MyItem->'%(FileName).out')">
    ...
    </Target>
 </Project>

其中 MyCompileTarget 是从 file.dat 生成 file.out 的目标(在实际代码中,增量构建目标和属性位于通过 NuGet 包自动包含的目标文件中)。

问题是,如果我更改 file.dat 并按下 Build,则根本不会执行任何目标,(但使用 Rebuild 或使用 msbuild 运行时正确执行了 MyTarget)。我希望执行 MyCompileTarget 以便更新 file.out 文件。

如果我使用 BeforeBuildAfterBuild 而不是 PrepareResourcesDependsOn 等,也会出现同样的问题。

似乎除非更改 @(Compile)@(EmbeddedResource) 中的某些文件,否则 Visual Studio 增量构建将不会启动。确实,如果我添加以下

1
<EmbeddedResource>file.dat</EmbeddedResource>

增量构建按预期工作(但显然我不想将 file.dat 嵌入到生成的程序集中)。

如果修改了 file.dat 并且相应生成的文件早于 file.dat 或者它不存在,是否可以强制 Visual Studio 启用增量构建?

注意:使用 .NET CORE 或 .NET FRAMEWORK 的 VS2015 也会出现同样的问题。
此外,如果我更改 csharp 文件,将触发增量构建,因此它将触发 MyTask,但前提是 file.dat 比生成的文件更新(如预期的那样)。

提前致谢,
法比奥。


Is it possible to force Visual Studio to enable incremental build if file.dat is modified

您可以在项目文件中将属性 DisableFastUpToDateCheck 设置为 true 以禁用 Visual Studio 构建管理器的 FastUpToDateCheck

1
2
3
<PropertyGroup>
    <DisableFastUpToDateCheck>True</DisableFastUpToDateCheck>
</PropertyGroup>

查看 MSDN 关于 DisableFastUpToDateCheck:

A boolean value that applies to Visual Studio only. The Visual Studio
build manager uses a process called FastUpToDateCheck to determine
whether a project must be rebuilt to be up to date. This process is
faster than using MSBuild to determine this. Setting the
DisableFastUpToDateCheck property to true lets you bypass the Visual
Studio build manager and force it to use MSBuild to determine whether
the project is up to date

更新:

此外,我们可以将 UpToDateCheckInput 设置为项目:

1
<UpToDateCheckInput Include="file.dat" />


禁用 VS 快速更新检查将使您的构建速度慢得多。不要这样做!

相反,请确保最新检查了解您项目中的项目以及它们与构建的关系。为此,您可以将两种项目添加到您的项目中:

  • UpToDateCheckInput 用于输入
  • UpToDateCheckBuilt 用于输出

在您的情况下,您需要第二个选项,因为既有输入又有输出。您需要确保如果您删除输出,它会被重建。

1
2
3
<PropertyGroup>
  <UpToDateCheckBuilt Original="@(MyItem)" Include="@(MyItem->'%(FileName).out')">
</PropertyGroup>

有关详细信息,请参阅文档:

https://github.com/dotnet/project-system/blob/main/docs/up-to-date-check.md