构建后事件始终在MSBUILD VS2013中运行

时间:2014-03-20 19:08:37

标签: visual-c++ msbuild visual-studio-2013

这是非常similar to this question,除了问题,除了在修复VS2013之后MSBUILD上存在问题。即使编译器和链接器认为项目是最新的,构建后事件仍在运行。

有关如何阻止构建后事件在此处运行的任何想法?

1>Project "D:\XXX\XXX\XXX\XXX.vcxproj" on node 1 (default targets).

1>InitializeBuildStatus:
  Creating ".\..\XXX\XXX\XXX\XXX.39DEE505.tlog\unsuccessfulbuild" because "AlwaysCreate" was specified.\

ClCompile:
  All outputs are up-to-date.
  All outputs are up-to-date.
ResourceCompile:
  All outputs are up-to-date.
Link:
  All outputs are up-to-date.
  WpnSiteOverlayManager.vcxproj -> D:\XXX\XXX\XXX\XXX\..\bin\Release\XXX.dll
PostBuildEvent:
  "..\..\..\Components\DevTools\Build\BuildCommand.exe" /p "..\..\..\Products" "D:\XXX
  ....
  buildcommand completed successfully
FinalizeBuildStatus:
  Deleting file ".\..\intermediate\release\XXX\XXX.39DEE505.tlog\unsuccessfulbuild".
  Touching ".\..\intermediate\release\XXX\XXX.39DEE505.tlog\XXX.lastbuildstate".
1>Done Building Project "D:\XXX\XXX\XXX\XXX.vcxproj" (default targets).

2 个答案:

答案 0 :(得分:4)

此功能内置于MsBuild for .Net项目(在Microsoft.Common.Targets中搜索PostBuildEvent,另见here),这是一个简化版本。原则是在构建之前获取输出文件的时间戳,在构建之后获取另一个时间戳,然后比较它们。如果它们是相同的,显然没有真正构建的东西。这个逻辑有一个可能的插入点的镜像,在这里我只选择了链接阶段应该做得很好:

<Target Name="GetTimeStampBeforeLink" BeforeTargets="Link">
  <ItemGroup>
    <ProjectOutputFiles Include="$(TargetPath)" />
  </ItemGroup>
  <PropertyGroup>
    <OutputTimeStampBeforeLink>%(ProjectOutputFiles.ModifiedTime)</OutputTimeStampBeforeLink>
  </PropertyGroup>
</Target>

<Target Name="GetTimeStampAfterLink" AfterTargets="Link">
  <PropertyGroup>
    <OutputTimeStampAfterLink>%(ProjectOutputFiles.ModifiedTime)</OutputTimeStampAfterLink>
    <OutputFilesModified Condition="'$(OutputTimeStampBeforeLink)' != '$(OutputTimeStampAfterLink)'">True</OutputFilesModified>
  </PropertyGroup>
</Target>

您可以将此代码直接插入到项目文件中,但更好的方法是将其保存在单独的文件中,以便您可以通过将其导入到任何您想要的位置来重复使用if。您还可以通过添加到ProjectOutputFiles ItemGroup来添加要检查的文件。

现在剩下的就是禁用PostBuildEvent。 MsBuild已经有了一个机制,因为postbuild事件调用是以一个名为PostBuildEventUseInBuild的属性为条件的,因此如果未修改输出文件,我们将其设置为false:

<Target Name="DisablePostBuildEvent" AfterTargets="GetTimeStampAfterLink">
  <PropertyGroup>
    <PostBuildEventUseInBuild Condition='"$(OutputFilesModified)' != 'True'">false</PostBuildEventUseInBuild>
  </PropertyGroup>
</Target>

答案 1 :(得分:3)

stjin的回答稍微简单一点:

<Target Name="DisablePostBuildEvent" AfterTargets="Link" BeforeTargets="PostBuildEvent">
  <PropertyGroup>
    <PostBuildEventUseInBuild Condition="'$(LinkSkippedExecution)' == 'True'">false</PostBuildEventUseInBuild>
  </PropertyGroup>
</Target>

如果链接器实际执行,这只会执行post build事件。