Search code examples
visual-studiomsbuildcsproj

MSBuild: Project not built when input file changed


In my project's .csproj file (using Visual Studio) I defined a Target with Inputs and Outputs attributes, specifying a transform on the Outputs. The Target simply copies each input file into a folder called dist:

<ItemGroup>
  <SourceFiles Include="**\*.src" />
</ItemGroup>

<Target
    Name="SourceFileTransform"
    BeforeTargets="BeforeBuild"
    Inputs="@(SourceFiles)"
    Outputs="@(SourceFiles -> '$(MSBuildProjectDirectory)\dist\%(Filename)%(Extension)')">
  <Copy SourceFiles="@(SourceFiles)" DestinationFolder="$(MSBuildProjectDirectory)\dist" />
</Target>

With this I'm expecting that due to incremental building my project should be built when any one of the input files had been changed, that is, when the input file's timestamp is later than its mapped output file.

In testing this, I delete the dist folder, perform "Clean Solution", and build the solution. As expected, the project is built, and my source.src file (in the project's folder) is copied into a new dist folder.

When I build again, the project doesn't build, as I get the following output from "Build":

Build started...
========== Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========
========== Build started at 10:48 AM and took 00,312 seconds ==========

All good. Now I edit my source.src file and do another build. However, I get the same build output ("0 succeeded, 0 failed, 1 up-to-date"). The project isn't built and the dist\source.src file isn't updated.

This doesn't make sense: source.src now has a later timestamp than dist\source.src, so since the transform specified in Outputs=... maps the source.src file to dist\source.src this should cause the project to be built.

What am I missing here?


Solution

  • It turns out deciding whether or not to build a project is a mechanism built into Visual Studio and is not done by MSBuild. Furthermore, it appears that in doing so Visual Studio does not take into account changes in the input files of targets.

    As pointed out by @Hans Passant disabling the "Up to Date Checks" option (Tools > Options > Projects and Solutions > SDK-Style projects > "Up to Date Checks") overcomes this issue at the cost of building all projects all the time.