MSBuild Проверка свойств - PullRequest
14 голосов
/ 30 апреля 2010

Я работаю над повторно используемой целью MSBuild, которая будет использоваться другими задачами. Эта цель требует, чтобы было определено несколько свойств. Каков наилучший способ проверки того, что свойства определены, если в противном случае выдается ошибка?

Две попытки, которые я почти вроде:

<?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 Ответ

17 голосов
/ 30 апреля 2010

Отличный вопрос! Я подробно писал об этом в моей книге и в сообщении в блоге Элементы повторно используемых скриптов MSBuild: проверка . Мой подход будет охватывать свойства и предметы.

Вот беги вниз. В общем файле .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>
...