Visual Studio 2012 - MSBuild incremental build not detecting changes

℡╲_俬逩灬. 提交于 2019-11-27 23:36:10

This feedback from Microsoft answers the question:

"This is due to a change in VS 2012 where C#/VB projects now do a "fast up-to-date check" that allows them to skip the build, rather than forcing the build all the time. One downside, however, is that fast up-to-date check does not take into account custom targets, which is why your incremental change was not detected. If you wish to disable the "fast up-to-date check" please set "DISABLEFASTUPTODATECHECK" to true either as an MSBuild property in the project file or as an environment variable in the environment you launch VS from."

http://connect.microsoft.com/VisualStudio/feedback/details/770784/visual-studio-2012-msbuild-incremental-build-not-detecting-changes#details

So basically this is a breaking change in Visual Studio 2012 that unfortunately does not seem to be documented very well.

This is an old issue, but still relevant. Thank you very much for raising it here.

I would like to provide the results of my research.

The example you share shows the abnormal behavior both when built inside the Visual Studio GUI and by the devenv command line (devenv .\MSBuildIssueExample.sln /build)

However, if you replace your csproj file with the following:

MSBuildIssueExample.csproj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
    <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
    <ProductVersion>8.0.30703</ProductVersion>
    <SchemaVersion>2.0</SchemaVersion>
    <ProjectGuid>{4EA8847D-262C-4937-8536-E526E9BAB1C7}</ProjectGuid>
    <OutputType>Library</OutputType>
    <AppDesignerFolder>Properties</AppDesignerFolder>
    <RootNamespace>MSBuildIssueExample</RootNamespace>
    <AssemblyName>MSBuildIssueExample</AssemblyName>
    <TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
    <FileAlignment>512</FileAlignment>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\Release\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
  </PropertyGroup>
  <ItemGroup>
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="System.Xml.Linq" />
    <Reference Include="System.Data.DataSetExtensions" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Data" />
    <Reference Include="System.Xml" />
  </ItemGroup>
  <ItemGroup>
    <Compile Include="Class1.cs" />
    <Compile Include="Properties\AssemblyInfo.cs" />
  </ItemGroup>
  <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
  <Import Project="Custom.Targets" />
</Project>

Custom.Targets

<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <CompileDependsOn>ExternalTool;$(CompileDependsOn)</CompileDependsOn>
    <CleanDependsOn>CleanOutput;$(CleanDependsOn)</CleanDependsOn>
  </PropertyGroup>
  <ItemGroup>
    <ExternalToolInputs Include="ExternalTool\Input.txt">
      <InProject>false</InProject>
    </ExternalToolInputs>
    <ExternalToolOutputs Include="ExternalTool\Output.txt">
      <InProject>false</InProject>
    </ExternalToolOutputs>
  </ItemGroup>
  <Target Name="ExternalTool" Inputs="@(ExternalToolInputs)" Outputs="@(ExternalToolOutputs)">
    <Message Text="ExternalTool target start, copying input file over output..." />
    <Copy SourceFiles="@(ExternalToolInputs)" DestinationFiles="@(ExternalToolOutputs)" />
    <Message Text="ExternalTool target end, copy successful" />
  </Target>
  <Target Name="CleanOutput">
    <Delete Files="@(ExternalToolOutputs)" ContinueOnError="true" />
  </Target>
</Project>

Then the behavior is different !

Visual Studio GUI continues to misbehave, however, the command line build with devenv does recognize the change in the input!

Also note, that running msbuild on the command line instead of devenv works correctly in both versions. Although msbuild has other problems ...

EDIT

There is a solution for the GUI build, which is only applicable when the amount of external files is small. You add them to the project as links and make sure the Build Action is None. Then it works fine in the GUI.

Although, I have only checked with the Custom.Targets, but I am pretty sure it is going to work with the original version as well.

To expand on mark's Edit, and since None-items didn't work for me, here's an example of a custom targets file that I can import in other projects, that reads a text file into a property (which I can then use in the DefineConstants property), and that will mark the text file as input for the CoreCompile target:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <PropertyGroup>
    <CommonDefines>$([System.IO.File]::ReadAllText('$(SolutionDir)\_meta\definesFlags.txt'));$(CommonDefines)</CommonDefines>
  </PropertyGroup>

  <ItemGroup>
    <CustomAdditionalCompileInputs Include="$(SolutionDir)\_meta\definesFlags.txt" />
  </ItemGroup>

</Project>

CustomAdditionalCompileInputs-items is taken as an input by Microsoft.Csharp.Core.targets.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!