Ask a questionAsk a question
 

AnswerTeamBuild - Individual Output Directories for Each Project

  • Tuesday, November 03, 2009 10:44 PMCraig Tadlock Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    As in previous versions, in TFS 2010 when a build is performed all of the output files for every project are dumped into the same directory. Is there a new/better way to have the build system create a folder in the output directory for each application/database in a solution?

    Here is a thread about this same issue for TFS 2008...

    http://social.msdn.microsoft.com/forums/en-US/tfsbuild/thread/68620f76-0187-4f3b-a7ef-7507f6d39182/

    CT
    http://www.tadlockenterprises.com
    • Edited byCraig Tadlock Wednesday, November 04, 2009 12:31 AMbetter title
    •  

Answers

  • Saturday, November 07, 2009 9:16 PMCraig Tadlock Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    So I finally figured out a fairly easy way to do this...

    • Instead of building the solution, set the build to build the individual projects you want (including the test projects)
    • Create a custom build definition
    • In the build definition...
    • ...Move the activity "Initialize OutputDirectory" under "Cmpile Each Project"
    • ...In "Compile Each Project" create a local variable "projectName", assign this from "serverBuildProjectItem.Substring(serverBuildProjectItem.LastIndexOf("/") + 1, serverBuildProjectItem.LastIndexOf(".") - serverBuildProjectItem.LastIndexOf("/") - 1)"
    • ...Change the "Initialize OutputDirectory" to include the projectName variable: BinariesDirectory + "\" + projectName

    Here is the part of the build definition that I changed...

     <Sequence DisplayName="Compile and Test for Configuration" sap:VirtualizedContainerService.HintSize="1200,2465">
                              <Sequence.Variables>
                                <Variable x:TypeArguments="x:String" Name="outputDirectory" />
                                <Variable x:TypeArguments="x:String" Name="logFileDropLocation" />
                              </Sequence.Variables>
                              <sap:WorkflowViewStateService.ViewState>
                                <scg:Dictionary x:TypeArguments="x:String, x:Object">
                                  <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                                </scg:Dictionary>
                              </sap:WorkflowViewStateService.ViewState>
                              <Sequence DisplayName="Initialize Variables" sap:VirtualizedContainerService.HintSize="1178,146">
                                <sap:WorkflowViewStateService.ViewState>
                                  <scg:Dictionary x:TypeArguments="x:String, x:Object">
                                    <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                                  </scg:Dictionary>
                                </sap:WorkflowViewStateService.ViewState>
                                <Assign x:TypeArguments="x:String" DisplayName="Initialize LogFile Drop Location" sap:VirtualizedContainerService.HintSize="200,22" To="[logFileDropLocation]" Value="[If (platformConfiguration.IsEmpty Or BuildSettings.PlatformConfigurations.Count = 1, BuildDetail.DropLocation + &quot;\logs&quot;, If (platformConfiguration.IsPlatformEmptyOrAnyCpu, BuildDetail.DropLocation + &quot;\logs\&quot; + platformConfiguration.Configuration, BuildDetail.DropLocation + &quot;\logs\&quot; + platformConfiguration.Platform + &quot;\&quot; + platformConfiguration.Configuration))]" />
                              </Sequence>
                              <If Condition="[BuildSettings.HasProjectsToBuild]" DisplayName="If BuildSettings.HasProjectsToBuild" sap:VirtualizedContainerService.HintSize="1178,749">
                                <If.Then>
                                  <ForEach x:TypeArguments="x:String" DisplayName="For Each Project in BuildSettings.ProjectsToBuild" sap:VirtualizedContainerService.HintSize="448,648" Values="[BuildSettings.ProjectsToBuild]">
                                    <ActivityAction x:TypeArguments="x:String">
                                      <ActivityAction.Argument>
                                        <DelegateInArgument x:TypeArguments="x:String" Name="serverBuildProjectItem" />
                                      </ActivityAction.Argument>
                                      <TryCatch DisplayName="Try to Compile the Project" sap:VirtualizedContainerService.HintSize="418,545">
                                        <TryCatch.Try>
                                          <Sequence DisplayName="Compile the Project" sap:VirtualizedContainerService.HintSize="400,367">
                                            <Sequence.Variables>
                                              <Variable x:TypeArguments="x:String" Name="localProject" />
                                              <Variable x:TypeArguments="x:String" Name="projectName" />
                                            </Sequence.Variables>
                                            <sap:WorkflowViewStateService.ViewState>
                                              <scg:Dictionary x:TypeArguments="x:String, x:Object">
                                                <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                                              </scg:Dictionary>
                                            </sap:WorkflowViewStateService.ViewState>
                                            <Assign DisplayName="Assign projectName" sap:VirtualizedContainerService.HintSize="242,57">
                                              <Assign.To>
                                                <OutArgument x:TypeArguments="x:String">[projectName]</OutArgument>
                                              </Assign.To>
                                              <Assign.Value>
                                                <InArgument x:TypeArguments="x:String">[serverBuildProjectItem.Substring(serverBuildProjectItem.LastIndexOf("/") + 1, serverBuildProjectItem.LastIndexOf(".") - serverBuildProjectItem.LastIndexOf("/") - 1)]</InArgument>
                                              </Assign.Value>
                                            </Assign>
                                            <Assign x:TypeArguments="x:String" DisplayName="Initialize OutputDirectory" sap:VirtualizedContainerService.HintSize="242,22" To="[outputDirectory]" Value="[If(platformConfiguration.IsEmpty Or BuildSettings.PlatformConfigurations.Count = 1,&#xA; BinariesDirectory + &quot;\&quot; + projectName,&#xA; If(platformConfiguration.IsPlatformEmptyOrAnyCpu,&#xA;  BinariesDirectory + &quot;\&quot; + projectName + &quot;\&quot; + platformConfiguration.Configuration,&#xA;  BinariesDirectory + &quot;\&quot; + projectName + &quot;\&quot; + platformConfiguration.Platform + &quot;\&quot; + platformConfiguration.Configuration))]" />
                                            <mtbwa:ConvertWorkspaceItem DisplayName="Convert Server Path to Local Path" sap:VirtualizedContainerService.HintSize="242,22" Input="[serverBuildProjectItem]" Result="[localProject]" Workspace="[Workspace]" />
                                            <mtbwa:MSBuild CommandLineArguments="[String.Format(&quot;/p:SkipInvalidConfigurations=true {0}&quot;, MSBuildArguments)]" Configuration="[platformConfiguration.Configuration]" DisplayName="Run MSBuild for Project" GenerateVSPropsFile="[True]" sap:VirtualizedContainerService.HintSize="242,22" LogFileDropLocation="[logFileDropLocation]" OutDir="[outputDirectory]" Platform="[platformConfiguration.Platform]" Project="[localProject]" RunCodeAnalysis="[RunCodeAnalysis]" TargetsNotLogged="[New String() {&quot;GetNativeManifest&quot;, &quot;GetCopyToOutputDirectoryItems&quot;, &quot;GetTargetPath&quot;}]" ToolPlatform="[MSBuildPlatform]" Verbosity="[Verbosity]" />
                                          </Sequence>
                                        </TryCatch.Try>
                                        <TryCatch.Catches>
                                          <Catch x:TypeArguments="s:Exception" sap:VirtualizedContainerService.HintSize="404,20">
                                            <sap:WorkflowViewStateService.ViewState>
                                              <scg:Dictionary x:TypeArguments="x:String, x:Object">
                                                <x:Boolean x:Key="IsExpanded">False</x:Boolean>
                                              </scg:Dictionary>
                                            </sap:WorkflowViewStateService.ViewState>
                                            <ActivityAction x:TypeArguments="s:Exception">
                                              <ActivityAction.Argument>
                                                <DelegateInArgument x:TypeArguments="s:Exception" Name="ex" />
                                              </ActivityAction.Argument>
                                              <Sequence DisplayName="Handle Exception" sap:VirtualizedContainerService.HintSize="486,495">
                                                <sap:WorkflowViewStateService.ViewState>
                                                  <scg:Dictionary x:TypeArguments="x:String, x:Object">
                                                    <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                                                  </scg:Dictionary>
                                                </sap:WorkflowViewStateService.ViewState>
                                                <mtbwa:SetBuildProperties CompilationStatus="[Microsoft.TeamFoundation.Build.Client.BuildPhaseStatus.Failed]" DisplayName="Set CompilationStatus to Failed" sap:VirtualizedContainerService.HintSize="464,22" PropertiesToSet="CompilationStatus" />
                                                <If Condition="[CreateWorkItem]" DisplayName="If CreateWorkItem" sap:VirtualizedContainerService.HintSize="464,247">
                                                  <If.Then>
                                                    <mtbwa:InvokeForReason DisplayName="Create Work Item for non-Shelveset Builds" sap:VirtualizedContainerService.HintSize="281,146" Reason="Manual, IndividualCI, BatchedCI, Schedule, ScheduleForced, UserCreated">
                                                      <mtbwa:OpenWorkItem AssignedTo="[BuildDetail.RequestedFor]" Comment="[&quot;This work item was created by TFS Build on a build failure.&quot;]" CustomFields="[New Dictionary(Of String, String) From { {&quot;System.Reason&quot;, &quot;Build Failure&quot;}, {&quot;Microsoft.VSTS.TCM.ReproSteps&quot;, &quot;Start the build using TFS Build&quot;}, {&quot;Priority&quot;, &quot;1&quot;}, {&quot;Severity&quot;, &quot;1 - Critical&quot;} }]" DisplayName="Create Work Item" sap:VirtualizedContainerService.HintSize="200,22" Title="[String.Format(&quot;Build Failure in Build: {0}&quot;, BuildDetail.BuildNumber)]" Type="[&quot;Bug&quot;]" />
                                                    </mtbwa:InvokeForReason>
                                                  </If.Then>
                                                </If>
                                                <Rethrow DisplayName="Rethrow the exception so the build will stop" sap:VirtualizedContainerService.HintSize="464,22" />
                                              </Sequence>
                                            </ActivityAction>
                                          </Catch>
                                        </TryCatch.Catches>
                                      </TryCatch>
                                    </ActivityAction>
                                  </ForEach>
                                </If.Then>
                              </If>
    


    Good luck!

    CT
    http://www.tadlockenterprises.com
    • Marked As Answer byCraig Tadlock Saturday, November 07, 2009 9:17 PM
    •  

All Replies

  • Saturday, November 07, 2009 4:01 AMCraig Tadlock Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Has Code
    After looking into this I dont see a simple way to do this. It doesnt appear that modifying the project file as shown below to detect if the build is a team build works in TFS 2010. It doesnt look like the property $(TeamBuildOutDir) exists anymore. You can make this all work, its just going to take some decent modifications to he build process template.

    Please someone correct me if I'm wrong here.

    <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
        <OutputPath Condition=" '$(TeamBuildOutDir)'=='' ">bin\debug\</OutputPath>
        <OutputPath Condition=" '$(TeamBuildOutDir)'!='' ">$(TeamBuildOutDir)foo\bin\debug</OutputPath>
    </PropertyGroup> 
    

    As a rant, doesnt anyone know why this is the default behavior? What value could it possibly provide? We all think in terms of deployable applications (web sites, console applications, databases,...) so why does TeamBuild throw it all together? I want to be able to modify the script such that I can deploy these components as individual units.

    Arg!

    CT
    http://www.tadlockenterprises.com
  • Saturday, November 07, 2009 9:16 PMCraig Tadlock Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     AnswerHas Code
    So I finally figured out a fairly easy way to do this...

    • Instead of building the solution, set the build to build the individual projects you want (including the test projects)
    • Create a custom build definition
    • In the build definition...
    • ...Move the activity "Initialize OutputDirectory" under "Cmpile Each Project"
    • ...In "Compile Each Project" create a local variable "projectName", assign this from "serverBuildProjectItem.Substring(serverBuildProjectItem.LastIndexOf("/") + 1, serverBuildProjectItem.LastIndexOf(".") - serverBuildProjectItem.LastIndexOf("/") - 1)"
    • ...Change the "Initialize OutputDirectory" to include the projectName variable: BinariesDirectory + "\" + projectName

    Here is the part of the build definition that I changed...

     <Sequence DisplayName="Compile and Test for Configuration" sap:VirtualizedContainerService.HintSize="1200,2465">
                              <Sequence.Variables>
                                <Variable x:TypeArguments="x:String" Name="outputDirectory" />
                                <Variable x:TypeArguments="x:String" Name="logFileDropLocation" />
                              </Sequence.Variables>
                              <sap:WorkflowViewStateService.ViewState>
                                <scg:Dictionary x:TypeArguments="x:String, x:Object">
                                  <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                                </scg:Dictionary>
                              </sap:WorkflowViewStateService.ViewState>
                              <Sequence DisplayName="Initialize Variables" sap:VirtualizedContainerService.HintSize="1178,146">
                                <sap:WorkflowViewStateService.ViewState>
                                  <scg:Dictionary x:TypeArguments="x:String, x:Object">
                                    <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                                  </scg:Dictionary>
                                </sap:WorkflowViewStateService.ViewState>
                                <Assign x:TypeArguments="x:String" DisplayName="Initialize LogFile Drop Location" sap:VirtualizedContainerService.HintSize="200,22" To="[logFileDropLocation]" Value="[If (platformConfiguration.IsEmpty Or BuildSettings.PlatformConfigurations.Count = 1, BuildDetail.DropLocation + &quot;\logs&quot;, If (platformConfiguration.IsPlatformEmptyOrAnyCpu, BuildDetail.DropLocation + &quot;\logs\&quot; + platformConfiguration.Configuration, BuildDetail.DropLocation + &quot;\logs\&quot; + platformConfiguration.Platform + &quot;\&quot; + platformConfiguration.Configuration))]" />
                              </Sequence>
                              <If Condition="[BuildSettings.HasProjectsToBuild]" DisplayName="If BuildSettings.HasProjectsToBuild" sap:VirtualizedContainerService.HintSize="1178,749">
                                <If.Then>
                                  <ForEach x:TypeArguments="x:String" DisplayName="For Each Project in BuildSettings.ProjectsToBuild" sap:VirtualizedContainerService.HintSize="448,648" Values="[BuildSettings.ProjectsToBuild]">
                                    <ActivityAction x:TypeArguments="x:String">
                                      <ActivityAction.Argument>
                                        <DelegateInArgument x:TypeArguments="x:String" Name="serverBuildProjectItem" />
                                      </ActivityAction.Argument>
                                      <TryCatch DisplayName="Try to Compile the Project" sap:VirtualizedContainerService.HintSize="418,545">
                                        <TryCatch.Try>
                                          <Sequence DisplayName="Compile the Project" sap:VirtualizedContainerService.HintSize="400,367">
                                            <Sequence.Variables>
                                              <Variable x:TypeArguments="x:String" Name="localProject" />
                                              <Variable x:TypeArguments="x:String" Name="projectName" />
                                            </Sequence.Variables>
                                            <sap:WorkflowViewStateService.ViewState>
                                              <scg:Dictionary x:TypeArguments="x:String, x:Object">
                                                <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                                              </scg:Dictionary>
                                            </sap:WorkflowViewStateService.ViewState>
                                            <Assign DisplayName="Assign projectName" sap:VirtualizedContainerService.HintSize="242,57">
                                              <Assign.To>
                                                <OutArgument x:TypeArguments="x:String">[projectName]</OutArgument>
                                              </Assign.To>
                                              <Assign.Value>
                                                <InArgument x:TypeArguments="x:String">[serverBuildProjectItem.Substring(serverBuildProjectItem.LastIndexOf("/") + 1, serverBuildProjectItem.LastIndexOf(".") - serverBuildProjectItem.LastIndexOf("/") - 1)]</InArgument>
                                              </Assign.Value>
                                            </Assign>
                                            <Assign x:TypeArguments="x:String" DisplayName="Initialize OutputDirectory" sap:VirtualizedContainerService.HintSize="242,22" To="[outputDirectory]" Value="[If(platformConfiguration.IsEmpty Or BuildSettings.PlatformConfigurations.Count = 1,&#xA; BinariesDirectory + &quot;\&quot; + projectName,&#xA; If(platformConfiguration.IsPlatformEmptyOrAnyCpu,&#xA;  BinariesDirectory + &quot;\&quot; + projectName + &quot;\&quot; + platformConfiguration.Configuration,&#xA;  BinariesDirectory + &quot;\&quot; + projectName + &quot;\&quot; + platformConfiguration.Platform + &quot;\&quot; + platformConfiguration.Configuration))]" />
                                            <mtbwa:ConvertWorkspaceItem DisplayName="Convert Server Path to Local Path" sap:VirtualizedContainerService.HintSize="242,22" Input="[serverBuildProjectItem]" Result="[localProject]" Workspace="[Workspace]" />
                                            <mtbwa:MSBuild CommandLineArguments="[String.Format(&quot;/p:SkipInvalidConfigurations=true {0}&quot;, MSBuildArguments)]" Configuration="[platformConfiguration.Configuration]" DisplayName="Run MSBuild for Project" GenerateVSPropsFile="[True]" sap:VirtualizedContainerService.HintSize="242,22" LogFileDropLocation="[logFileDropLocation]" OutDir="[outputDirectory]" Platform="[platformConfiguration.Platform]" Project="[localProject]" RunCodeAnalysis="[RunCodeAnalysis]" TargetsNotLogged="[New String() {&quot;GetNativeManifest&quot;, &quot;GetCopyToOutputDirectoryItems&quot;, &quot;GetTargetPath&quot;}]" ToolPlatform="[MSBuildPlatform]" Verbosity="[Verbosity]" />
                                          </Sequence>
                                        </TryCatch.Try>
                                        <TryCatch.Catches>
                                          <Catch x:TypeArguments="s:Exception" sap:VirtualizedContainerService.HintSize="404,20">
                                            <sap:WorkflowViewStateService.ViewState>
                                              <scg:Dictionary x:TypeArguments="x:String, x:Object">
                                                <x:Boolean x:Key="IsExpanded">False</x:Boolean>
                                              </scg:Dictionary>
                                            </sap:WorkflowViewStateService.ViewState>
                                            <ActivityAction x:TypeArguments="s:Exception">
                                              <ActivityAction.Argument>
                                                <DelegateInArgument x:TypeArguments="s:Exception" Name="ex" />
                                              </ActivityAction.Argument>
                                              <Sequence DisplayName="Handle Exception" sap:VirtualizedContainerService.HintSize="486,495">
                                                <sap:WorkflowViewStateService.ViewState>
                                                  <scg:Dictionary x:TypeArguments="x:String, x:Object">
                                                    <x:Boolean x:Key="IsExpanded">True</x:Boolean>
                                                  </scg:Dictionary>
                                                </sap:WorkflowViewStateService.ViewState>
                                                <mtbwa:SetBuildProperties CompilationStatus="[Microsoft.TeamFoundation.Build.Client.BuildPhaseStatus.Failed]" DisplayName="Set CompilationStatus to Failed" sap:VirtualizedContainerService.HintSize="464,22" PropertiesToSet="CompilationStatus" />
                                                <If Condition="[CreateWorkItem]" DisplayName="If CreateWorkItem" sap:VirtualizedContainerService.HintSize="464,247">
                                                  <If.Then>
                                                    <mtbwa:InvokeForReason DisplayName="Create Work Item for non-Shelveset Builds" sap:VirtualizedContainerService.HintSize="281,146" Reason="Manual, IndividualCI, BatchedCI, Schedule, ScheduleForced, UserCreated">
                                                      <mtbwa:OpenWorkItem AssignedTo="[BuildDetail.RequestedFor]" Comment="[&quot;This work item was created by TFS Build on a build failure.&quot;]" CustomFields="[New Dictionary(Of String, String) From { {&quot;System.Reason&quot;, &quot;Build Failure&quot;}, {&quot;Microsoft.VSTS.TCM.ReproSteps&quot;, &quot;Start the build using TFS Build&quot;}, {&quot;Priority&quot;, &quot;1&quot;}, {&quot;Severity&quot;, &quot;1 - Critical&quot;} }]" DisplayName="Create Work Item" sap:VirtualizedContainerService.HintSize="200,22" Title="[String.Format(&quot;Build Failure in Build: {0}&quot;, BuildDetail.BuildNumber)]" Type="[&quot;Bug&quot;]" />
                                                    </mtbwa:InvokeForReason>
                                                  </If.Then>
                                                </If>
                                                <Rethrow DisplayName="Rethrow the exception so the build will stop" sap:VirtualizedContainerService.HintSize="464,22" />
                                              </Sequence>
                                            </ActivityAction>
                                          </Catch>
                                        </TryCatch.Catches>
                                      </TryCatch>
                                    </ActivityAction>
                                  </ForEach>
                                </If.Then>
                              </If>
    


    Good luck!

    CT
    http://www.tadlockenterprises.com
    • Marked As Answer byCraig Tadlock Saturday, November 07, 2009 9:17 PM
    •  
  • Monday, November 16, 2009 9:42 AMCraig Tadlock Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I've taken this on personally to develop a build process workflow that actually meets an n-tier system's needs. You can follow the progress on my site...

    http://www.tadlockenterprises.com/2009/11/tfs-2010-teambuild-deployment-fail/

    CT
    http://www.tadlockenterprises.com