我已经自定义了一个MSBuild项目,使默认目标成为一个名为“BuildWithExternalReference”类似的新目标。这个新目标调用了另外两个目标;第一个是一个自定义目标,类似于“BuildExternalReference”,它使用一个外部工具构建DLL。生成的DLL是主项目的引用,主项目使用正常的“Build”目标进行构建。我为“BuildExternalReference”目标设置了Inputs和Outputs属性,因此输入引用源文件,输出引用生成的DLL。
在Visual Studio 2012和Visual Studio 2010中,第一次调用构建时都能正常工作。但是,在以后的构建中,如果我更改了外部源文件(由“BuildExternalReference”目标的Inputs属性引用),则Visual Studio 2012仅报告“Build: 0 succeeded, 0 failed, 1 up-to-date, 0 skipped”。而Visual Studio 2010仍然完美地工作。此外,使用MSBuild.exe从命令行构建也可以正常工作。
我知道Visual Studio 2012中的构建系统已经发生了变化,但我找不到有关增量构建方式变化的信息。
在这里是我正在使用的csproj文件的缩减版本:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="BuildWithExternalTool" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ExternalSourceFiles Include="..\ExternalSourceFiles\\*\*.cs" />
<ExternalDll Include="..\ExternalSource\External.dll" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<Target Name="BuildExternalTool" Inputs="@(ExternalSourceFiles);" Outputs="@(ExternalDll)">
<Exec Command="C:\External\Path\To\Tool.exe" />
</Target>
<Target Name="BuildWithExternalTool">
<CallTarget Targets="BuildExternalTool" />
<CallTarget Targets="Build" />
</Target>
</Project>
2012年11月1日更新
以下是一个完整的自包含示例,可复现此问题:
https://skydrive.live.com/redir?resid=EA1DD6ACA92F9EFF!155&authkey=!ANhuqF_rrCgxpLE
这是一个包含一个项目的解决方案。MSBuildIssueExample\MSBuildIssueExample.csproj文件已经被定制,因此存在一个自定义默认目标。该默认目标调用一个自定义目标(称为“ExternalTool”),然后调用默认的Build目标。
自定义的ExternalTool目标会输出一些消息以确保其正常工作,并将MSBuildIssueExample\ExternalTool\Input.txt文件的内容复制到MSBuildIssueExample\ExternalTool\Output.txt文件中。
Input.txt文件是ExternalTool目标的输入,Output.txt是输出。
要重现此问题,请按照以下步骤进行:
1)在指定版本的Visual Studio中打开解决方案
2)首先构建解决方案以确保输出与输入保持最新
3)修改MSBuildIssueExample\ExternalTool\Input.txt,使其内容与Output.txt不匹配
4)再次构建
当您在Visual Studio 2010中执行此过程时,将再次调用ExternalTool目标,并将Input.txt文件复制到Output.txt。
当您在Visual Studio 2012中执行此过程时,即使输入比输出更新,也不会调用ExternalTool目标,因此Input.txt的内容不会被写入Output.txt。
但是,如果您执行重新生成(而不仅仅是构建),则两个版本的Visual Studio都按预期工作。