ボンネットの下で何が起こっているのかを正確に伝えるのは困難です。私は MSBuild を使用していないため、実際の実装についてはあまり詳しくありません。100% 正しい答えを得るには、MSBuild 開発者が必要です。しかし、これが私が想定していることです(読んでください:これの残りの部分には私の推測が含まれています)。
ステートメントを使用するときに対象とする内部
Projects="$(BaseDirectory)\DebugConsoleApp\DebugConsoleApp.csproj"
MSBuild は、プロパティ展開 $(BaseDirectory) が使用されていること、および MSBuild のプロジェクトのパラメーター タイプが配列であることを認識します。また、MSBuild は、BaseDirectory が項目を含むプロパティであることを認識します。これらのプロパティは、通常のプロパティとは異なります。それらを「仮想プロパティ」と考えることができます (はい、私はその用語を作りました)。値を検索する代わりにこれらのプロパティを使用すると、インラインで置換が行われます。したがって、 Projects 属性は次のように変更されます。
Projects="@(Base->'%(FullPath)')\DebugConsoleApp\DebugConsoleApp.csproj"
Projects は配列であるため、MSBuild は指定された式に対して変換を実行しようとします。これは有効な変換ではないため、エラーが発生します。あなたが受け取っているエラーはどれですか。
これを回避するには、ビルド ターゲットを次のように変更します。
<Target Name="Build">
<PropertyGroup>
<_BaseDir>$(BaseDirectory)</_BaseDir>
<_DeployDir>@(Base->'%(FullPath)')</_DeployDir>
</PropertyGroup>
<Message Text="_BaseDir: $(_BaseDir)"/>
<Message Text="DeployDirectory: $(DeployDirectory)"/>
<MSBuild Projects="$(_BaseDir)\DebugConsoleApp\DebugConsoleApp.csproj"
Properties="Configuration=$(Configuration);OutputPath=$(_Tmp2)"
ContinueOnError="false" />
<!--<MSBuild Projects="$(BaseDirectory)\DebugConsoleApp\DebugConsoleApp.csproj"
Properties="Configuration=$(Configuration);OutputPath=$(DeployDirectory)"
ContinueOnError="false" />-->
</Target>
このアプローチでは、ターゲット自体にプロパティ グループを作成し、それらの「仮想プロパティ」の値を新しいプロパティに割り当てました。これらの新しいプロパティは仮想プロパティではなく、実際のプロパティであるため、問題なく期待どおりに使用できます。
「なぜメッセージタスクはWTFで動作するのですか?!!!」という質問に進みましょう。
Hello ターゲット内には、次のものがあります。
<Message Text="Hello world. BaseDirectory=$(BaseDirectory), DeployDirectory=$(DeployDirectory)" />
これは問題なく動作します。前に、これらの仮想プロパティは本質的に、それらを裏付ける定義にインラインで置き換えられると述べたので、実際にはそうなるでしょう。
<Message Text="Hello world. BaseDirectory=@(Base->'%(FullPath)'), DeployDirectory=@(Base->'%(FullPath)')\Deploy" />
OK、その考えを保持します。
MSBuild タスクのText
プロパティは、スカラー値である文字列として定義されます。MSBuild タスクの Projects プロパティが ITaskItem[] として定義されていることを思い出してください。これは配列であり、ベクトル値であるためです。ベクトル値プロパティ内でa@(...)
が見つかった場合、式全体が項目変換として使用されます。この場合、ステートメント@(Base->'%(FullPath)')\DebugConsoleApp\DebugConsoleApp.csproj
は有効な変換式ではありません。「@(..)」がスカラー値プロパティ宣言内で見つかった場合、値は文字列にフラット化されます。したがって、「@(...)」の各インスタンスが処理され、単一の文字列値にフラット化されます。複数の値がある場合は、区切り記号が使用されます。
うまくいけば、それはあなたが見ている動作を説明するものであり、実際にはバグである可能性があります. http://connect.microsoft.com/でログに記録すると、MSBuild チームがトリアージします。
仮想プロパティの詳細について
は前述しましたが、これらの仮想プロパティは、値が検索されないという意味で通常のプロパティのようには動作しませんが、代わりに $(...) の使用がプロパティ式に置き換えられます。私の言葉を鵜呑みにしないで、自分の目で確かめてください。これが私が作成したサンプルファイルです
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
<ItemGroup>
<MyItem Include="C:\temp\01.txt"></MyItem>
</ItemGroup>
<PropertyGroup>
<MyProperty>@(MyItem->'%(FullPath)')</MyProperty>
</PropertyGroup>
<Target Name="Demo">
<Message Text="MyProperty: $(MyProperty)" />
<!-- Add to the item -->
<ItemGroup>
<MyItem Include="C:\temp\01.txt"></MyItem>
</ItemGroup>
<Message Text="MyProperty: $(MyProperty)" />
</Target>
</Project>
ここでは、宣言された項目リストMyItemと依存プロパティMyPropertyがあります。Demo ターゲット内で、MyProperty の値を出力してから、別の値を MyItem アイテム リストに追加し、MyProperty の値を再度出力します。これが結果です。
PS C:\temp\MSBuild\SO> msbuild .\Build.proj /nologo
Build started 4/26/2011 10:17:08 PM.
Project "C:\temp\MSBuild\SO\Build.proj" on node 1 (default targets).
First:
MyProperty: C:\temp\01.txt
MyProperty: C:\temp\01.txt;C:\temp\01.txt
Done Building Project "C:\temp\MSBuild\SO\Build.proj" (default targets).
ご覧のとおり、私が述べた方法で動作します。