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)" >

**

...

Comments

  • Anonymous
    October 14, 2005
    I have amended the .vbproj of one of my class libraries with the target below in an attempt to have a centralised binaries folder containing my external references, but when I build through the IDE, I dont get a 'Binaries' folder created containing the class library. DO I need to define $(SolutionDir) and/or $(TargetPath) for this target to work or is there something else I need to do?



    <Target Name="AfterBuild">

    <Exec

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

    </Target>

  • Anonymous
    October 14, 2005
    You are right I didn't accounted for desktop build in my example. In intent was to give a rough idea of what needs to be done.

    However to solve you problem, you can do the following; -

    In your csproj file of the project, add the following lines

    <PropertyGroup>
    <!-- set the value of this property for building inside visual studio -->
    <CentralisedBinariesFolderLocation Condition="'$(BuildingInsideVisualStudio)'=='true'">
    c:temp
    </CentralisedBinariesFolderLocation>
    <!-- set the value of this property for team build scenario -->
    <CentralisedBinariesFolderLocation Condition="'$(BuildingInsideVisualStudio)'!='true'">
    $(SolutionDir)..binaries
    </CentralisedBinariesFolderLocation>
    </PropertyGroup>

    <Target Name="AfterBuild">
    <Exec
    Command="xcopy /Y /S /F $(TargetPath) $(CentralisedBinariesFolderLocation)" />
    </Target>

    Please note that -
    1) BuildingInsideVisualStudio and TargetPath properties are defined inside Microsoft.Common.targets. They are evaluated for each project seperately. You do not need to define these properties.
    2) I have not tried this scenario on my machine but i am sure it should work. Do let us know if you face other issues.


  • Anonymous
    October 17, 2005
    You might find that you need to add a /R to the xcopy command as once you checkin the CustomLibrary.dll into source control in the 'binaries' folder, the next time you try to build CustomLibrary locally, the AfterBuild target will fail because its trying to overwrite a read-only file

  • Anonymous
    November 16, 2005
    Thanks for all this useful info, especially the %3B bug.

  • Anonymous
    December 20, 2005
    Hey thanks for the info - it was quite useful.

  • Anonymous
    February 01, 2006
    The %3B bug is not fixed in beta 3! Hope this gets fixed in RTM...

  • Anonymous
    February 01, 2006
    Joey,

    We have fixed this bug in RTM bits. Thanks for your feedback

  • Anonymous
    September 27, 2007
    PingBack from http://johnnynine.com/blog/AssemblyNotFoundWhenCompilingOnANewdifferentMachine.aspx

  • Anonymous
    December 02, 2009
    Hi,  Is it possible to get the hint path automatically generated for our own assemblies. When I build my assembly I observe that for those assemblies which are 3'rd party hintpath automatically gets included but if I refer some other file reference in my project then in my csproj file (I work in c#) we do not get <HintPath>. We have to manuallly add it :(. Any suggestions please. Regards Bharti