问题描述
这与该问题非常类似,除了除了我在VS2013修复它之后,MSBUILD上存在该问题以外的其他问题.即使编译器和链接器认为项目是最新的,构建后事件也正在运行.
This is very similar to this question, except for the problem except the problem exists on MSBUILD after I fix it for VS2013. The post-build event is running even though the compiler and linker think the project is up-to-date.
是否有任何关于如何防止构建后事件在此处运行的想法?
Any thoughts on how to prevent the post-build event from running here?
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).
推荐答案
此功能内置在MsBuild for .Net项目中(在Microsoft.Common.Targets中搜索PostBuildEvent,另请参见),这是简化版本.原理是在构建之前获得输出文件的时间戳,在构建之后获得另一个时间戳,然后对其进行比较.如果它们相同,则显然没有真正构建任何东西.这个逻辑有很多可能的插入点,在这里我刚刚选择了链接阶段,应该做得很好:
This functionality is built-in in MsBuild for .Net projects (search for PostBuildEvent in Microsoft.Common.Targets, also see here), here is a simplified version. The principle is you get a timestamp of your output file(s) before the build, and another one after the build, then compare them. If they are the same, obviously nothing was really built. There's a miriad of possible insertion points for this logic, here I just picked the link stage which should do just fine:
<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>
您可以将此代码直接插入到您的项目文件中,但是更好的主意是将其保存在单独的文件中,以便通过将其导入到任何其他位置来将其重用于其他项目.您也可以通过添加到ProjectOutputFiles
ItemGroup中来添加要检查的文件.
You can insert this code right into your projectfile, but a better idea is to save it in a seperate file so you can reuse if for other projects by importing it wherever you want it. Also you can add files to check by adding to the ProjectOutputFiles
ItemGroup.
现在剩下的就是禁用PostBuildEvent. MsBuild已经有了一种机制,因为构建后事件的调用取决于名为PostBuildEventUseInBuild
的属性,因此如果未修改输出文件,则将其设置为false:
Now all is left is disabling the PostBuildEvent. MsBuild already has a mechanism for that since postbuild event invokation is conditional on a propery named PostBuildEventUseInBuild
, so we set this to false if output files are not modified:
<Target Name="DisablePostBuildEvent" AfterTargets="GetTimeStampAfterLink">
<PropertyGroup>
<PostBuildEventUseInBuild Condition='"$(OutputFilesModified)' != 'True'">false</PostBuildEventUseInBuild>
</PropertyGroup>
</Target>
这篇关于生成后事件始终在MSBUILD VS2013中运行的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!