7

多くのプロジェクトを含むソリューションの一部として、(<ProjectReference>ソリューション内の他の 3 つのプロジェクトと他のいくつかのプロジェクトを介して) 参照するプロジェクトがあります。でAfterBuild、3 つの特定の依存プロジェクトの出力を別の場所にコピーする必要があります。

さまざまなSOの回答などを介して、それを達成するために私が落ち着いた方法は次のとおりです。

    <MSBuild 
        Projects="@(ProjectReference)" 
        Targets="Build" 
        BuildInParallel="true" 
        Condition="'%(Name)'=='ProjectA' OR '%(Name)'=='ProjectB' OR '%(Name)'=='ProjectC'">
        <Output TaskParameter="TargetOutputs" ItemName="DependentAssemblies" />
    </MSBuild>
    <Copy SourceFiles="@(DependentAssemblies)" DestinationFolder="XX" SkipUnchangedFiles="true" />

しかし、これで問題が発生しました。<MSBuildステップのタスクは、最終的IncrementalCleanに のいくつかの出力を削除しますProjectC。これを VS2008 で実行すると、build.forceファイルが ProjectC のobj/Debugフォルダーに置かれ、プロジェクトがこのターゲットを含む場合にソリューション全体でビルドを実行すると、ProjectC が再構築されますが、AfterBuildこのプロジェクトをビルドから除外すると、[正しく] は、ProjectC の再構築をトリガーしません (そして、ProjectCのすべての依存関係の再構築は重要です)。これは、この場合、TeamBuild またはその他のコマンドライン MSBuild 呼び出しのコンテキストでは発生しない VS 固有の策略である可能性があります (ただし、最も一般的な使用法は VS 経由であるため、いずれかの方法でこれを解決する必要があります)。

依存プロジェクト (および一般的なソリューションの残りの部分) はすべて VS と対話的に作成されているため、ProjectRefences には相対パスなどが含まれています。これが問題を引き起こす可能性があるという言及を見てきましたが、理由の完全な説明はありません。 、またはいつ修正されるか、またはそれを回避する方法。言い換えれば、ProjectReference.csproj を手動で編集してパスを絶対パスに変換するなどにはあまり興味がありません。

私がばかげたことをしていて、誰かがすぐにそれが何であるかを指摘する可能性は十分にありますが (それは素晴らしいことです)、/v:diag出力などを熟読するのに多くの時間を費やしたことを確認してください (ただし、から再現を構築しようとしたことはありません)ゼロから - これは比較的複雑な全体的なビルドのコンテキストにあります)

4

4 に答える 4

6

元のソリューションは、変更するだけで機能するはずです

Targets="Build"

Targets="GetTargetPath"

GetTargetPathターゲットはプロパティを返すだけで、ビルドTargetPathは必要ありません。

于 2010-09-27T05:28:05.957 に答える
2

最初に次のようにターゲットを呼び出すと、ProjectC でファイルを保護できます。

  <Target Name="ProtectFiles">
    <ReadLinesFromFile File="obj\ProjectC.csproj.FileListAbsolute.txt">
        <Output TaskParameter="Lines" ItemName="_FileList"/>
    </ReadLinesFromFile>
    <CreateItem Include="@(_DllFileList)" Exclude="File1.sample; File2.sample">
        <Output TaskParameter="Include" ItemName="_FileListWitoutProtectedFiles"/>
    </CreateItem>      
      <WriteLinesToFile 
        File="obj\ProjectC.csproj.FileListAbsolute.txt"
        Lines="@(_FileListWitoutProtectedFiles)"
        Overwrite="true"/>
  </Target>
于 2010-09-16T16:12:45.947 に答える
1

の現在の回避策は、この SO question に基づいています。つまり、次のとおりです。

    <ItemGroup>
        <DependentAssemblies Include="
            ..\ProjectA\bin\$(Configuration)\ProjectA.dll;
            ..\ProjectB\bin\$(Configuration)\ProjectB.dll;
            ..\ProjectC\bin\$(Configuration)\ProjectC.dll">
        </DependentAssemblies>
    </ItemGroup>

ただし、これは TeamBuild (すべての出力が 1 つのディレクトリに配置される) の下で機能しなくなり、依存プロジェクトの出力の名前が変更された場合にも機能しなくなります。

EDIT:ハードコーディングを少しきれいにする方法について、よりきれいな答えがあるかどうかについてのコメントも探しています:

    <PropertyGroup>
        <_TeamBuildingToSingleOutDir Condition="'$(TeamBuildOutDir)'!='' AND '$(CustomizableOutDir)'!='true'">true</_TeamBuildingToSingleOutDir>
    </PropertyGroup>

と:

    <ItemGroup>
        <DependentAssemblies 
            Condition="'$(_TeamBuildingToSingleOutDir)'!='true'"
            Include="
                ..\ProjectA\bin\$(Configuration)\ProjectA.dll;
                ..\ProjectB\bin\$(Configuration)\ProjectB.dll;
                ..\ProjectC\bin\$(Configuration)\ProjectC.dll">
        </DependentAssemblies>
        <DependentAssemblies 
            Condition="'$(_TeamBuildingToSingleOutDir)'=='true'"
            Include="
                $(OutDir)\ProjectA.dll;
                $(OutDir)\ProjectB.dll;
                $(OutDir)\ProjectC.dll">
        </DependentAssemblies>
    </ItemGroup>
于 2010-02-24T11:41:16.153 に答える