如此摆弄MSBuild任务,我发现Regex元数据属性只被评估一次而不是每个项目。
例如
<!--
actual items, we use standard project reference items and extend via
ItemDefinitionGroup. add project references through IDE to extend
coverage
-->
<ItemGroup>
<ProjectReference Include="..\Example.UnitTests-x86\Example.UnitTests-x86.csproj">
<Project>{7e854803-007c-4800-80f9-be908655229d}</Project>
<Name>Example.UnitTests-x86</Name>
</ProjectReference>
<ProjectReference Include="..\Example.UnitTests\Example.UnitTests.csproj">
<Project>{eaac5f22-bfb8-4df7-a711-126907831a0f}</Project>
<Name>Example.UnitTests</Name>
</ProjectReference>
</ItemGroup>
<!-- additional item properties, defined with respect to item declaring it -->
<ItemDefinitionGroup>
<ProjectReference>
<Isx86>
$([System.Text.RegularExpressions.Regex]::IsMatch(%(Filename), '.*x86*'))
</Isx86>
</ProjectReference>
</ItemDefinitionGroup>
<!-- additional task target, invoke both x64 and x86 tasks here -->
<Target Name="AdditionalTasks">
<Message
Text="%(ProjectReference.Filename) Isx86 '%(Isx86)' Inline
'$([System.Text.RegularExpressions.Regex]::IsMatch(%(Filename), '.*x86*'))'"
Importance="high" />
</Target>
生成此输出
Example.UnitTests-x86 Isx86 'False' Inline 'True'
Example.UnitTests Isx86 'False' Inline 'False'
答案 0 :(得分:4)
文档ItemDefinitionGroup Element (MSBuild)引用Item Definitions,其中有一条注明:
ItemGroup中的项元数据在ItemDefinitionGroup元数据声明中没有用,因为ItemDefinitionGroup元素在ItemGroup元素之前处理。
这意味着无法展开%(Filename)
中的<ItemDefinitionGroup/>
元数据参考。您可以使用以下代码片段自行查看。在代码段中,.ToString()
调用将结果转换为字符串对象,从而阻止MSBuild进一步扩展它。 (如果我离开了.ToString()
,MSBuild将留下一个System.RegularExpressions.Match
对象。将元数据定义保留为Match
对象似乎会将扩展延迟到字符串,直到{{1}评估<Message/>
,导致MSBuild对其进行字符串扩展传递,导致Text
在您可能不期望的情况下进行扩展。此延迟扩展也在以下代码段中得到证明。)
%(Identity)
输出:
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<MyItem Include="MyItem’s value" />
<MyItem Include="MyItem’s second value" />
</ItemGroup>
<ItemDefinitionGroup>
<MyItem>
<ItemDefinitionMatchedText>$([System.Text.RegularExpressions.Regex]::Match(%(Identity), ".*").get_Groups().get_Item(0).ToString())</ItemDefinitionMatchedText>
<ItemDefinitionMatchedTextDelayed>$([System.Text.RegularExpressions.Regex]::Match(%(Identity), ".*").get_Groups().get_Item(0))</ItemDefinitionMatchedTextDelayed>
</MyItem>
</ItemDefinitionGroup>
<Target Name="Build" Outputs="%(MyItem.Identity)">
<Message Text="Data being matched against for item “%(MyItem.Identity)” is “%(ItemDefinitionMatchedText)”"/>
<Message Text="Delayed string conversion causes delayed expansion: “%(MyItem.ItemDefinitionMatchedTextDelayed)”"/>
</Target>
</Project>
MSBuild文档中的注释表明Build:
Data being matched against for item “MyItem’s value” is “%(Identity)”
Delayed string conversion causes delayed expansion: “MyItem’s value”
Build:
Data being matched against for item “MyItem’s second value” is “%(Identity)”
Delayed string conversion causes delayed expansion: “MyItem’s second value”
中没有项元数据。从使用<ItemDefinitionGroup/>
开始,property function expansion正在处理Regex.Match()
,或者在您的情况下,%(Identity)
作为未加引号的自由格式字符串。因此,由于您使用与我在上面的示例中调用%(Filename)
相同的语法调用Regex.IsMatch()
,因此您的Regex.Match()
正在尝试检查文字字符串Regex.IsMatch()
是否包含%(Filename)
(可选地后跟任意数量的6,其存在或不存在不会影响匹配)。
我知道根据现有元数据动态计算Item元数据的唯一方法是创建一个从原始项派生的新Item。例如,要创建包含所需元数据的x8
列表,可以使用以下项定义来生成<ProjectReference/>
项。在使用property function syntax将[MSBuild]::ValueOrDefault()
转换为属性扩展上下文中的字符串后,我选择使用that you can dynamically update an Item’s metadata if you do so in a <Target/>
以便我可以使用ProjectReferenceWithArch
(正则表达式对您的情况有点矫枉过正,但您可以轻松如果需要,修改它以匹配正则表达式)。我更新了您的String.Contains()
以打印出<Message/>
元数据,以证明此元数据可以保留在新商品的定义中。
Project
输出:
<ItemGroup>
<ProjectReferenceWithArch Include="@(ProjectReference)">
<Isx86>$([MSBuild]::ValueOrDefault('%(Filename)', '').Contains('x86'))</Isx86>
</ProjectReferenceWithArch>
</ItemGroup>
<Target Name="AdditionalTasks">
<Message
Text="%(ProjectReferenceWithArch.Filename) Isx86 '%(Isx86)' Inline '$([System.Text.RegularExpressions.Regex]::IsMatch(%(Filename), '.*x86*'))' Project '%(Project)'"
Importance="high" />
</Target>
我刚注意到{{3}}。语法如下所示:
AdditionalTasks:
Example.UnitTests-x86 Isx86 'True' Inline 'True' Project '{7e854803-007c-4800-80f9-be908655229d}'
Example.UnitTests Isx86 'False' Inline 'False' Project '{eaac5f22-bfb8-4df7-a711-126907831a0f}'
只需确保此目标在您需要检查<Target Name="AdditionalTasks">
<ItemGroup>
<ProjectReference>
<Isx86>$([MSBuild]::ValueOrDefault('%(Filename)', '').Contains('x86'))</Isx86>
</ProjectReference>
</ItemGroup>
</Target>
元数据的目标之前运行,或者在Isx86
中需要元数据之前显示<ItemGroup/>
。