Подтвердить что ты не робот

Область действия MSBuild

Еще раз я сражаюсь с MSBuild. Я хочу иметь значение свойства, определенное корневым путем. В рамках сборки путь будет обновляться с информацией о версии. Тем не менее, MSBuild, похоже, имеет свои собственные правила обзора, которые кажутся полностью обратными. Возьмите этот первый пример:

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

  <PropertyGroup>
    <MyPath>\\server\folder</MyPath>
  </PropertyGroup>

  <Target Name="Main">
    <Message Text="In Main Before - MyPath = $(MyPath)"/>
    <CallTarget Targets="Task1" />
    <CallTarget Targets="Task2" />
    <CallTarget Targets="Task3" />
    <Message Text="In Main After - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task1">
    <PropertyGroup>
        <MyPath>$(MyPath)\version5</MyPath>
    </PropertyGroup>
    <Message Text="In Task1 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task2">
    <Message Text="In Task2 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task3">
    <Message Text="In Task3 - MyPath = $(MyPath)"/>
  </Target>

</Project>

Здесь вывод с этой командной строкой: msbuild PropertyScopeTest1.proj /target:Main

Project "C:\Temp\PropertyScopeTest1.proj" on node 1 (Main target(s)).
Main:
  In Main Before - MyPath = \\server\folder
Task1:
  In Task1 - MyPath = \\server\folder\version5
Task2:
  In Task2 - MyPath = \\server\folder\version5
Task3:
  In Task3 - MyPath = \\server\folder\version5
Main:
  In Main After - MyPath = \\server\folder
Done Building Project "C:\Temp\PropertyScopeTest1.proj" (Main target(s)).

Теперь, здесь немного другая версия, устанавливающая переменную MyPath в главной цели:

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

  <PropertyGroup>
    <MyPath>\\server\path</MyPath>
  </PropertyGroup>

  <Target Name="Main">
    <Message Text="In Main Before - MyPath = $(MyPath)"/>
    <PropertyGroup>
        <MyPath>$(MyPath)\version5</MyPath>
    </PropertyGroup>
    <Message Text="In Main After PropertyGroup - MyPath = $(MyPath)"/>
    <CallTarget Targets="Task1" />
    <CallTarget Targets="Task2" />
    <CallTarget Targets="Task3" />
    <Message Text="In Main After - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task1">
    <Message Text="In Task1 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task2">
    <Message Text="In Task2 - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="Task3">
    <Message Text="In Task3 - MyPath = $(MyPath)"/>
  </Target>

</Project>

Здесь вывод с этой командной строкой: msbuild PropertyScopeTest2.proj /target:Main

Project "C:\Temp\PropertyScopeTest2.proj" on node 1 (Main target(s)).
Main:
  In Main Before - MyPath = \\server\path
  In Main After PropertyGroup - MyPath = \\server\path\version5
Task1:
  In Task1 - MyPath = \\server\path
Task2:
  In Task2 - MyPath = \\server\path
Task3:
  In Task3 - MyPath = \\server\path
Main:
  In Main After - MyPath = \\server\path\version5
Done Building Project "C:\Temp\PropertyScopeTest2.proj" (Main target(s)).

Я просмотрел другие ссылки на этом сайте, которые похожи, но все, кажется, вызывают задачу MSBuild из файла проекта MSBuild. Все, что я хочу сделать, это обновить путь и иметь его везде в проекте. Любые идеи?

4b9b3361

Ответ 1

На основе ответа sll, создавая цель, которая устанавливает новый путь для зависимости, вместо использования CallTarget приведет к ожидаемому поведению:

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

  <PropertyGroup>
    <MyPath>\\server\folder</MyPath>
  </PropertyGroup>

  <Target Name="Main" DependsOnTargets="SetMyPathProperty">
    <Message Text="In Main Before - MyPath = $(MyPath)"/>
    <CallTarget Targets="Task1" />
    <Message Text="In Main After - MyPath = $(MyPath)"/>
  </Target>

  <Target Name="SetMyPathProperty">
    <PropertyGroup>
      <MyPath>$(MyPath)\version5</MyPath>
    </PropertyGroup>
  </Target>

  <Target Name="Task1">
    <Message Text="In Task1 - MyPath = $(MyPath)"/>
  </Target>

</Project>

Создать вывод:

Main:
  In Main Before - MyPath = \\server\folder\version5
Task1:
  In Task1 - MyPath = \\server\folder\version5
Main:
  In Main After - MyPath = \\server\folder\version5

Создание SetMyPathProperty зависимости Task1 вместо Main приведет к идентичному поведению с вашим PropertyScopeTest1.proj.

Ответ 2

Это очень интересный вопрос, который глубоко изучен с примерами в следующей статье: Область свойств и элемента в MSBuild script

В основном есть трюки с локальным и глобальным контекстными переключателями в целевых исполнениях:

  • Один экземпляр класса Project создается для script и содержит все значения свойств и элементов в глобальном контекст.
  • Когда цель выполняется, глобальный контекст копируется в локальном контекст, который будет использоваться целевой.
  • Конечный конец выполнения, локальные обновления контекста объединяются вернуться к глобальному контексту.
  • До завершения целевого исполнения локальные обновления не доступный для целевых объектов с использованием задач CallTarget или MSBuild.