5

我的 VC++ 项目在 VS2010 中有一个自定义构建规则。在这条规则中,我想允许用户添加关于文件是否被处理的复杂条件。

这也需要在目标执行时进行评估,而不是在 'Item' 本身的 'Condition' 中进行评估(由于只有 'application' 项目可以处理它并且需要使用设置来处理它“应用程序”项目而不是依赖项目)。

我尝试向对象添加自定义字段,然后在执行时从组中删除项目。例如

<ItemGroup>
    <MyItemType Remove="@(MyItemType)" Condition="!(%(MyItemType.IncludeCondition))" />
</ItemGroup>

不幸的是,这给了我错误:

错误 MSB4113:指定条件 "!(%(MyItemType.IncludeCondition))" 计算结果为 "!'testfilename1' == 'testfilename2' or false" 而不是布尔值。

('%(MyItemType.IncludeCondition)' 中的原始条件表达式是'%(Filename)' == 'testfilename2' or $(TestBooleanFalse)

似乎 MSBuild 不会将项目元数据的内容评估为布尔值(在大多数情况下这似乎是一种很好的做法,只是不是这个)。

无论如何,我可以让 MSbuild 将元数据实际评估为布尔值,还是有其他方法可以用来获得相同的结果?


PS 我已经简要浏览了 MSBuild Property Functions,但看不到任何可以在函数输入上运行 MSBuild 布尔评估代码的东西)


一个非常精简的 MSBuild 项目示例,显示了该问题,由 Lanrokin 提供:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" DefaultTargets="Build">
    <ItemGroup>
        <MyItemType Include="item1.ext1" />
        <MyItemType Include="item1.ext2" />
    </ItemGroup>

    <Target Name="SpecifyConditions">
        <ItemGroup>
            <MyItemType>
                <IncludeCondition>'%(Filename)%(Extension)' == 'item1.ext1'</IncludeCondition>
            </MyItemType>
        </ItemGroup>
    </Target>

    <Target Name="Build" DependsOnTargets="SpecifyConditions">
        <Message Importance="high" Text="@(MyItemType)" Condition="%(MyItemType.IncludeCondition)" />
    </Target>
</Project>
4

3 回答 3

1

这与 MSBuild 的评估方式有关。有关详细信息,请参阅 Sayed 的书:Microsoft® Build Engine 内部:使用 MSBuild 和 Team Foundation Build

通过移动样本中条件的位置,您可以完成我认为您想要实现的目标。

<Target Name="SpecifyConditions">
    <ItemGroup>
        <MyItemType Condition="'%(Filename)%(Extension)' == 'item1.ext1'">
            <IncludeCondition>true</IncludeCondition>
        </MyItemType>
    </ItemGroup>
</Target>

<Target Name="Build" DependsOnTargets="SpecifyConditions">
    <Message Importance="high" Text="@(MyItemType)" Condition="%(MyItemType.IncludeCondition) == 'true'" />
</Target>

于 2013-04-08T16:04:24.023 回答
0

我认为您的条件语句的一个小调整来自:

'%(Filename)' == 'testfilename2' or $(TestBooleanFalse)

('%(Filename)' == 'testfilename2') or $(TestBooleanFalse)

通过将第一个条件包裹在括号内将解决问题。

于 2013-04-04T12:40:40.740 回答
0

尝试内联声明条件而不是项目元数据:

 <ItemGroup>
    <MyItemType Remove="@(MyItemType)" Condition="('%(MyItemType.Filename)' == 'testfilename2')" />
  </ItemGroup>

或者Property Functions在元数据条件中使用:

<Target Name="SpecifyConditions">
    <ItemGroup>
        <MyItemType>
            <IncludeCondition>$([System.String]::Equals('%(Filename)%(Extension)', 'item1.ext1'))</IncludeCondition>
        </MyItemType>
    </ItemGroup>
</Target>

<Target Name="Build" DependsOnTargets="SpecifyConditions">
    <Message Importance="high" Text="@(MyItemType)" Condition="%(MyItemType.IncludeCondition)" />
</Target>
于 2013-03-29T16:11:43.737 回答