web-dev-qa-db-ja.com

TFS 2010で各プロジェクトを個別のディレクトリにビルドするにはどうすればよいですか?

私たちのプロジェクトでは、TFSビルドで、すべてのファイルを1つのフラットな構造にドロップするのではなく、各プロジェクトをドロップフォルダーの下の独自のフォルダーに配置する必要があります。説明のために、次のようなものを見たいと思います。

DropFolder/
  Foo/
    foo.exe
  Bar/
    bar.dll
  Baz
    baz.dll

これは基本的に質問と同じ質問です ここ ですが、ワークフローベースのビルドを使用しているため、これらのソリューションは機能していないようです。 CustomizableOutDirプロパティを使用したソリューションは、私たちにとって最適に機能するように見えましたが、そのプロパティを認識させることができません。コマンドライン引数(/ p:CustomizableOutDir = true)としてMSBuildに渡すようにワークフローをカスタマイズしましたが、MSBuildはそれを無視し、ワークフローによって指定されたOutDirに出力を配置しているようです。

ビルドログを確認したところ、CustomizableOutDirプロパティとOutDirプロパティの両方がMSBuildのコマンドライン引数で設定されていることがわかりました。最後にファイルをTeamBuildOutDirにコピーできるように、OutDirを渡す必要があります。

CustomizableOutDirパラメーターが認識されない理由、またはこれを実現するためのより良い方法があるかどうかはわかりませんか?

22

私はそれを行うための良い方法を考え出しました。 OutDirはワークフロー内で任意に設定できるため、空の文字列に設定すると、MSBuildは代わりにプロジェクト固有のOutputPathを使用することがわかりました。これにより、柔軟性が大幅に向上します。これが私のソリューション全体です(デフォルトのビルドワークフローに基づいています):

Run MSBuildタスクで、OutDirを空の文字列に設定します。同じタスクで、CommandLineArgumentsを次のように設定します。これにより、プロジェクトからTFSのデフォルトのOutDirへの参照を取得できます。

String.Format("/p:CommonOutputPath=""{0}\\""", outputDirectory)

ドロップフォルダにコピーする各プロジェクトで、次のようにOutputPathを設定します。

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <OutputPath Condition=" '$(CommonOutputPath)'=='' ">bin\Release\</OutputPath>
    <OutputPath Condition=" '$(CommonOutputPath)'!='' ">$(CommonOutputPath)YourProjectName\bin\Release\</OutputPath>
</PropertyGroup>

すべてをチェックインすると、各プロジェクトをドロップフォルダーの下の独自のフォルダーにデプロイする作業ビルドができているはずです。

14

私もこの問題を解決しました。このスレッドの既存のソリューションよりもクリーンだと思います。

  • _Run MSBuild for Project_アクティビティの前に、Assignアクティビティを追加しました:projectName = Regex.Replace(New FileInfo(localProject).Name, "\.sln$", "")
  • 次に、_Create Directory_アクティビティを追加しました:_outputDirectory + "\" + projectName_
  • 最後に、MSBuildアクティビティで、OutDirを_outputDirectory + "\" + projectName_に変更しました。

テンプレートには、エージェント上に構築されている_.sln_ファイルのフルパス名(例:_c:\build\path\to\MySolution.sln_)がすでにlocalProjectに入力されています。割り当てアクティビティはパスと内線番号を切り取り、出力をMySolutionに配置します。 projectName変数を作成し、_System.Text.RegularExpressions_と_System.IO_をインポートする必要があります。

OPのソリューションに対する利点は、各_.csproj_を編集する必要がないことです。その情報は、ソリューションファイルの名前から推測されます。

8

CSLAシリアル化に同じ名前のSilverlightライブラリと.Netライブラリがあるという問題を回避するために、これを行う必要がありました。ライブラリが上書きされ、テストが失敗します。

Jonathanの答えと Jim Lambの投稿 を使用しましたが、OutDirも空に設定する必要があることがわかりました。

したがって、MSBuildアクティビティに対してこれらのパラメーターを実行する必要があります(次のマクロを使用する場合は、Cleanのアクティビティパラメーターも設定する必要があります。そうしないと、OutputPathが設定されていないという警告が表示されます)。

  • CommandLineArgumentsをString.Format("/p:SkipInvalidConfigurations=true;TeamBuildOutDir=""{0}"" {1}", BinariesDirectory, MSBuildArguments)に設定します
  • OutDirを空に設定します(以前はBinariesDirectoryでした)

また、Visual Studioで実行できるマクロを作成しました。このマクロは、構成からOutputPathを削除し、次のようにすべての構成のOutputPathを含むPropertyGroupを追加します。

<PropertyGroup Label="OutputPathLabel">
  <OutputPath Condition="'$(TeamBuildOutDir)'=='' ">bin\$(Configuration)\</OutputPath>
  <OutputPath Condition="'$(TeamBuildOutDir)'!='' ">$(TeamBuildOutDir)\$(SolutionName)\$(MSBuildProjectName)\$(Configuration)\</OutputPath>
</PropertyGroup>

これがマクロです:

Public Sub SetTeamBuildOutDir()

    Dim projectObjects = DTE.Solution.Projects

    For Each project In projectObjects

        If project.ProjectItems IsNot Nothing Then
            SetTeamBuildOutDirRecursive(project)
        End If
    Next

End Sub

Sub SetTeamBuildOutDirRecursive(ByVal proj As Project)
    If proj.ConfigurationManager Is Nothing Then
        For Each subProj As ProjectItem In proj.ProjectItems
            If subProj.SubProject IsNot Nothing Then
                SetTeamBuildOutDirRecursive(subProj.SubProject)
            End If
        Next
    Else
        SetTeamBuildOutDir(proj)
    End If

End Sub

Sub SetTeamBuildOutDir(ByVal project As Project)
    'Do not handle .vdproj
    If project.FullName.ToLower().EndsWith(".vdproj") Then
        Exit Sub
    End If

    Dim needToSave = False
    Dim msproject = ProjectRootElement.Open(project.FullName)
    Dim outputPathGroupExists = False
    Dim outputPropertyGroup As ProjectPropertyGroupElement = Nothing
    Dim lastConfigPropertyGroup As ProjectPropertyGroupElement = Nothing

    For Each propertyGroup In msproject.PropertyGroups

        If propertyGroup.Label = "OutputPathLabel" Then
            outputPathGroupExists = True
            outputPropertyGroup = propertyGroup
        End If

        If Not String.IsNullOrEmpty(propertyGroup.Condition) AndAlso _
            propertyGroup.Condition.TrimStart().StartsWith("'$(Configuration)") Then

            lastConfigPropertyGroup = propertyGroup
        End If

        'Remove the OutputPath from the configurations
        Dim outputPathElement As ProjectPropertyElement = Nothing
        For Each element As ProjectPropertyElement In propertyGroup.Children
            If element.Name = "OutputPath" Then
                outputPathElement = element
            End If
        Next
        If outputPathElement IsNot Nothing Then
            propertyGroup.RemoveChild(outputPathElement)
            needToSave = True
        End If
    Next

    'If we want to always remove the group and add it back (in case of modifications to the group)
    'If outputPathGroupExists Then
    '    msproject.RemoveChild(outputPropertyGroup)
    '    outputPathGroupExists = False
    'End If

    If Not outputPathGroupExists Then
        Dim propertyGroup = msproject.CreatePropertyGroupElement()
        propertyGroup.Label = "OutputPathLabel"
        'Need to insert the PropertyGroup before the CSharp targets are included
        msproject.InsertAfterChild(propertyGroup, lastConfigPropertyGroup)

        Dim isDbProject = project.FullName.ToLower().EndsWith(".dbproj")

        Dim outputEmpty = propertyGroup.AddProperty("OutputPath", IIf(Not isDbProject, "bin\$(Configuration)\", "sql\$(Configuration)\"))
        outputEmpty.Condition = "'$(TeamBuildOutDir)'=='' "

        Dim outputTeamBuild = propertyGroup.AddProperty("OutputPath", "$(TeamBuildOutDir)\$(SolutionName)\$(MSBuildProjectName)\$(Configuration)\")
        outputTeamBuild.Condition = "'$(TeamBuildOutDir)'!='' "

        needToSave = True
    End If

    If needToSave Then
        'checkout the project file with tfs
        Shell("C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE\tf.exe checkout " & project.FullName, , True)

        'Save the project file
        msproject.Save()
    End If
End Sub

お役に立てれば!!!

4

ここでの手順では、プロジェクトファイルを変更する必要はありません http://lajak.wordpress.com/2011/05/07/customize-binaries-folder-in-tfs-team-build/

2
ak7

これは、ソースファイルやプロジェクトファイルを変更する必要のない非常に単純なソリューションです。ビルド定義の[プロセス]-> [ビルドするプロジェクト]を設定するときは、ビルドするプロジェクトで.slnファイルを指定する代わりに、各プロジェクト(.csprojまたは.vbproj)を追加します。ワークフローの「MSBuildforProjectの実行」ステップ内で、OutDirプロパティを次のように変更します。

outputDirectory + "/" + serverBuildProjectItem.Substring(serverBuildProjectItem.LastIndexOf("/"), serverBuildProjectItem.Length - serverBuildProjectItem.LastIndexOf("/")).Replace(".csproj", String.Empty)

これにより、各プロジェクトのビルド出力が、プロジェクトにちなんで名付けられたサブディレクトリに配置されます。

1
Andy Morris

チームビルド2010で最新バージョンのmsbuildを使用できるかどうかはわかりませんが、新しいプロパティ/ p:GenerateProjectSpecificOutputFolder = trueを指定すると、各プロジェクトのビットが$(OutDir)\ $(ProjectName)\にドロップされます。

1
Richard Spence

My Solutionの各実行可能ファイルに対してNugetから パッケージPublishedApplications をインストールし、ビルド中に各プロジェクトの_PublishedApplicationsフォルダーの下にサブフォルダーを作成しました。

TFS/MSBuildで出力ファイルを別々のフォルダーに配置することを試したことがないので、直接答えることはできません。ただし、ここに私があなたのリンクで見つけなかったいくつかの提案があります:

  • 必要なファイルを「デプロイメント」構造にコピーするプロジェクトに、ビルド後の手順を追加できます。 (もちろん、これは開発マシンでも実行されるため、面倒な場合があります)。ライブラリにはこのアプローチを使用します。ライブラリはビルドされてから、他のプロジェクトが参照できるように共有ライブラリ(バイナリ)フォルダーにコピーされます。

  • MSBuildターゲットを追加して、必要なファイルを必要な場所にコピーできます。デフォルトの「コピーしてドロップフォルダー」ターゲットをオーバーライドして、ファイルを別のフォルダーにコピーし、難読化し、デジタル署名し、インストーラーに組み込み、インストーラーにデジタル署名してからコピーします(およびその他の便利なもの難読化マップファイル)およびドロップフォルダーへの最後のビルド以降の変更のリスト。最終的に、独自のビルド後のターゲットを追加すると、何をどこに配置するかを最大限に制御できます。 (マイナス面として、ビルド後のコピーターゲットに新しいdllまたはexeを手動で追加する必要がある場合があります。これはイライラする可能性があります)

0
Jason Williams

これは、ソースファイルやプロジェクトファイルを変更する必要のない、もう1つの非常に単純なソリューションです。ビルド定義の[プロセス]-> [ビルドするプロジェクト]を設定するときは、ビルドするプロジェクトで.slnファイルを指定する代わりに、各プロジェクト(.csprojまたは.vbproj)を追加します。ワークフローの「MSBuildforProjectの実行」ステップ内で、OutDirプロパティを次のように変更します。

OutputDirectory + "\" + System.IO.Path.GetFileNameWithoutExtension(serverBuildProjectItem)
0
Rajani