多框架目标时$(TargetFramework)属性为空,如何实现框架特定操作?
解决多目标框架下
$(TargetFramework)为空的问题 当使用<TargetFrameworks>(复数)设置多框架目标时,MSBuild会分两个阶段处理:
- 全局评估阶段:顶层的
<PropertyGroup>和<ItemGroup>会先执行,此时还未进入单个框架的构建流程,$(TargetFramework)属性为空。 - 子构建阶段:为每个目标框架单独启动构建实例,此时
$(TargetFramework)会被设置为当前框架版本(如net5.0)。
你的问题就出在:顶层的Target和ItemGroup是在全局阶段执行的,自然拿不到框架值。下面分两种场景给出解决方案:
一、让Target在每个框架构建时执行
给Target添加Condition="'$(TargetFramework)' != ''",确保它只在子构建阶段(有框架值时)运行,同时保留AfterTargets="Build"保证在每个框架的构建完成后触发:
<Target Name="DoSomethingFrameworkSpecific" AfterTargets="Build" Condition="'$(TargetFramework)' != ''"> <Message Text="当前构建框架:$(TargetFramework)" Importance="High" /> </Target>
这样每个框架的构建完成后,都会输出对应的框架版本,而全局阶段因条件不满足不会执行这个Target。
二、实现框架特定的PackagePath
不能在顶层<ItemGroup>中直接使用$(TargetFramework),需要把项的定义放到子构建阶段执行的Target中,确保元数据在有框架值的上下文里被评估:
<Target Name="AddFrameworkSpecificPackItems" BeforeTargets="PrepareForPack" Condition="'$(TargetFramework)' != ''"> <ItemGroup> <None Include="MyProject.targets"> <Pack>True</Pack> <PackagePath>build\$(TargetFramework)</PackagePath> </None> </ItemGroup> </Target>
这里选择BeforeTargets="PrepareForPack",确保在打包前为当前框架添加对应的项,这样文件就会被放到build\net5.0、build\net6.0等框架特定路径下。
完整示例代码
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFrameworks>net5.0;net6.0;net7.0</TargetFrameworks> </PropertyGroup> <Target Name="DoSomethingFrameworkSpecific" AfterTargets="Build" Condition="'$(TargetFramework)' != ''"> <Message Text="当前构建框架:$(TargetFramework)" Importance="High" /> </Target> <Target Name="AddFrameworkSpecificPackItems" BeforeTargets="PrepareForPack" Condition="'$(TargetFramework)' != ''"> <ItemGroup> <None Include="MyProject.targets"> <Pack>True</Pack> <PackagePath>build\$(TargetFramework)</PackagePath> </None> </ItemGroup> </Target> </Project>
内容的提问来源于stack exchange,提问作者Ted Nyberg
相关产品推荐
相关产品推荐

