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

7

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

<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增量构建才会启动。确实,如果我添加以下内容

<EmbeddedResource>file.dat</EmbeddedResource>

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

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

注意:使用 .NET CORE 或者 .NET FRAMEWORK 的 VS2015 也会出现同样的问题。另外,如果我改变了一个 csharp 文件,增量构建将会被触发,因此触发 MyTask,但只有在 file.dat 比生成文件新时才会如预期那样工作。

谢谢, Fabio.


如果你使用详细输出运行它,它是否会说明目标被跳过的原因?可能有帮助的是,在你的目标中添加一个记录到文件跟踪机制的记录,类似于 <WriteLinesToFile File="$(TLogLocation)$(ProjectName).write.u.tlog" Lines="@(MyItem->'%(FileName).out"/> - stijn
谢谢您的回复。我尝试了您的解决方案,但仍然没有起作用。当我更改源文件时,它仍然无法重新编译,除非我删除输出文件。是否有一种方法可以将文件插入到某个列表中,以便Visual Studio中的“快速更新”可以捕捉到源文件和输出文件之间的差异? - Fabio Strocco
2个回答

9
可以强制Visual Studio在修改file.dat时启用增量编译吗?
您可以在项目文件中将属性“DisableFastUpToDateCheck”设置为“true”,以禁用Visual Studio构建管理器的“FastUpToDateCheck”。
<PropertyGroup>
    <DisableFastUpToDateCheck>True</DisableFastUpToDateCheck>
</PropertyGroup>

请查看MSDN中有关于DisableFastUpToDateCheck的内容:

这是一个布尔值,仅适用于Visual Studio。 Visual Studio构建管理器使用称为FastUpToDateCheck的过程来确定项目是否必须重新构建以保持最新状态。此过程比使用MSBuild来确定更快。将DisableFastUpToDateCheck属性设置为true可让您绕过Visual Studio构建管理器并强制其使用MSBuild来确定项目是否最新。

更新:

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

<UpToDateCheckInput Include="file.dat" />

非常感谢您的回复 :) 有没有办法在不禁用快速更新检查的情况下完成这项工作?我尝试使用 <UpToDateCheckInput Include="file.dat" />,但它不起作用。 - Fabio Strocco
问题在于出于性能原因,我需要启用快速的最新检查,而上述解决方案(UpToDateCheckInput)不起作用,至少当项目项位于.target文件中时不起作用,该文件通过NuGet包引用自动包含在VS2017项目中。 - Fabio Strocco
我的错,我把项目组放错了位置。 <UpToDateCheckInput Include="file.dat" /> 解决了这个问题,同时保持了快速更新检查的功能,所以我建议您在回答中包含它,这样我就可以关闭这个主题了。 - Fabio Strocco
我想把所有这些内容放入NuGet目标文件中的原因是,我想将编译器作为NuGet软件包分发,它会在构建时自动触发编译,而不需要NuGet软件包用户除了将MyItem 包含在其.csproj文件中之外再添加其他东西。 - Fabio Strocco
你永远不应该禁用最新版本检查。这是错误的建议,我建议删除或编辑此答案。人们会将该属性复制/粘贴到他们的项目中,并遭受缓慢构建的痛苦。 - Drew Noakes
显示剩余2条评论

2
禁用VS快速更新检查会使您的构建速度变慢。不要这样做!
相反,确保最新检查知道项目中的项目以及它们与构建的关系。对此,您可以向项目添加两种类型的项目:
- UpToDateCheckInput 用于输入 - UpToDateCheckBuilt 用于输出
在您的情况下,您需要第二个选项,因为存在输入和输出。您需要确保如果删除输出,则重新构建它。
<PropertyGroup>
  <UpToDateCheckBuilt Original="@(MyItem)" Include="@(MyItem->'%(FileName).out')">
</PropertyGroup>

更多信息请参见文档:

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

这是关于it技术的内容,如果需要了解更多信息,请查看上述链接中的文档。

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