MSBuild验证属性

时间:2010-04-29 21:15:27

标签: msbuild properties batch-file

我正在开发一个可重用的MSBuild Target,它将被其他几个任务使用。此目标要求定义多个属性。验证属性是否已定义的最佳方法是什么,如果不是,则抛出错误?

我几乎的两次尝试:

<?xml version="1.0" encoding="utf-8" ?>
  <Project ToolsVersion="3.5" DefaultTarget="Release" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <Target Name="Release">
    <Error
      Text="Property PropA required"
      Condition="'$(PropA)' == ''"/>
    <Error
      Text="Property PropB required"
      Condition="'$(PropB)' == ''"/>

    <!-- The body of the task -->

  </Target>
</Project>

这是一次批量尝试。由于额外的“名称”参数,这很难看。是否可以使用Include属性?

<?xml version="1.0" encoding="utf-8" ?>
<Project ToolsVersion="3.5" DefaultTarget="Release" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <Target Name="Release">
    <!-- MSBuild BuildInParallel="true" Projects="@(ProjectsToBuild)"/ -->
    <ItemGroup>
      <RequiredProperty Include="PropA"><Name>PropA</Name></RequiredProperty>
      <RequiredProperty Include="PropB"><Name>PropB</Name></RequiredProperty>
      <RequiredProperty Include="PropC"><Name>PropC</Name></RequiredProperty>
    </ItemGroup>

    <Error
      Text="Property %(RequiredProperty.Name) required"
      Condition="'$(%(RequiredProperty.Name))' == ''" />

  </Target>

</Project>

1 个答案:

答案 0 :(得分:17)

好问题!我已在book和博文Elements of Reusable MSBuild Scripts: Validation中深入探讨了这一点。我的方法将涵盖属性和项目。

这是向下跑。在共享.targets文件中创建验证目标,这应该是文件中声明的第一个目标之一,以便用户可以轻松找到它。

<强>属性

在验证目标内定义您的属性,如下所示:

<_RequiredProperties Include="Root">
  <Value>$(Root)</Value>
</_RequiredProperties>

我将属性的名称放在include及其Value元数据中的值中。我这样做的原因是我可以检测到Value何时为空,然后我使用include值,用于向用户报告缺失属性的名称。

<强>项

在目标内部,将所需项目放在项目中,如:

<_RequiredItems Include="AllConfigurations">
  <RequiredValue>@(AllConfigurations)</RequiredValue>
</_RequiredItems>

与属性类似,在include中放置项的名称,然后在RequiredValue元数据内部检查值。在此示例中,它仅检查以确保AllConfiguraitons项不为空。如果要确保在所有项目上指定给定的元数据值,请执行以下操作:

<_RequiredItems Include = "AllConfigurations.Configuration">
  <RequiredValue>%(AllConfigurations.Configuration </RequiredValue>
</_RequiredItems>

如果要确保文件存在,请添加其他元数据RequiredFilePath。

<_RequiredItems Include ="ProjectsToBuild">
  <RequiredValue>%(ProjectsToBuild.Identity)</RequiredValue>
  <RequiredFilePath>%(ProjectsToBuild.Identity)</RequiredFilePath>
</_RequiredItems>

验证

以下是执行验证所需的内容

完整示例

以下是完整示例

<Target Name="ValidateBuildSettings">
  <ItemGroup>
    <_RequiredProperties Include="Root">
      <Value>$(Root)</Value>
    </_RequiredProperties>

    <_RequiredProperties Include="BuildInstallRoot">
      <Value>$(BuildInstallRoot)</Value>
    </_RequiredProperties>

    <_RequiredProperties Include="SourceRoot">
      <Value>$(SourceRoot)</Value>
    </_RequiredProperties>
    <!-- 
    _RequiredItems is the item where required items should be placed. 
    The following metadata is significant: 
      REQUIRED METADATA: 
      Identity          = This will basically be used to identify the specific required item 
      RequiredValue     = This is the specific value that will be validated to exist 

      OPTIONAL METADATA 
      RequiredFilePath  = Populate this with a path that should exists, if it is not empty 
                            then it will be checked to exist on disk. 
    -->

    <_RequiredItems Include="AllConfigurations">
      <RequiredValue>@(AllConfigurations)</RequiredValue>
    </_RequiredItems>
    <_RequiredItems Include = "AllConfigurations.Configuration">
      <RequiredValue>%(AllConfigurations.Configuration </RequiredValue>
    </_RequiredItems>
    <_RequiredItems Include ="ProjectsToBuild">
      <RequiredValue>%(ProjectsToBuild.Identity)</RequiredValue>
      <RequiredFilePath>%(ProjectsToBuild.Identity)</RequiredFilePath>
    </_RequiredItems>
  </ItemGroup>
  <!-- Raise an error if any value in _RequiredProperties is missing -->

  <Error Condition =" '%(_RequiredProperties.Value)'=='' "
          Text=" Missing required property [%(_RequiredProperties.Identity)]" />

  <!-- Raise an error if any value in _RequiredItems is empty -->
  <Error Condition = " '%(_RequiredItems.RequiredValue)'=='' "
          Text = " Missing required item value [%(_RequiredItems.Identity)] " />

  <!-- Validate any file/directory that should exist -->
  <Error Condition = " '%(_RequiredItems.RequiredFilePath)' != '' and !Exists('%(_RequiredItems.RequiredFilePath)') "
          Text = " Unable to find expeceted path [%(_RequiredItems.RequiredFilePath)] on item [%(_RequiredItems.Identity)] " />
</Target>