I've modified a .csproj project to append a task to BuildDependsOn. This performs a file copy. If the file copy fails, the build fails. (see XML below).
However, if I then 'build' again after a failed build attempt (in Visual Studio) Visual Studio reports that the project built successfully. It believes the project to be up to date
.
========== Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped ==========
How do I ensure that this CopyFiles target runs on every build, to prevent this problem of VS reporting a successful build when a key stage in the build failed?
<ItemGroup>
<MySourceFiles Include="$(TargetDir)*.dll;$(TargetDir)*.pdb"/>
</ItemGroup>
<Target Name="CopyFiles">
<Copy SourceFiles="@(MySourceFiles)" DestinationFolder="$(DestFolder)\subfolder" />
<Copy SourceFiles="$(ProjectDir)AnotherFile.txt" DestinationFolder="$(DestFolder)" />
<OnError ExecuteTargets="CopyFiles_Failed" />
</Target>
<Target Name="CopyFiles_Failed">
<Error text="File copies failed">
</Error>
</Target>
<PropertyGroup>
<BuildDependsOn>
$(BuildDependsOn);
CopyFiles
</BuildDependsOn>
</PropertyGroup>
As @maxkenir mentions, the Inputs and Output parameter in a target define the set of files the build should check to decide whether it is up to date.
Inputs
The files that form inputs into this target. Multiple files are separated by semicolons. The timestamps of the files will be compared with the timestamps of files in Outputs to determine whether the Target is up to date. For more information, see Incremental Builds, How to: Build Incrementally, and MSBuild Transforms.
Outputs
The files that form outputs into this target. Multiple files are separated by semicolons. The timestamps of the files will be compared with the timestamps of files in Inputs to determine whether the Target is up to date. For more information, see Incremental Builds, How to: Build Incrementally, and MSBuild Transforms.
And the process to use them is further explained in the article on Incremental Builds.
Basically it looks like thsi for a simple copy files action:
<Target Name="Backup" Inputs="@(files)"
Outputs="@(Compile->'$(BackupFolder)%(Identity).bak')">
<Copy SourceFiles="@(Compile)" DestinationFiles=
"@(Compile->'$(BackupFolder)%(Identity).bak')" />
</Target>
More information on these MsBuild transforms can be found again on MSDN, in your case it will probably be very close to:
<Target Name="CopyOutputs"
Inputs="@(BuiltAssemblies)"
Outputs="@(BuiltAssemblies -> '$(OutputPath)%(Filename)%(Extension)')">
<Copy
SourceFiles="@(BuiltAssemblies)"
DestinationFolder="$(OutputPath)"/>
</Target>
But Inputs and Outputs will also accept an Item Group and you can have multiple transforms as well.