问题
I have a simple Word to Pdf converter as an MSBuild Task. The task takes Word files (ITaskItems) as input and Pdf files (ITaskItems) as output. The script uses a Target transform for conversion:
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="3.5">
<UsingTask AssemblyFile="$(MSBuildExtensionsPath)\MyTasks.dll" TaskName="MyTasks.DocToPdf" />
<Target Name="Build" DependsOnTargets="Convert" />
<Target Name="Convert"
Inputs="@(WordDocuments)"
Outputs="@(WordDocuments->'%(FileName).pdf')">
<DocToPdf Inputs="@(WordDocuments)"
Outputs="%(FileName).pdf">
<Output TaskParameter="ConvertedFiles" ItemName="PdfDocuments" />
</DocToPdf>
</Target>
<ItemGroup>
<WordDocuments Include="One.doc" />
<WordDocuments Include="SubDir\Two.doc" />
<WordDocuments Include="**\*.doc" />
</ItemGroup>
</Project>
What's happening is that SubDir\Two.doc gets converted on every incremental build, One.doc does not (ie MSBuild correctly skips that file because it was already converted). If I use the recursive items spec (the third one above), I get the same behaviour (ie. One.doc only gets converted if the PDF is out of date or missing, but all documents in subdirectories always get converted regardless).
What am I doing wrong here?
回答1:
I found the problem. It turns out that I had some logic in the Task that would turn any relative path specified for a PDF file into an absolute path. Once I removed that and changed the script to this:
<Target Name="Convert"
Inputs="@(WordDocuments)"
Outputs="@(WordDocuments->'%(RelativeDir)%(FileName).pdf')">
<DocToPdf Inputs="%(WordDocuments.Identity)"
Outputs="%(RelativeDir)%(FileName).pdf">
<Output TaskParameter="ConvertedFiles" ItemName="PdfDocuments" />
</DocToPdf>
</Target>
I got the behaviour I expected.
回答2:
Here's my example of a task that performs incremental builds on items found recursively through subdirectories:
<Target Name="Build" Inputs="@(RequestTextFiles)" Outputs="@(RequestTextFiles -> '%(Rootdir)%(Directory)%(Filename).out')">
<DoSomething SourceFiles="@(RequestTextFiles)" />
</Target>
This maps 1:1 with an input file, and an output file with the same name, that outputs to the same path with a different extension, namely 'out' in this case.
来源:https://stackoverflow.com/questions/187974/msbuild-task-items-in-subdirectories-are-incremental-builds-not-possible-on-the