MSBuild 条件
MSBuild 支持一组特定的条件,只要允许使用 Condition
属性,即可应用这些条件;请参阅支持的元素。 下表对这些条件进行了说明。
条件 | 描述 |
---|---|
'stringA ' == 'stringB ' |
如果 stringA 等于 stringB ,则计算结果为 true 。例如: Condition="'$(Configuration)'=='DEBUG'" 简单的字母数字字符串或布尔值不需要使用单引号。 但对于空值,单引号是必需的。 此检查不区分大小写。 |
'stringA' != 'stringB' |
如果 stringA 不等于 stringB ,则计算结果为 true 。例如: Condition="'$(Configuration)'!='DEBUG'" 简单的字母数字字符串或布尔值不需要使用单引号。 但对于空值,单引号是必需的。 此检查不区分大小写。 |
<、=><、>= | 计算操作数的数值。 如果关系评估为 true,则返回 true 。 操作数的计算结果必须为十进制或十六进制数或由四部分组成的点分版本。 十六进制数字必须以 0x 开头。 注意:在 XML 中,必须对字符 < 和 > 进行转义。 符号 < 表示为 < 。 符号 > 表示为 > 。 |
Exists('stringA ') |
如果存在名为 stringA 的文件或文件夹,则计算结果为 true 。例如: Condition="!Exists('$(Folder)')" 简单的字母数字字符串或布尔值不需要使用单引号。 但对于空值,单引号是必需的。 此条件不会展开通配符,例如 * 。 |
HasTrailingSlash('stringA ') |
如果指定的字符串末尾包含反斜杠 (\) 或正斜杠 (/) 字符,则计算结果为 true 。例如: Condition="!HasTrailingSlash('$(OutputPath)')" 简单的字母数字字符串或布尔值不需要使用单引号。 但对于空值,单引号是必需的。 |
! | 如果操作数计算结果为 false ,则计算结果为 true 。 |
And |
如果两个操作数计算结果均为 true ,则计算结果为 true 。 |
Or |
如果至少一个操作数计算结果为 true ,则计算结果为 true 。 |
() | 如果内含表达式计算结果为 true ,则分组机制的计算结果为 true 。 |
$if$ ( %expression% ), $else$, $endif$ |
检查指定的 %expression% 是否与传递的自定义模板参数的字符串值相匹配。 如果 $if$ 条件计算结果为 true ,则其语句处于运行状态;否则,检查 $else$ 条件。 如果 $else$ 条件为 true ,则其语句为运行状态;否则,$endif$ 条件将结束表达式求值。有关用法的示例,请参阅 Visual Studio Project/Item Template Parameter Logic(Visual Studio 项目/项模板参数逻辑)。 |
元素 Condition
是单个字符串,因此表达式中使用的任何字符串(包括属性值周围)都需要用单引号括起来。 允许运算符之间的空格,通常用于可读性,但它们不是必需的。
若要使用布尔 And
值和 Or
运算符,请在元素的字符串值内 Condition
指定操作数,如以下示例所示:
Condition="'$(Configuration)' == 'Debug' And '$(MSBuildProjectExtension)' == '.csproj'"
可以链接布尔运算符。 运算符 And
的优先级高于 Or
,但为了清楚起见,我们建议在使用多个布尔运算符时使用括号来明确计算顺序。 否则,MSBuild 会发出警告 MSB4130。
在以下示例所示的情况下可以使用字符串方法,其中 TrimEnd() 函数仅用于比较字符串的相关部分,以区分 .NET Framework 与 .NET Core 目标框架。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net45;net48;netstandard2.1;netcoreapp2.1;netcoreapp3.1</TargetFrameworks>
</PropertyGroup>
<PropertyGroup Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'">
<!-- Properties for .NET Framework -->
</PropertyGroup>
</Project>
在 MSBuild 项目文件中,没有真正的布尔类型。 布尔数据用属性表示,这些属性可能是空的,也可能设置为任何值。 因此,'$(Prop)' == 'true'
表示“如果 Prop 是 true
,但 '$(Prop)' != 'false'
表示“如果 Prop 是 true
或者未设置,或者设置为其他内容。”
布尔逻辑只在条件的上下文中计算,因此,像 <Prop2>'$(Prop1)' == 'true'</Prop>
这样的属性设置是以(变量扩展后的)字符串的形式来表示的,而不是以布尔值的形式来计算。
MSBuild 实现了一些特殊的处理规则,使其更容易处理用作布尔值的字符串属性。 接受布尔文本,因此 Condition="true"
和 Condition="false"
按预期方式工作。 MSBuild 还包括支持布尔求反运算符的特殊规则。 因此,如果 $(Prop)
为“true”,则 !$(Prop)
会展开为 !true
,并且此值会按预期等于 false
。
比较版本
关系运算符 <
、>
、<=
和 >=
支持由 System.Version 分析的版本,因此可以比较具有四个数值部分的版本。 例如,'1.2.3.4' < '1.10.0.0'
为 true
。
注意
如果有一个或两个版本未指定全部四个部分,System.Version
比较可能会产生令人吃惊的结果。 例如,版本 1.1 早于版本 1.1.0。
MSBuild 提供了用于比较版本的属性函数,这些版本具有与语义化版本控制 (SemVer) 兼容的不同规则集。
条件中的扩展
根据项目文件中的位置,可以对属性 ($)、项列表 (@) 和项元数据 (%) 使用扩展。 扩展取决于 MSBuild 处理项目文件的方式。
属性
计算包含表达式(如 $(SomeProperty)
)的条件并将其转换为属性值。 如果条件在目标外部,则在计算项目文件期间计算表达式。 属性的值取决于展开所有导入内容后项目文件中的位置。 如果条件在目标内部,则在目标执行期间对其进行计算,并且值会受到执行生成期间发生的任何更改的影响。
未在出现条件表达式的展开项目文件中的点定义的属性计算结果为空字符串,而不会出现任何诊断错误或警告。
项列表
包含 @-expression(如 @(SomeItems)
)的条件在顶级和目标的项目组中展开。
项可以依赖于任何属性,也可以依赖于已按顺序定义的项。
原因在于 MSBuild 在多个阶段处理项目文件。 项计算阶段在初始属性计算和导入扩展阶段之后发生。 因此,允许在开始定义项后计算的任何条件中使用 @-expressions。 也就是在项、项组和目标中。
元数据
包含元数据表达式(如 %(ItemMetadata)
)的条件在与项目列表相同的上下文中展开,即在顶级和目标内部的项组中展开。 但是,扩展可以在项组中具有不同的行为,具体取决于项组是位于目标外部还是目标内部。 此外,在各种形式的元数据表达式(%(ItemName.MetadataName)
、%(JustTheMetadataName)
和 @(ItemName->'%(MetadataName)')
)中,仅允许项转换(最后一个)位于目标外部。 目标中 %-expression 的值在运行时计算,具体取决于目标执行期间的任何状态更改。 目标的执行及其中包含的任何 %-expressions 的值也取决于目标的批处理,并且还可以触发批处理;请参阅 MSBuild 批处理。
支持的元素
以下元素支持该 Condition
特性:
- Import
- ImportGroup
- 项
- ItemDefinitionGroup
- ItemGroup
- ItemMetadata
- OnError
- 输出
- properties
- PropertyGroup
- 目标
- 任务
- UsingTask
- When