在没有构建csproj时抑制AfterBuild目标

我在MSBuild中有一个后期构建目标来复制一些构建输出。

它作为依赖于AfterBuild目标(由Microsoft.CSharp.targets公开)链接:

  

如果构建实际上没有重新构建,有没有办法避免文件被复制?

例如,当MSBuild依赖关系分析声明项目不需要构建因为它的源文件都没有更新时,它不会构建,但仍然执行我的复制目标。 有什么办法可以防止这种情况吗?

由于您要覆盖AfterBuild目标,因此它将始终在构建发生后执行。 这是重建或正常构建的情况。 如果要在重建(而不是构建)之后执行某些操作,则应扩展Rebuild目标的依赖项属性。 因此,在重建发生后注入目标的情况下,您的项目文件应如下所示:

      $(RebuildDependsOn); InstallUtil; CopyPostBuildFiles    

此方法扩展了Rebuild目标用于声明其所依赖的目标的属性。 我在文章Inside MSBuild中对此进行了详细介绍,请参阅扩展构建过程一节。

如果您可以指定哪些文件将“ 触发 ”更新发生,那么AfterBuild目标可能会实现您要完成的任务。 换句话说,您可以在目标中指定一组“输入”,并将一组“输出”指定为两个文件。 如果所有输出都是在所有输入之后创建的,那么目标将被认为是最新的并且被跳过。 这个概念被称为增量构建,我在文章MSBuild最佳实践第2部分中介绍了它。 此外,我在我的书“Microsoft Build Engine内部:使用MSBuild和Team Foundation Build”中详细说明了这一点。

编辑:添加BuildDependsOn示例

如果希望目标仅在实际构建文件时执行,而不是仅在执行重建目标时执行。 然后,您应该创建您的项目,如下所示:

      $(BuildDependsOn); CustomAfterBuild;       

我只是复制了Microsoft.CSharp.targets中的CoreCompile目标的输入和输出( 我假设您在这里使用C# )并将其粘贴到此处。 这意味着只要执行CoreCompile目标,就会跳过目标。 此外,由于我扩展了BuildDependsOn,我们知道无论何时构建项目,MSBuild都会尝试执行它。

我只是用谷歌搜索了这个,并找到了这个岁月的答案。 通过从核心目标中窃取一个创意,我找到了一种更容易实现的方法。 覆盖BeforeBuild和AfterBuild,并执行以下操作:

    %(IntermediateAssembly.ModifiedTime)       

如何在编译目标中使用输入和输出目标的属性呢?

  CopiedFilesDirectory      

您可以在CopyPostBuildFilesInstallUtil上使用它,也可以直接在AfterBuild上使用

有关目标输入输出的更多信息,请参阅此页面

构建目标定义是:

  

我认为如果你的文件没有改变就不会执行CoreBuild,所以你可以尝试使用AfterCompile而不是AfterBuild。

  

那这个呢。

  • BuildBreak 。 发生编译错误时设置为true,否则设置为false。 可以在构建中断目标中使用,以确定它们是在编译错误之后执行还是正常执行。

http://blogs.msdn.com/aaronhallberg/archive/2008/02/12/team-build-2008-property-reference.aspx

我没试过,但听起来很有希望。

当且仅当重建了项目目标文件时,这将调用AfterBuild目标:

  

这假定您已定义了一个属性$(DeployPath) ,用于标识复制目标输出文件的文件夹。

我对MSBuild知之甚少,但对于Visual Studio for C#使用的MSBuild项目,有一个简单的替代方法:使用Post-build构建事件而不是AfterBuild目标。

您可以通过Visual Studio项目属性对话框在第三个“构建事件”选项卡上设置构建后构建事件。 在某些情况下,可能需要在此对话框中输入一些命令,然后在确定其工作原理后直接编辑.csproj文件。

请记住在对话框中选择“运行此构建后事件:构建更新项目输出时” – 这是获取OP请求的function的关键。

就像我说的,我对MSBuild知之甚少,可能是Post-build构建事件不适用于AfterBuild目标可以做的一些事情。 但我用它来复制文件和运行BAT脚本,为此它工作正常。

编辑:

我将添加一些关于我如何在C#项目中使用post-build事件的注释。

为了分隔不同的function区域,我通常会创建一个名为PostBuildEvent.bat的BAT脚本,并将其放在与.csproj文件相同的文件夹中。 然后我的post-build事件只包含两行:

 cd $(ProjectDir) PostBuildEvent.bat 

然后我将我想要的命令放在PostBuildEvent.bat文件中。 这是一个例子:

 copy "..\..\..\..\..\Shared Bin\Merlinia.CommonClasses.NamedPipesNative.dll" bin copy "..\..\..\..\..\Shared Bin\Merlinia.CommonClasses.NamedPipesNative.pdb" bin cd Packed-NonObfuscated call PackForWindowsSystem32-NonObfuscated.bat cd ..\ cd Packed-Obfuscated call PackForWindowsSystem32-Obfuscated.bat cd ..\ pause 

请记住,要从BAT脚本调用BAT脚本,请明确指定“call”。 另请注意使用“暂停” – 这样可以通过双击BAT文件来测试脚本,然后您可以在cmd窗口中看到任何错误消息。 当脚本通过MSBuild运行时,将忽略“暂停”。