Frage

Im Rahmen einer Lösung viele Projekte enthält, habe ich ein Projekt, dass Verweise (über einen <ProjectReference> drei weitere Projekte in der Lösung, sowie einige andere). Im AfterBuild, ich brauche die Ausgänge von drei spezifischen abhängigen Projekten an einem anderen Ort zu kopieren.

über verschiedene SO Antworten usw. die Art und Weise ließ ich mich zu erreichen, auf das war:

    <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" />

Allerdings lief ich in Probleme. Die Aufgabe des <MSBuild IncrementalClean Schritt endet eine Anzahl der Ausgänge des ProjectC löschen. Wenn dies unter VS2008 ausgeführt wird, eine build.force Datei im obj/Debug Ordner ProjectC abgelegt werden, die dann lösen wieder aufgebauten ProjectC bekommen, wenn ich eine bauen auf der gesamten Lösung, wenn das Projekt mit diesem AfterBuild Ziel zu tun, während, wenn man schließt dieses Projekt aus dem Build, es [richtig] löst nicht ein von ProjectC wieder aufbauen (und kritisch ein Umbau der alle unterhalte ProjectC). Dies kann VS-spezifische Tricks in diesem Fall, die nicht im Rahmen eines Teambuild oder anderen Kommandozeilen MSBuild Aufruf (aber die am weitesten verbreiteten Anwendung wird über VS so dass ich dies so oder so lösen muß) auftreten würde,

Die abhängigen Projekte (und der Rest der Lösung im Allgemeinen) haben alle interaktiv mit VS erstellt worden ist, und somit die ProjectRefences enthält relative Pfade usw. habe ich erwähnt, dies zu verursachen Probleme ist wahrscheinlich gesehen - aber ohne einen vollständigen Erklärung, warum, oder wenn es behoben werden kann oder wie um ihn zu arbeiten. Mit anderen Worten, bin interessiert ich nicht wirklich in z.B. die ProjectReference Pfade zu absoluten Pfade von Hand-Bearbeitung der CSPROJ umwandelt.

Während es durchaus möglich ist, mache ich etwas Dummes und jemand wird sofort darauf hinweisen, was es ist (das wäre gut), seien Sie versichert, ich habe viel Zeit damit verbracht brütete über /v:diag Ausgänge usw. (obwohl ich versucht haben zu baut eine repro von Grunde auf - dies ist im Zusammenhang mit einem relativ komplexen Gesamt Build)

War es hilfreich?

Lösung

Wie bereits in meinem Kommentar, rief GetTargetPath auf dem referenzierte Projekt gibt nur die primäre Ausgabebaugruppe des Projektes. Um alle die referenzierten kopier lokalen Versammlungen des referenzierten Projekt zu bekommen es ist ein bisschen unordentlicher.

Fügen Sie folgende zu jedem Projekt, dass Sie verweisen, dass Sie die CopyLocals von erhalten möchten:

    <Target
    Name="ComputeCopyLocalAssemblies"
    DependsOnTargets="ResolveProjectReferences;ResolveAssemblyReferences"
    Returns="@(ReferenceCopyLocalPaths)" /> 

Meine besondere Situation ist, dass ich benötigen, um die Pipeline-Ordnerstruktur für System.AddIn im Ordner ist mein Top-Level-Host-Projekt neu zu erstellen. Das ist ein bisschen chaotisch und ich war nicht glücklich mit der MSDN-Lösungen vorgeschlagen, mit dem OutputPath von Ausmisten - wie die Pausen auf unserem Build-Server und verhindert, dass die Ordnerstruktur in einem anderen Projekt zu schaffen (zB einen Systemtest)

So zusammen mit dem obigen Ziel Zugabe (unter Verwendung eines .targets Imports), habe ich Folgendes in einer .targets-Datei von jedem „host“ importiert, die die Pipeline-Ordner muss erstellt:

<Target
    Name="ComputePipelineAssemblies"
    BeforeTargets="_CopyFilesMarkedCopyLocal"
    Outputs="%(ProjectReference.Identity)">

    <ItemGroup>
        <_PrimaryAssembly Remove="@(_PrimaryAssembly)" />
        <_DependentAssemblies Remove="@(_DependentAssemblies)" />
    </ItemGroup>

    <!--The Primary Output of the Pipeline project-->
    <MSBuild Projects="%(ProjectReference.Identity)"
             Targets="GetTargetPath"
             Properties="Configuration=$(Configuration)"
             Condition=" '%(ProjectReference.PipelineFolder)' != '' ">
        <Output TaskParameter="TargetOutputs"
                ItemName="_PrimaryAssembly" />
    </MSBuild>

    <!--Output of any Referenced Projects-->
    <MSBuild Projects="%(ProjectReference.Identity)"
             Targets="ComputeCopyLocalAssemblies"
             Properties="Configuration=$(Configuration)"
             Condition=" '%(ProjectReference.PipelineFolder)' != '' ">
        <Output TaskParameter="TargetOutputs"
                ItemName="_DependentAssemblies" />
    </MSBuild>

    <ItemGroup>
        <ReferenceCopyLocalPaths Include="@(_PrimaryAssembly)"
                                 Condition=" '%(ProjectReference.PipelineFolder)' != '' ">
            <DestinationSubDirectory>%(ProjectReference.PipelineFolder)</DestinationSubDirectory>
        </ReferenceCopyLocalPaths>
        <ReferenceCopyLocalPaths Include="@(_DependentAssemblies)"
                                 Condition=" '%(ProjectReference.PipelineFolder)' != '' ">
            <DestinationSubDirectory>%(ProjectReference.PipelineFolder)</DestinationSubDirectory>
        </ReferenceCopyLocalPaths>
    </ItemGroup>
</Target>

Ich muß auch die erforderlichen PipelineFolder Meta-Daten zu den eigentlichen Projektreferenzen hinzuzufügen. Zum Beispiel:

    <ProjectReference Include="..\Dogs.Pipeline.AddInSideAdapter\Dogs.Pipeline.AddInSideAdapter.csproj">
        <Project>{FFCD0BFC-5A7B-4E13-9E1B-8D01E86975EA}</Project>
        <Name>Dogs.Pipeline.AddInSideAdapter</Name>
        <Private>False</Private>
        <PipelineFolder>Pipeline\AddInSideAdapter\</PipelineFolder>
    </ProjectReference>

Andere Tipps

Ihre ursprüngliche Lösung sollte einfach funktionieren, indem

Targets="Build"

Targets="GetTargetPath"

Das GetTargetPath Ziel gibt einfach die TargetPath Eigenschaft und erfordert keine Gebäude.

Sie können Ihre Dateien in ProjectC schützen, wenn Sie ein Ziel wie dieser erste Anruf:

  <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>

aktuelle Problemumgehung basiert auf dieser Frage SO , das heißt, ich habe:

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

wird dies jedoch unter Teambuild brechen (wo alle die Ausgänge in einem Verzeichnis am Ende), und auch wenn die Namen von einem der Ausgänge der abhängigen Projekte ändern.

EDIT: auch die Suche nach allen möglichen Anmerkungen, ob es eine sauberere Antwort, wie Sie den Hardcoding machen etwas sauberer als:

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

und

    <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>
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top