我该如何在VS2010(用于VC++)中公开MSBuild的“Conditions”?

5
我在我的VC ++项目中使用VS2010自定义构建规则。在这个规则中,我希望允许用户添加复杂的条件来确定文件是否被处理。
此外,这也需要在目标执行时进行评估,而不是在“Item”的“Condition”中进行评估(因为只有“应用程序”项目可以处理它,并且需要使用“应用程序”项目的设置来处理它,而不是依赖项目)。
我尝试向对象添加自定义字段,然后在执行时仅从组中删除项目。 例如:
<ItemGroup>
    <MyItemType Remove="@(MyItemType)" Condition="!(%(MyItemType.IncludeCondition))" />
</ItemGroup>

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

error MSB4113:指定的条件“!(%(MyItemType.IncludeCondition))”评估为“!'testfilename1' == 'testfilename2'或false”,而不是布尔值。

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

看起来MSBuild不会将项目元数据评估为布尔值(在大多数情况下,这似乎是一个好的实践,但在这种情况下不是)。

是否有任何方法可以让MSbuild实际将元数据评估为布尔值,或者是否有其他方法可以使用以获得相同的结果?


P.S. 我已经简要查阅了 MSBuild 属性函数, 但没有看到任何可以在函数输入上运行 MSBuild 布尔评估代码的内容。


以下是Lanrokin提供的一个非常简化的MSBuild项目示例,展示了该问题:

<?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>

尝试编辑帖子,但被拒绝了。请查看是否是您想要使其工作的内容http://pastebin.com/nkdz80y5,并考虑将示例包含在问题中。 - Lanorkin
@Lanorkin - 谢谢,你给出的示例中有一个小错误,但它展示了我遇到的问题。(希望人们不要只回复并说将“SpecifyConditions”中的“ItemGroup”转换为带有指定条件的“MyItemType”声明的“Remove”) - Grant Peters
3个回答

1
这与MSBuild评估的方式有关。有关更多信息,请参阅Sayed的书:Inside the Microsoft® Build Engine: Using MSBuild and 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>


在这种解决方案中,我们仍然让msbuild在SpecifyConditions任务中计算条件,而想法是将条件作为参数“传递”,以便在Build任务中计算。 - Lanorkin

0

我认为你的条件语句只需要进行小的调整:

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

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

通过将第一个条件放在括号内,可以解决这个问题。

0
尝试将条件声明为内联,而不是项目元数据:
 <ItemGroup>
    <MyItemType Remove="@(MyItemType)" Condition="('%(MyItemType.Filename)' == 'testfilename2')" />
  </ItemGroup>

或者在元数据条件中使用属性函数

<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>

我无法这样做,因为条件是根据每个文件的用户定义的(正如在原问题中的第二句话所述)。 - Grant Peters
这个可以工作吗:Condition="'(%(MyItemType.IncludeCondition))' == 'False'" - KMoraz
不,这个想法是%(MyItemType.IncludeCondition)被扩展为字符串而不是布尔值,虽然它并没有被评估。 - Lanorkin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接