Visual Studio 2012 - MSBuild增量构建未检测到更改

时间:2012-10-30 12:18:28

标签: msbuild visual-studio-2012 incremental-build

我已经定制了一个MSBuild项目,因此默认目标是一个名为“BuildWithExternalReference”的新目标。这个新目标调用另外两个目标;第一个是自定义目标,称为“BuildExternalReference”,它使用外部工具构建DLL。构建的DLL是主项目的引用,它是使用普通的“Build”目标构建的。我已经为'BuildExternalReference'目标设置了Inputs和Outputs属性,因此Inputs引用源文件,输出引用生成的DLL。

在Visual Studio 2012和Visual Studio 2010中,构建在第一次调用时都能正常工作。但是,在后续构建中,如果我更改外部源文件(由“BuildExternalReference”目标输入属性引用),则Visual Studio 2012只会报告“构建:0成功,0失败,1最新,0跳过”。 Visual Studio 2010继续完美运行。此外,使用MSBuild.exe从命令行构建工作非常完美。

我知道Visual Studio 2012中的构建系统已经发生了变化,但我无法找到有关对增量构建执行方式的更改的信息。

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 \ Output.txt文件复制MSBuildIssueExample \ ExternalTool \ Input.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。

但是,如果你进行Rebuild(而不仅仅是Build),那么两个版本的Visual Studio都会按预期工作。

3 个答案:

答案 0 :(得分:11)

Microsoft的反馈回答了这个问题:

&#34;这是由于VS 2012的变化,C#/ VB项目现在进行了快速的最新检查&#34;这允许他们跳过构建,而不是一直强制构建。然而,一个缺点是快速的最新检查没有考虑自定义目标,这就是未检测到增量更改的原因。如果您希望禁用&#34;快速最新检查&#34;请设置&#34; DISABLEFASTUPTODATECHECK&#34;无论是作为项目文件中的MSBuild属性还是作为环境变量,您都可以从中启动VS.&#34;

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

所以基本上这是Visual Studio 2012中的一个重大变化,遗憾的是,它似乎没有很好地记录下来。

答案 1 :(得分:4)

这是一个老问题,但仍然相关。非常感谢你在这里提出它。

我想提供我的研究结果。

您共享的示例显示了在Visual Studio GUI内部构建时和devenv命令行(devenv .\MSBuildIssueExample.sln /build

时的异常行为

但是,如果使用以下内容替换csproj文件:

<强> 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>

然后行为不同!

Visual Studio GUI继续行为不端,但是,使用devenv构建的命令行确实识别输入中的更改!

另请注意,在命令行上运行msbuild而不是devenv在两个版本中都能正常运行。虽然msbuild还有其他问题......

修改

GUI构建有一个解决方案,仅在外部文件数量较少时才适用。您可以将它们作为链接添加到项目中,并确保Build ActionNone。然后它在GUI中工作正常。

虽然,我只检查了Custom.Targets,但我很确定它也适用于原始版本。

答案 2 :(得分:0)

要扩展标记的修改,以及var myArr1 = [ {any: 1, some: 1}, {any: 2, some: 2}, {any: 3, some: 3} ], myArr2 = [ {other: 1}, {other: 2} ], mergedObjectList = myArr1.reduce(function (collector, item_1, idx) { var item_2 = collector[idx], merger = Object.assign({}, item_1, item_2); // or whatever one wants to do to `merger` with `myNewAttribute` collector[idx] = merger; return collector; }, Array.from(myArr2)); console.log("myArr1 : ", myArr1); console.log("myArr2 : ", myArr2); console.log("mergedObjectList : ", mergedObjectList); - 项目对我不起作用,这里是我可以在其他项目中导入的自定义目标文件的示例,将文本文件读入属性(我可以在None属性中使用),并将文本文件标记为DefineConstants目标的输入:

CoreCompile

<?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视为输入。