2011-01-26 19 views
6

私は何かを時々繰り返すことは気にしませんが、MSBuildではどうして実際にどうすればの繰り返しを避けるのか分かりません。通常の意味では「機能」を提供しません。ターゲットはCallTargetでさえ一度だけ呼び出され、<Import>Projectレベルでのみ動作します。MSBuildで繰り返しを避けるには?

は、ここで私は "repetizeを" デしようとしている具体的な例を示します

<Target Name="Tgt1"> 
    <PropertyGroup><Conf1>Twiddle</Conf1><Conf2>Thing</Conf2></PropertyGroup> 

    <PropertyGroup><xxxxxxxxxxExePath>$(xxxxxxxBuildRoot)\$(Conf1)Console-xxxxxxxxed</xxxxxxxxorExePath></PropertyGroup> 
    <MSBuild Projects="$(BuildSingleProj)" Targets="Build;Merge" 
      Properties="Configuration=$(Conf1)$(Conf2);Platform=$(Platform);CompiledFileName=$(CompiledFileName);ProjectName=$(ProjectName);SolutionFile=$(SolutionFile);Root=$(Root);Caller=$(MSBuildProjectFullPath)"/> 
    <MakeDir Directories="$(xxxxxxxxorExePath)" /> 
    <WriteLinesToFile File="$(xxxxxxxxorExePath)\xxxxxxx.IsPortable.txt" /> 
    <WriteLinesToFile File="$(xxxxxxxxorExePath)\xxxxxxx.Global.Settings.xml" Lines="@(xxxxxxxLicense)" Overwrite="true" /> 
    <Exec Command='$(xxxxxxxxorExePath)\xxxxxxx.exe -a "$(xxxxxxxBuildRoot)\$(Conf1)$(Conf2)-Merged\xxxxxxx.exe" "$(xxxxxxxBuildRoot)\$(Conf1)$(Conf2)-xxxxxxxxed\xxxxxxx.exe"'/> 
</Target> 

私はそのような4つの目標、Tgt1Tgt2Tgt3Tgt4を持っています。 これらの4つのターゲットで異なるものは、最初の行で、Conf1Conf2を定義するものです。

私が気づいている、より多くのまたはより少ない実行可能な重複除外アイデアは、共有コードを新しいターゲットに移動し、MSBuildタスクを使用して呼び出すことです。残念ながら、loooooongプロパティの文字列を手動で渡す必要があります。このタスクでは、ほんの少し(11個のプロパティと1個のアイテムグループを数えました)を使用します。

追加の要件は、これらのターゲットのサブセットを任意ので呼び出すことができます。 \t:Tgt2,Tgt3

このコードをコピー/ペーストするだけの賢明な選択肢がありますか?代わりに大量のプロパティリストをコピーする必要はありません。

答えて

8

これはBatchingを使用するのに最適なシナリオです。

適切なメタデータを使用してカスタムItemsを作成し、新しいアイテムを参照する単一のターゲットを作成する必要があります。

あなたがそうのようにそれ自身の目標の各項目をラップすることができます:あなたはその後、それはそうのようにすべての作業を実行します呼び出すためにコアターゲットが必要になります

<Target Name="Tgt1"> 
    <ItemGroup> 
    <BuildConfig Include="Tgt1"> 
     <Conf1>Twiddle</Conf1> 
     <Conf2>Thing</Conf2> 
    </BuildConfig> 
    </ItemGroup> 
</Target> 

<Target Name="Tgt2"> 
    <ItemGroup> 
    <BuildConfig Include="Tgt2"> 
     <Conf1>Twaddle</Conf1> 
     <Conf2>Thing 1</Conf2> 
    </BuildConfig> 
    </ItemGroup> 
</Target> 

<Target Name="Tgt3"> 
    <ItemGroup> 
    <BuildConfig Include="Tgt3"> 
     <Conf1>Tulip</Conf1> 
     <Conf2>Thing 2</Conf2> 
    </BuildConfig> 
    </ItemGroup> 
</Target> 

<Target Name="CoreBuild" Outputs="%(BuildConfig.Identity)"> 
    <Message Text="Name : %(BuildConfig.Identity)" /> 
    <Message Text="Conf1 : %(BuildConfig.Conf1)" /> 
    <Message Text="Conf2 : %(BuildConfig.Conf2)" /> 
</Target> 

Outputs="%(BuildConfig.Identity)"をターゲットに追加すると、タスクレベルではなくターゲットレベルでバッチ処理が行われます。

これは、最後のターゲットがコアターゲットである限り、ターゲットの任意の組み合わせを渡してmsbuildから実行できます。このコマンドを実行するたとえばMSBuild.exe test.msbulid /t:Tgt1,Tgt3,CoreBuildあなたに次のような出力が得られます:

Name : Tgt1 
Conf1 : Twiddle 
Conf2 : Thing 

Name : Tgt3 
Conf1 : Tulip 
Conf2 : Thing 2 
+0

これは、もはや1つだけ、あるいは2つしか作成できないことを意味します。その能力を保持する方法はありますか? –

+0

アイテムに条件を付けることができます。答えを例で更新します。 –

+0

ありがとうございますが、_two_ビルドを含めるには条件が非常に厄介になることがあります。私は現在、 '/ t:Tgt1、Tgt2'を指定する能力を保持したいので、繰り返しを続けることに傾いています - 実際のスクリプトは実際にはもっとターゲットをいくつか持っており、任意のサブセットを選ぶ能力に頼っていますこのような。 –

5

DRYは、MSBuildのの信条ではありません。どんな場合でも自分自身を繰り返すことは良くないと言われているので、それはと合理的には避けることができます。 Aaronがバッチ処理に関して与えた答えは良いものです。これは重複を防ぐ手段の1つです。

私が指摘したいことの1つは、MSBuildを手続き型言語(つまり呼び出すことができる関数を持つものとしないもの)として考えているようなものです。 MSBuildは手続き型よりもはるかに宣言的です。MSBuildスクリプトを作成しているときに、「ポイントYで呼び出すことができるようにXを作成する」という考え方があれば、苦痛の世界に入ります。代わりにMSBuildをフェーズと考えるべきです。例えば;このように考えると、ターゲットが一度実行された後にターゲットがスキップされた理由を完全に理解することができます(、あなたの試行中に明らかに観察されました)。

また、MSBuildと一緒に働いている間は、ジェネリック/ユーバー再利用可能な方法でやりとりすることが本当にピタとなることが分かっています。それはできますが、私は確実にあなたが再利用されることを知っている.targetsファイルのための努力のタイプを予約します多くの回。私はもっ​​と実用的で、完全にハッキングしているスクリプトの間のどこかに着いた&私がやったやり方で物事をしています。私は再利用する一連のスクリプトを用意していますが、私はそれを試して単純なものにしています。この大きな理由の1つは、MSBuildの基本をどのように知っているか、非常に深い知識を持っている人はいないということです。優れた汎用スクリプトを作成するには、MSBuildに関する深い知識が必要です。プロジェクトを終了するときに、後ろにいる人はあなたが何をしているのか分かりません(、請負業者の場合はおそらく役に立ちますか?lol)。

いずれにしても、バッチ処理のリソースはhttp://sedotech.com/Resources#Batchingです。

+0

この洞察をいただきありがとうございます。うまくいけば私をあまりにも頑張って救うだろう私はMSBuildを宣言的に見ようとしていますが、宣言的な言語でさえ、抽象を作成するためのメカニズムが必要です。名前 "機能"を提案してくれたことは間違っています。 –

+0

私は秘密裏に、私には分かりませんでした。多分、10以上のプロパティの_same_セットをいくつかのMSBuildタスクに渡すという苦労を緩和するためのいくつかの方法はありますか?私は実際にそこにたどり着きました。プロパティはあまりにも早く評価されました。私はMSBuildに渡されるのと同じように評価するために "eval"のようなものを見つけることができませんでした。 –

+0

"eval"あなたが実行するターゲットの内部にItemGroupを配置する必要があります。ターゲット外のItemGroup Elmenetsは、ターゲットが実行される前に評価されますが、ターゲット内のItemGroup要素は、ターゲットの実行時に評価されます。 –

関連する問題