Resolving file references in team build ( Part -2 )

  • Salient points about file references
    • File reference is used to reference outer system assemblies (i.e .NET framework assemblies, third party assemblies or assemblies that are not generated by the current solution).
    • File reference is defined by the reference item defined in the build scripts (.xxproj file).
    • The reference item has following attributes
      • Include contains the file name or fusion name of the assembly. It can contain the full path or only name.
      • HintPath is an optional attribute of the item. It gives the clue to the build process on where to find the assembly
      • Private is also an optional boolean attribute. It indicates whether to copy the mentioned assembly to the output folder or not.
      • Specific Version is an optional boolean attribute that indicates whether to do the complete name matching (including version, culture and PublicKeyToken)
    • Example of reference item

<Reference

Include="Microsoft.TeamFoundation.VersionControl.Client,

         Version=8.0.0.0, Culture=neutral,

      PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=x86">

 

   <SpecificVersion>False</SpecificVersion>

   <Private>false<Private>

<HintPath>d:\temp\Microsoft.TeamFoundation.VersionControl.Client.dll<HintPath>

</Reference>

  • Salient points about resolving file references
    • The SearchPaths property defined in Microsoft.Common.targets define the search order of the assemblies. The user can change the order by editing the property value. Please note that modifying standard targets file is not recommended.
    • The default search order is
      •  Files from the current project – indicated by {CandidateAssemblyFiles}.
      • $(ReferencePath) property that comes from .user/targets file.
      • $(HintPath) indicated by reference item.
      • Target framework directory.
      • Directories found in registry that uses AssemblyFoldersEx Registration.
      • Registered assembly folders, indicated by {AssemblyFolders}.
      • $(OutputPath) or $(OutDir)
      • GAC
      • The reference item include attribute as if it were a complete file name.
    • Please note that in resolving file references
      • components in HKCU are always preferred over HKLM
      • current framework target version is preferred over older target version
  • Using file references in team build
    • Team build provides “AdditionalReferencePath” item for resolving file references.
      • You can add/define AdditionalReferencePath items by manually editing tfsbuild.proj file. We are overriding the “ReferencePath” property to include folders specified by AdditionalReferencePath items ( please refer target "CoreCompile" in file Microsoft.TeamFoundation.Build.targets) . Thus in new search order, external folders can be used to resolve additional\external file references.
      • For example consider a scenario where we have two solutions. One solution (CustomApplication) has dependency on other (CustomLibrary). Please refer the folder structure below -

$/MyProj2

├───CustomLibrary

│ │ CustomLibrary.sln

│ │ CustomLibrary.vssscc

│ │

│ ├─── CustomLibrary

│ │ │ CustomLibrary.csproj

│ │ │ CustomLibrary.csproj.vspscc

│ │ │ MyLibrary.cs

│ │ └───Properties

│ │ AssemblyInfo.cs

├───CustomApplication

│ │ CustomApplication.sln

│ │ CustomApplication.vssscc

│ │

│ ├─── CustomApplication

│ │ │ CustomApplication.csproj

│ │ │ CustomApplication.csproj.vspscc

│ │ │ Program.cs

│ │ └───Properties

│ │ AssemblyInfo.cs

├───binaries

      • To enable building sources that have solution to solution dependencies:-
        • User has to define a common drop folder (binaries) from where team build can resolve file references. For example in the given example we have a binaries folder just under team project ($/MyProj2)

        • User has to make sure that references are added using file reference instead of project reference. In fact project reference across solutions does not work. For example in the given scenario, CustomApplication has reference item defined in CustomApplication.csproj which contains file reference to CustomLibrary.dll. 

           

<Reference

   Include="CustomLibrary, Version=1.0.0.0,

      Culture=neutral, processorArchitecture=MSIL">

 

    <SpecificVersion>False</SpecificVersion>

    <HintPath>..\..\binaries\CustomLibrary.dll</HintPath>

</Reference>

      • User needs to customize the build scripts of individual solutions to copy generated assemblies in the common binaries folder. This is to facilitate the assembly resolution of dependent projects. User can do this easily by adding a custom post build step in the csproj file. For example in our project we added the following target to CustomLibrary.csproj.

<Target Name="AfterBuild">

    <Exec

      Command="xcopy /Y /S /F $(TargetPath) $(SolutionDir)..\binaries" />

</Target>

      • When creating the build type user make sure

        • Template workspace selected should result in syncing of binaries folder on build machine.

        • Ordering of solutions is proper. For example in our example, CustomLibrary.sln should be build before CustomApplication.sln

        • In our example we do not need to define AdditionalReferencePath item but user can define new item to resolve references from different locations. For example user can additional define AdditionalReferencePath item in tfsbuild.proj.

<AdditionalReferencePath

Include="$(SolutionRoot)\Binaries ">

        • Please note that there is a bug in Microsoft.TeamFoundation.Build.targets where value of ReferencePath is not evaluated properly. This is fixed in post beta3 bits. You need to make the following change in target "CoreCompile" :-

From:- 

 

<CreateProperty

   Condition=" '@(AdditionalReferencePath)'!='' "

   Value="$(OutDir)%3B@(AdditionalReferencePath)"

    ...    

 

To:-

 

<CreateProperty

   Condition=" '@(AdditionalReferencePath)'!='' "

   Value="$(OutDir);@(AdditionalReferencePath)" >

**

...