MSBuild 17:项目文件中属性与项的作用域及跨目标生效疑问
关于MSBuild属性与项组作用域的疑问
我对MSBuild项目中的属性作用域存在疑惑,原本认为在Target外声明的属性在项目文件中是全局的,为此编写了如下测试代码:
<PropertyGroup> <TestProp>Unassigned</TestProp> </PropertyGroup> <ItemGroup> <TestEnvironments Include="Development;UAT;Production" /> </ItemGroup> <Target Name="TestScope"> <PropertyGroup> <TestProp>Some test data</TestProp> </PropertyGroup> <Message Text="Test property scope $(TestProp)" /> <CallTarget Targets="ForEachTestScope" /> </Target> <Target Name="ForEachTestScope" Inputs="@(TestEnvironments)" Outputs="%(Identity).done"> <Message Text="Test property scope $(TestProp)" /> <Message Text="Selected environment: @(TestEnvironments)" /> </Target>
执行TestScope目标后,输出结果如下:
TestScope: Test property scope Some test data ForEachTestScope: Test property scope Unassigned Selected environment: Development ForEachTestScope: Test property scope Unassigned Selected environment: UAT ForEachTestScope: Test property scope Unassigned Selected environment: Production
我原本预期被调用的ForEachTestScope目标中$(TestProp)的值为TestScope内设置的Some test data,但实际却是初始值Unassigned。请问:在Target内局部声明的PropertyGroup(或ItemGroup)的作用域是否始终仅限于所在Target?
回答
在MSBuild中,Target内部声明的PropertyGroup或ItemGroup的作用域默认仅限于当前Target的执行上下文,不会自动传递给通过CallTarget调用的其他目标。
原因是每个Target的执行都拥有独立的属性/项上下文:当你在TestScope内修改TestProp时,这个修改只在TestScope的执行过程中有效;当通过CallTarget触发ForEachTestScope时,新的目标会使用项目全局层面的属性初始值(也就是你在Target外声明的Unassigned),不会继承调用方Target内的局部修改。
如果需要在目标间传递属性值,可以通过以下方式实现:
- 使用
CallTarget的PropertiesToPass参数显式指定要传递的属性,修改TestScope中的调用代码:<CallTarget Targets="ForEachTestScope" PropertiesToPass="TestProp" /> - 将属性修改为全局级别的(即不要在Target内声明PropertyGroup,而是直接在Target外修改,但这种方式会影响后续所有目标的执行,需谨慎使用)
- 对于项(ItemGroup),可以通过元数据或显式传递项集合的方式共享
内容的提问来源于stack exchange,提问作者endurium
相关产品推荐
相关产品推荐

