Working with multiple team projects in Team Build

 

 

Building solutions that reference to assemblies belonging to different team project

 

Scenario

 

Assume that we two projects (ConsoleApplication1 and ConsoleApplication2) under team project (TP1) and they are using the assembly (commonlibrary.dll) that is checked in under a different team project (TP2). Let us assume the corresponding paths under version control are

 

$/TP1/Framework/Common/v2.0/commonlibrary.dll

$/TP2/Main/ConsoleApplication1/ConsoleApplication1.sln

$/TP2/Main/ConsoleApplication1/ConsoleApplication1.sln

 

Note: please make sure that you have used File Reference to add the reference for commonlibrary.dll and CopyLocal option is set to true. Otherwise your desktop build scenario will be broken.

 

Custom steps to enable building the project

  • Create the BuiltType “Type1” for TP2.
  • Check out the Tfsbuild.proj file for “Type1” build type.
  • Reset the following property. This is done to skip invoking the default tasks to delete and recreate workspace on the build machine.

<SkipInitializeWorkspace>true</SkipInitializeWorkspace>

  • Define the new property. This is just for the user convenience and will be used in the custom target “BeforeGet” (mentioned below)

<TfCommand>$(TeamBuildRefPath)\..\tf.exe</TfCommand>

  • Define the folder mappings item group. (You are responsible for giving the correct local paths for the build machine. Please note that multiple mappings can not share the same local folder and will result in MappingConflictException in the CreateWorkspace task. Another recommendation is to avoid mapping to $(SolutionRoot). This is because if while creating workspace, task detects overlapping local paths, it will try to merge the local paths and screw up the relative paths. Please note that I have not explored the cloaking option.

<ItemGroup>

<Map Include="$/TP2/Main">

<LocalPath>$(SolutionRoot)\Main</LocalPath>

</Map>

<Map Include="$/TP1/Framework">

<LocalPath>$(SolutionRoot)\Framework</LocalPath>

</Map>

</ItemGroup>

  • Override the “BeforeGet” target.

    <Target Name="BeforeGet">   

    <!— to remove any workspace that exist with the same name, from some previous build à

    <DeleteWorkspaceTask

        TeamFoundationServerUrl="$(TeamFoundationServerUrl)"

        Name="$(WorkspaceName)" />

   

 

    <!— create the workspace with default mapping that maps $(SolutionRoot) to $/ à

    <Exec

      WorkingDirectory="$(SolutionRoot)"

      Command="&quot;$(TfCommand)&quot; workspace /new $(WorkspaceName) /server:$(TeamFoundationServerUrl)"/>

 

   

    <!— task will add the folder mappings corresponding to items define in step 5 à

    <Exec

      WorkingDirectory="$(SolutionRoot)"

      Command="&quot;$(TfCommand)&quot; workfold /map /workspace:$(WorkSpaceName) /server:$(TeamFoundationServerUrl) &quot;%(Map.Identity)&quot; &quot;%(Map.LocalPath)&quot;"/>

 

 

    <!— remove the default mapping ( $(SolutionRoot) ß> $/)that was created initially. Otherwise all the team projects will be synced under the $(SolutionRoot) à  

    <Exec

     WorkingDirectory="$(SolutionRoot)"

     Command="&quot;$(TfCommand)&quot; workfold /unmap /workspace:$(WorkSpaceName) &quot;$(SolutionRoot)&quot;"/>

 

    </Target>

 

  •  Verify that sln paths (SolutionToBuild itemgroup) for correct relative paths

<SolutionToBuild Include="$(SolutionRoot)\Main\ConsoleApplication1\ConsoleApplication1.sln" />

<SolutionToBuild Include="$(SolutionRoot)\Main\ConsoleApplication2\ConsoleApplication2.sln" />

  • Similarly verify the vsmdi paths (MetaDataFile itemgroup) for correct relative paths.
  • Checkin the tfsbuild.proj file and launch the build.

 

Recommendations

  • Please make sure that CopyLocal option is set for the file reference.
  • Use File reference to add references for assemblies belonging to different team projects. Sometime these reference paths will be broken because the relative path on the build machine is different from the one mentioned in the csproj file of your project. In such cases you need to specify the correct location of the external assembly. You can easily do it by defining “AdditionalReferencePath” item pointing to the folder containing the assembly.
  • Please try to avoid mapping directly to “$(SolutionRoot)”. Still if your “Map” item group contains any working folder mapping that points to only “$(SolutionRoot)”, then you need to remove the following line from the BeforeGet target :-

<Exec Command="&quot;$(TfCommand)&quot; workfold /unmap /workspace:$(WorkSpaceName) &quot;$(SolutionRoot)&quot;" WorkingDirectory="$(SolutionRoot)"/>   

References

 

Other interesting posts on the related/same issue are [post] [post1] [post2] [post3]

Comments

  • Anonymous
    February 01, 2006
    Great post!

    I’m having a problem in how to get my test cases to run after running a build. Here’s what I’m trying to do:

    Project
    |--Dev
    |--Site
    |--UnitTests
    |--Docs
    |--Tools
    |--Test
    |--Automations
    |--Docs
    |--TRD
    |--Spec

    We need to build the Site, and run the Automations in the Test folder, but don’t want to load everything under Project, so we’re trying to selectively include the sections we want.

    As such, I want to include the following Map node in my Build .proj file
    <Map Include="$/Project/Main/Dev/Site">
    <LocalPath>$(SolutionRoot)Site</LocalPath>
    </Map>
    <Map Include="$/Project/Main/Test">
    <LocalPath>$(SolutionRoot)Test</LocalPath>
    </Map>

    However, doing this causes me to get a OutOfMemoryException after about 5 minutes of the build server trying to get sources. Even when I get rid of the second map element, this happens. In fact, any time I map LocalPath to anything other than “$(SolutionRoot)”, I get the exception. I notice that you have mapped successfully to $(SolutionRoot)Main, do you know why I would be seeing the problems I'm seeing? Thank you very much!

    -Jeff

  • Anonymous
    February 01, 2006
    Sorry, the above folder structure should show "Project" as highest level. Dev, Test, and Docs should be second level, and everything else is third level.

    Project
    |--Dev
    |---|--Site
    |---|--UnitTests
    |---|--Docs
    |---|--Tools
    |--Test
    |---|--Automations
    |--Docs
    |---|--TRD
    |---|--Spec

  • Anonymous
    February 01, 2006
    Jeff,

    It looks like you are interested in selectively sync specific folders and not download everything. Moreover I am assuming everything in under same team project. Please check the post for the solution -
    http://blogs.msdn.com/manishagarwal/archive/2005/10/13/480584.aspx

    Hope it helps

  • Anonymous
    February 03, 2006
    I'm afraid this didn't work, at least not what I expected it to do. For example, i added the item

    <InternalMapping ServerItem="$/Project/Site/Main/Docs" Type="Cloak"/>

    Then I checked the sources folder in the build location, and the docs folder was still there, as it was previously. My goal is simply to keep from 'getting' folders that arn't necessary for this build, such as the Docs folder. Am I doing something wrong? Thanks for the help!

  • Anonymous
    April 05, 2006
    http://blogs.msdn.com/manishagarwal/archive/2005/12/22/506635.aspx

  • Anonymous
    May 20, 2006
    One of the challenges we hadn&amp;rsquo;t figured out was how to deal with the case where Team Project B...

  • Anonymous
    July 20, 2006
    Swap the map and unmap elements in BeforeGet and it works.

    See:
    http://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=367208&SiteID=1

  • Anonymous
    August 29, 2006
    Last week, the folks at Vertigo Software wrote a couple of really good posts involving Team Build.
    The...

  • Anonymous
    March 10, 2007
    Hi Al I have a situation where the reverse order of team projects needs to be compiled in a team build. How do i specify the path for the source project for team project 1 in custom task?

  • Anonymous
    March 17, 2007
    I returned to work after Tuesday's MSDN Roadshow fired up and full of ideas, eager to try out ASP.NET

  • Anonymous
    April 02, 2008
    Which idiot came up with this? http://msdn2.microsoft.com/en-us/library/bb668986.aspx You end up with a folder structure 5 levels deep before you get to any files. And you've got folders named things like 'MyWebAppSln' - why not 'MyWebApplication'? Sorry if this is the wrong place to vent, but the article links to this blog post.

  • Anonymous
    September 03, 2008
    The solution structure described on MSDN works quite well.  The names don't matter too much, but the structure copes with 90% of development.

  • Anonymous
    October 01, 2008
    PingBack from http://doddychsaputra.thecoderblogs.com/2008/10/02/how-to-structure-aspnet-applications-in-visual-studio-team-foundation-server/

  • Anonymous
    October 01, 2008
    PingBack from http://doddychsaputra.thecoderblogs.com/2008/10/02/how-to-structure-windows-applications-in-visual-studio-team-foundation-server-team-foundation-server/

  • Anonymous
    December 10, 2008
    Building solutions that reference to assemblies belonging to different team project If you facing the

  • Anonymous
    February 02, 2009
    Huaahhh… ini kasus yang umum namun anehnya agak perlu sedikit effort untuk bisa berhasil. Kasus apa sih

  • Anonymous
    June 17, 2009
    I am working with several team projects that need assemblies from other team projects. For example,...

  • Anonymous
    December 10, 2011
    The comment has been removed