Visual Studio 2017多目标项目AfterTargets="Build"依赖执行顺序异常
解决多目标项目中AfterTargets="Build"执行顺序不符合预期的问题
首先我先梳理下你提供的依赖项目代码(主项目内容虽有截断,但核心问题聚焦在多目标项目的Build目标执行逻辑上):
依赖项目代码:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netcoreapp2.0;net45</TargetFrameworks> </PropertyGroup> <Target Name="DependencyAfterBuild" AfterTargets="Build"> <Message Text="DependencyAfterBuild IsCrossTargetingBuild=$(IsCrossTargetingBuild)" /> </Target> </Project>
问题根源分析
在多目标(CrossTargeting)项目中,MSBuild的执行逻辑和单目标项目有本质区别:
- 顶层的
Build目标是一个聚合目标,它会遍历所有TargetFrameworks,为每个框架单独执行内部的InnerBuild目标。 - 你当前绑定
AfterTargets="Build"的目标,默认会在所有框架的Build都完成之后只执行一次;但如果你的预期是每个框架Build完成后都执行一次,就会出现执行顺序/次数不符合预期的情况。 - 另外,
IsCrossTargetingBuild属性在顶层Build时为true,而在每个框架的InnerBuild上下文里,这个属性会被设置为false,这也会直接影响目标的触发时机。
针对性解决方案
根据你的实际需求,分两种场景处理:
场景1:希望每个TargetFramework构建完成后都执行目标
把AfterTargets从Build改成InnerBuild,这个目标是每个框架单独构建时的实际完成节点:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netcoreapp2.0;net45</TargetFrameworks> </PropertyGroup> <Target Name="DependencyAfterBuild" AfterTargets="InnerBuild"> <Message Text="DependencyAfterBuild for $(TargetFramework) | IsCrossTargetingBuild=$(IsCrossTargetingBuild)" /> </Target> </Project>
修改后,netcoreapp2.0构建完成后会执行一次,net45构建完成后又会执行一次,完全贴合多目标项目的逐个构建流程。
场景2:希望所有TargetFramework都构建完成后只执行一次目标
如果你的需求是所有框架都构建完毕后统一执行,那可以保留AfterTargets="Build",但添加条件确保只在顶层聚合Build时触发:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>netcoreapp2.0;net45</TargetFrameworks> </PropertyGroup> <Target Name="DependencyAfterBuild" AfterTargets="Build" Condition="'$(IsCrossTargetingBuild)' == 'true'"> <Message Text="DependencyAfterBuild (All frameworks completed) | IsCrossTargetingBuild=$(IsCrossTargetingBuild)" /> </Target> </Project>
这个条件会过滤掉每个框架InnerBuild时的触发请求,只在顶层聚合Build完成后执行一次。
额外注意点
如果主项目也是多目标项目,要确保主项目对依赖项目的引用是框架匹配的(即主项目的每个TargetFramework会引用依赖项目对应框架的输出),这样主项目的构建流程才会正确触发依赖项目对应框架的InnerBuild,进而保证你的目标按预期执行。
内容的提问来源于stack exchange,提问作者Roman G.
相关产品推荐
相关产品推荐

