22

もう一度、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 タスクを呼び出しているようです。私がしたいのは、パスを更新して、プロジェクトのどこでも利用できるようにすることだけです。何か案は?

4

2 に答える 2

24

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をMainではなくTask1依存関係にすると、PropertyScopeTest1.proj と同じ動作になります。

于 2011-09-26T16:47:48.813 に答える
20

これは非常に興味深い質問であり、次の記事の例で深く調査されています: MSBuild スクリプトのプロパティと項目のスコープ

基本的に、ターゲット実行全体でローカルおよびグローバル コンテキスト スイッチを使用するトリックがあります。

  • Project クラスの 1 つのインスタンスがスクリプト用に作成され、グローバル コンテキストのプロパティと項目のすべての値が含まれます。
  • ターゲットが実行されると、グローバル コンテキストがターゲットによって使用されるローカル コンテキストにコピーされます。
  • ターゲットの実行が終了すると、ローカル コンテキストの更新がマージされてグローバル コンテキストに戻されます。
  • ターゲットの実行が完了するまで、CallTarget または MSBuild タスクを使用して呼び出されたターゲットは、ローカルの更新にアクセスできません。
于 2011-09-24T13:54:37.933 に答える