Example on how to resolve project to project reference (for single solution) in team build.



 


Consider a simple solution (OfficeSolution.sln) that has one main project (OfficeSolution.csproj). The main project has dependency (project to project reference) on two independent sub projects (WordApplication.csproj and ExcelApplication.csproj). Note that both the sub projects also belong to the same solution. The folder structure for the sources is shown in the following diagram.


 


├───OfficeSolution


      OfficeSolution.sln


      OfficeSolution.vssscc


  


   ├───ExcelApplication


         ExcelApplication.csproj


         ExcelApplication.csproj.vspscc


         ExcelClass.cs


      └───Properties


              AssemblyInfo.cs


  


   ├───OfficeSolution


         OfficeSolution.csproj


         OfficeSolution.csproj.vspscc


         OfficeDocument.cs


      └───Properties


              AssemblyInfo.cs


  


   └───WordApplication


          WordClass.cs


          WordApplication.csproj


          WordApplication.csproj.vspscc


       └───Properties


               AssemblyInfo.cs


 


figure 1




There are two team projects (MyProj1 and My Proj2). The Excel and Word projects belong to one team project (MyProj2) and main project (OfficeSolution) is checked in different team project (MyProj1). Now we want to build this solution using team build. Based on case 1.2, recommendation 1, the directory structure of files under build directory should be identical to figure 1.


 



$/MyProj1  


├───OfficeSolution


      OfficeSolution.sln


      OfficeSolution.vssscc


   ├───OfficeSolution


         OfficeSolution.csproj


         OfficeSolution.csproj.vspscc


         OfficeDocument.cs


      └───Properties


              AssemblyInfo.cs


 


$/MyProj2  


├───OfficeSolution


   ├───ExcelApplication


         ExcelApplication.csproj


         ExcelApplication.csproj.vspscc


         ExcelClass.cs


      └───Properties


              AssemblyInfo.cs


   └───WordApplication


          WordClass.cs


          WordApplication.csproj


          WordApplication.csproj.vspscc


       └───Properties


               AssemblyInfo.cs


 


figure 2



User needs to modify the build type to get sources from different team project. For example you can add the following targets in the tfsbuild.proj to get files from different team project. Please note that target “AfterGet” defined in this file will override the default target “AfterGet” of file Microsoft.TeamFoundation.Build.targets.



<PropertyGroup>


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


</PropertyGroup>


 


<Target Name=CustomGet>       


    <!– Delete the default workspace used to sync sources from MyProj1 –>


    <Exec


      Command=&quot;$(TfCommand)&quot; workspace /delete $(WorkspaceName) /s:$(TeamFoundationServerUrl)/>


   


    <!– Create workspace to get files from MyProj2–>


    <Exec


      WorkingDirectory=$(SolutionRoot)


      Command=&quot;$(TfCommand)&quot; workspace /new


$(WorkspaceName) /s:$(TeamFoundationServerUrl)/>


 


    <!– Set the folder mappings to get files from MyProj2–>


    <Exec


      Command=&quot;$(TfCommand)&quot; workfold /map /s:$(TeamFoundationServerUrl)


/workspace:$(WorkspaceName) $/MyProj2/OfficeSolution $(SolutionRoot)\OfficeSolution/>


 


    <!– Get the files from team project MyProj2 –>


    <Exec


      WorkingDirectory=$(SolutionRoot)


      Command=&quot;$(TfCommand)&quot; get /r /force ./>



</Target>   




<!—Custom target to get sources from team project (MyProj2) –>


<Target Name=AfterGet


DependsOnTargets=CustomGet;InitializeWorkspace/>


 




 


<!—Assuming the second AT name is burton-tfs1 –>


<PropertyGroup>


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


    <TfsName2>http://burton-tfs1:8080/</TfsName2>


</PropertyGroup>


 


<Target Name=AfterGet> 


    <!– Delete the default workspace –>


    <Exec


      Command=&quot;$(TfCommand)&quot; workspace /delete $(WorkspaceName) /s:$(TeamFoundationServerUrl)/>


 


    <!– Create workspace to get files from different AT (burton-tfs1)–>


    <Exec


      WorkingDirectory=$(SolutionRoot)


      Command=&quot;$(TfCommand)&quot; workspace /new $(WorkspaceName) /s:$(TfsName2)/>


 


    <!– Set the folder mappings to get files from burton-tfs1 –>


    <Exec


      Command=&quot;$(TfCommand)&quot; workfold /map /s:$(TfsName2)


/workspace:$(WorkspaceName) $/MyProj2/OfficeSolution $(SolutionRoot)\OfficeSolution/>


 


    <!– Get the files from team project belonging to different AT–>


    <Exec


      WorkingDirectory=$(SolutionRoot)\OfficeSolution


      Command=&quot;$(TfCommand)&quot; get /r /force ./>


 


    <!– Delete the workspace used to sync files from different AT –>


    <Exec


      Command=&quot;$(TfCommand)&quot; workspace /delete $(WorkspaceName) /s:$(TfsName2)/>


  


    <!– Recreate the default workspace  –>


    <CreateWorkspaceTask


      Condition= ‘$(SkipInitializeWorkspace)’!=’true’ and ‘$(IsDesktopBuild)’!=’true’


      Url=$(TeamFoundationServerUrl)


      MappingFile=WorkspaceMapping.xml


      LocalPath=$(SolutionRoot)


      Name=$(WorkspaceName)


      TeamProject=$(TeamProject) /> 


</Target>


 


I will be talking about file references in team build in next post.


Comments (3)

  1. ManishAgarwal says:

    Please note that example code of scenario 1, case 1.2 might result in logger failure. This happens because logger does the conversion of server path to local path of all the (sln and csproj) files. You have to make sure that all the sources present under the "sources" folder are mapped to workspace.

    An alternative example (hint):-

    <PropertyGroup>

    <WorkingDirectories>$(SolutionRoot)..Reusable Code</WorkingDirectories>

    <TfCommand>&quot;$(TeamBuildRefPath)..tf.exe&quot;</TfCommand>

    </PropertyGroup>

    <Target Name="AfterGet">

    <!– Clean and create the working folder for the external project –>

    <RemoveDir Directories="$(WorkingDirectories)" ContinueOnError="true" />

    <MakeDir Directories="$(WorkingDirectories)" />

    <!– Delete existing workspace created by TeamBuild –>

    <Exec Command="$(TfCommand) workspace /delete &quot;$(WorkSpaceName)&quot; /server:vsts /noprompt" WorkingDirectory="$(SolutionRoot)..Reusable Code" ContinueOnError="true" />

    <!– Create a new one with the same name as the TeamBuild one –>

    <Exec Command="$(TfCommand) workspace /new &quot;$(WorkSpaceName)&quot; /server:vsts /noprompt" WorkingDirectory="$(SolutionRoot)..Reusable Code" />

    <!– Map the external projects to this workspace –>

    <Exec Command="$(TfCommand) workfold /map /workspace:&quot;$(WorkSpaceName)&quot; /server:vsts &quot;$/Reusable Code/Framework&quot; &quot;$(SolutionRoot)..Reusable CodeFramework&quot;" WorkingDirectory="$(SolutionRoot)..Reusable Code" />

    <!– Get the external projects into the correct locations –>

    <Exec Command="$(TfCommand) get &quot;$/Reusable Code/Framework&quot; /recursive /version:T /force" WorkingDirectory="$(SolutionRoot)..Reusable Code" />

    <!– Label external projects –>

    <Exec Condition=" ‘$(SkipLabel)’!=’true’ " Command="$(TfCommand) label /server:vsts &quot;$(BuildNumber)&quot; &quot;$/Reusable Code/Framework&quot; /version:&quot;W$(WorkSpaceName)&quot; /recursive" WorkingDirectory="$(SolutionRoot)..Reusable Code" />

    <!– Add mapping to default project back into the workspace –>

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

    </target>

  2. Vladimir Lyahov says:

    I have team build like in scenario_1 . It looks like in works right.

    But after I exec it always get "error CS0246: The type or namespace name ‘ActionList’ could not be found (are you missing a using directive or an assembly reference?)"(((. Could you advise something?

  3. Marco Wlotzka says:

    Thanks for your Suggestion. In TFS 2008 is another Option to do that. Just add other Team Projects’ Workspaces to the build definition, so they get check out with.

    Cheers, Marco