Welcome to MSDN Blogs Sign in | Join | Help

Redirecting the copy of output assemblies for individual solutions to specified subfolders at drop site in Team Build

 

Team Build overrides the output directories that are specified in the individual project files, and thus places all build output at $(BinariesRoot)\$(Platfom)\$(Configuration)\

 

  1. Is there a way disable copying the assemblies at drop site? 

Yes, you need to set the SkipDropBuild property to true inside your tfsbuild.proj file. 

 

  1. Disable override behavior and have team Build use the relative output paths specified in each project properties?

No it is not possible now. We are working on it.

 

Unfortunately Team Build can not use the relative output paths specified in each project properties. We wanted to use TargetOutputs item which captures the relative path of output assembly (based on project settings). We can not use it because –

    1. The item is populated only when we call MSbuild on .XXPROJ files. It does not get initialized when we call MSbuild on .SLN files.  In Team Build basic unit of building is .SLN.
    2. The TargetOutputs item does not include the PDB files and other output configuration files for different type of projects.

  1. Specify override for individual projects during the build without any impact on desktop scenario?

There is no easy way to do it but I do have this workaround –

 

Expected actions from the user -  

  1. Override the core compile target and core clean target. Just past the following code in your tfsbuild.proj (towards the end , just before </project> tag). Note that you should not make modifications to Microsoft.Teamfoundation.Build.targets file.  

<Target Name="CoreClean"

          DependsOnTargets="$(CoreCleanDependsOn)"

          Condition=" '$(SkipClean)'!='true' ">

 

 

  <!-- Clean for desktop build -->

  <MSBuild

        Condition="'$(IsDesktopBuild)'=='true'"

        Projects="$(MSBuildProjectFile)"

        Targets="RunCoreCleanWithConfiguration"

        Properties="RunCodeAnalysis=$(RunCodeAnalysis); BinariesRoot=$(BinariesRoot);FxCopDir=$(FxCopDir);Platform=%(ConfigurationToBuild.PlatformToBuild);Flavor=%(ConfigurationToBuild.FlavorToBuild); " />

 

  <!-- Clean SolutionRoot only for end to end build -->

  <RemoveDir

        Condition="Exists('$(SolutionRoot)') and '$(IsDesktopBuild)'!='true'"

        Directories="$(SolutionRoot)" />

 

  <RemoveDir

        Condition="Exists('$(BinariesRoot)') and '$(IsDesktopBuild)'!='true'"

        Directories="$(BinariesRoot)" />

 

  <RemoveDir

        Condition="Exists('$(TestResultsRoot)') and '$(IsDesktopBuild)'!='true'"

        Directories="$(TestResultsRoot)" />

 

</Target>

 

<Target Name="RunCoreCleanWithConfiguration" >

 

  <!-- OutDirForClean for not Any CPU -->

  <CreateItem

        Condition=" '$(Platform)'!='Any CPU' "

        Include="$(BinariesRoot)\$(Platform)\$(Flavor)\" >

    <Output TaskParameter="Include" ItemName="OutDirForClean" />

  </CreateItem>

 

  <!-- OutDirForClean for Any CPU -->

  <CreateItem

        Condition=" '$(Platform)'=='Any CPU' "

        Include="$(BinariesRoot)\$(Flavor)\" >

    <Output TaskParameter="Include" ItemName="OutDirForClean" />

  </CreateItem>

 

  <!-- OutDir - to ensure we have absolute path as property -->

  <CreateProperty Value="%(OutDirForClean.FullPath)" >

    <Output TaskParameter="Value" PropertyName="OutDir" />

  </CreateProperty>

 

  <!-- Call MSBuild /t:Clean for desktop build -->

  <MSBuild

        Projects="@(SolutionToBuild)"         

 Properties="Configuration=$(Flavor);Platform=$(Platform);RunCodeAnalysis=$(RunCodeAnalysis);SkipInvalidConfigurations=true;FxCopDir=$(FxCopDir);OutDir=$(OutDir)%(SolutionToBuild.OutputFolder)\"

 

        Targets="Clean" />

 

</Target>

 

 

<Target Name="CoreCompile"

          DependsOnTargets="$(CoreCompileDependsOn)">

 

  <MakeDir

        Directories="$(BinariesRoot)"

        Condition="!Exists('$(BinariesRoot)')" />

 

  <TeamBuildMessage

        Tag="Configuration"

        Condition=" '$(IsDesktopBuild)'!='true' "

        Value="%(ConfigurationToBuild.FlavorToBuild)" />

 

  <TeamBuildMessage

        Tag="Platform"

        Condition=" '$(IsDesktopBuild)'!='true' "

        Value="%(ConfigurationToBuild.PlatformToBuild)" />

 

  <!-- Need proper location of build type otherwise logger fail (file not in enlistment)-->

  <MSBuild

        Condition="'$(IsDesktopBuild)'!='true' "

      Projects="$(SolutionRoot)\TeamBuildTypes\$(BuildType)\TfsBuild.proj"

 

        Targets="RunCoreCompileWithConfiguration"

        Properties="Platform=%(ConfigurationToBuild.PlatformToBuild);Flavor=%(ConfigurationToBuild.FlavorToBuild);RunCodeAnalysis=$(RunCodeAnalysis);BinariesRoot=$(BinariesRoot);FxCopDir=$(FxCopDir);TeamBuildConstants=$(TeamBuildConstants);SolutionRoot=$(SolutionRoot)" />

 

  <!-- Destop build, need this because $(Buildtype) not defined in desktop scenario-->

  <MSBuild

            Condition="'$(IsDesktopBuild)'=='true' "

            Projects="$(MSBuildProjectFile)"

            Targets="RunCoreCompileWithConfiguration"

            Properties="Platform=%(ConfigurationToBuild.PlatformToBuild);Flavor=%(ConfigurationToBuild.FlavorToBuild);RunCodeAnalysis=$(RunCodeAnalysis);BinariesRoot=$(BinariesRoot);FxCopDir=$(FxCopDir);TeamBuildConstants=$(TeamBuildConstants);SolutionRoot=$(SolutionRoot)" />

 

  <OnError ExecuteTargets="OnBuildBreak;" />

</Target>

 

 

<Target Name="RunCoreCompileWithConfiguration" >

 

  <!-- OutDirForCompile for not Any CPU -->

  <CreateItem

        Condition=" '$(Platform)'!='Any CPU' "

        Include="$(BinariesRoot)\$(Platform)\$(Flavor)\" >

    <Output TaskParameter="Include" ItemName="OutDirForCompile" />

  </CreateItem>

 

  <!-- OutDirForCompile for Any CPU -->

  <CreateItem

        Condition=" '$(Platform)'=='Any CPU' "

        Include="$(BinariesRoot)\$(Flavor)\" >

    <Output TaskParameter="Include" ItemName="OutDirForCompile" />

  </CreateItem>

 

  <!-- OutDir property - This is to ensure we have absolute path as property -->

  <CreateProperty Value="%(OutDirForCompile.FullPath)" >

    <Output TaskParameter="Value" PropertyName="OutDir" />

  </CreateProperty>

 

  <!-- First part of VCOverride file -->

  <CreateProperty Value="%3C?xml version=%221.0%22?%3E%0D%0A%3CVisualStudioPropertySheet ProjectType=%22Visual C++%22 Version=%228.00%22 Name=%22Team Build Overrides%22 OutputDirectory=%22$(OutDir)%22%3E%0D%0A" >

 

    <Output TaskParameter="Value"

        PropertyName="VCOverridesString1"/>

  </CreateProperty>

 

  <!-- Third part of VCOverride file -->

  <CreateProperty Value="%3C/VisualStudioPropertySheet%3E" >

    <Output TaskParameter="Value" 

        PropertyName="VCOverridesString3"/>

  </CreateProperty>

 

  <!-- RunCodeAnalysis option -->

  <CreateProperty

        Condition=" '$(RunCodeAnalysis)'=='Always' "

        Value="RunCodeAnalysis=true" >

    <Output TaskParameter="Value"

        PropertyName="CodeAnalysisOption" />

  </CreateProperty>

 

  <!— 2nd part of VCOverride file when RunCodeAnalysis is always -->

  <CreateProperty

        Condition=" '$(RunCodeAnalysis)'=='Always' "

 

        Value="%09%3CTool Name=%22VCCLCompilerTool%22 EnablePREfast=%22true%22 /%3E%0D%0A%09%3CTool Name=%22VCFxCopTool%22 EnableFxCop=%22true%22 /%3E%0D%0A" >

 

    <Output TaskParameter="Value"

        PropertyName="VCOverridesString2"/>

  </CreateProperty>

 

  <CreateProperty

        Condition=" '$(RunCodeAnalysis)'=='Never' "

        Value="RunCodeAnalysis=false" >

    <Output TaskParameter="Value"

        PropertyName="CodeAnalysisOption" />

  </CreateProperty>

 

  <!-- Second part of VCOverride file when RunCodeAnalysis is never -->

  <CreateProperty

        Condition=" '$(RunCodeAnalysis)'=='Never' "

 

        Value="%09%3CTool Name=%22VCCLCompilerTool%22 EnablePREfast=%22false%22 /%3E%0D%0A%09%3CTool Name=%22VCFxCopTool%22 EnableFxCop=%22false%22 /%3E%0D%0A" >

 

    <Output TaskParameter="Value"

        PropertyName="VCOverridesString2"/>

  </CreateProperty>

 

  <!-- ReferencePath option -->

  <CreateProperty

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

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

    <Output TaskParameter="Value" PropertyName="ReferencePath" />

  </CreateProperty>

 

  <CreateProperty

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

        Value="$(OutDir)" >

    <Output TaskParameter="Value" PropertyName="ReferencePath" />

  </CreateProperty>

 

  <!-- Generate VCOverride file for C++ projects -->

  <WriteLinesToFile

        File="TFSBuild.vsprops"

        Lines="$(VCOverridesString1)$(VCOverridesString2)$(AdditionalVCOverrides)$(VCOverridesString3)"

 

        Overwrite="true" />

 

  <!-- Build using MSBuild task -->

  <MSBuild

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

        Projects="@(SolutionToBuild)"

        Properties="Configuration=$(Flavor);Platform=$(Platform);SkipInvalidConfigurations=true;VCBuildOverride=$(MSBuildProjectDirectory)\TFSBuild.vsprops;FxCopDir=$(FxCopDir);OutDir=$(OutDir)%(SolutionToBuild.OutputFolder)\;ReferencePath=$(ReferencePath);TeamBuildConstants=$(TeamBuildConstants);$(CodeAnalysisOption)"

 

        Targets="Build" />

 

 

 

  <!-- Specify SolutionToPublish ItemGroup if you have ClickOnce based solutions or projects that you want to publish. The task below will generate manifest and deployment package. -->

  <MSBuild

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

        Projects="@(SolutionToPublish)"

        Properties="Configuration=$(Flavor);Platform=$(Platform);SkipInvalidConfigurations=true;VCBuildOverride=$(MSBuildProjectDirectory)\TFSBuild.vsprops;FxCopDir=$(FxCopDir);OutDir=$(OutDir)%(SolutionToPublish.OutputFolder)\;PublishDir=$(OutDir)%(SolutionToPublish.OutputFolder)\;ReferencePath=$(ReferencePath);TeamBuildConstants=$(TeamBuildConstants);$(CodeAnalysisOption)"

 

        Targets="Publish" />

</Target>

  1. In the build type file you need to make the following changes –

  <ItemGroup>   

    <SolutionToBuild Include="$(SolutionRoot)\ClassLibrary1\ClassLibrary1.sln">

      <OutputFolder>Lib</OutputFolder>

    </SolutionToBuild>

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

      <OutputFolder>App</OutputFolder>

    </SolutionToBuild>

</ItemGroup>

 

Please note the OutputFolder attribute will point to the sub folder under BinariesRoot\<platform>\<configuration>. For example in the above scenario we are interested in building for AnyCPU|Debug, then the output assemblies will be @ $(BinariesRoot)\Debug\Lib\Classlibrary1.dll, $(BinariesRoot)\Debug\App\ClassApplication1.exe.

 

It is not advisable to change the structure to BinariesRoot\<subfolder>\<platform>\<configuration>.

 

Advantages of this approach

  1. Desktop build will not get impacted
  2. If the OutputFolder attribute is not specified, then we revert back to the original behavior
  3. User does not need to make any modifications to the individual .csproj files (big +)

 Disadvantages of this approach

  1. I am not sure of the impact on project to project reference.  
  2. You will get a (dummy) entry under compile steps in report for building tfsbuild.proj. You can just ignore it.
  3. Solution will not work for unmanaged projects (using VCBuild.exe) that uses overrides file. The reason is that we generate the overrides file once and then pass it for all solutions. We can not do task batching while generating the overrides file (because it will impact the order in which solutions will be build) (big -)
  4. Not tested the test task. User might need to specify (hardcode) the correct value of SearchPathRoot property. (big -)

Tested scenarios

  1. Desktop clean/build/rebuild without specifying the OutputFolder attribute
  2. Desktop clean/build/rebuild with OutputFolder attribute defined
  3. End to end build with OutputFolder attribute for all solutions
  4. End to end build with OutputFolder attribute for some solutions

 

Published Friday, March 24, 2006 12:28 PM by ManishAgarwal

Comment Notification

If you would like to receive an email when updates are made to this post, please register here

Subscribe to this post's comments using RSS

Comments

# re: Redirecting the copy of output assemblies for individual solutions to specified subfolders at drop site in Team Build

I see you using $(BinariesRoot)- I would like to know how they are defined- Any documentation where I can find other macros like this one?
Thursday, April 06, 2006 8:07 PM by Shrish Jain

# re: Redirecting the copy of output assemblies for individual solutions to specified subfolders at drop site in Team Build

Please refer the file  Microsoft.teamfoundation.build.targets for all such macros
Friday, April 07, 2006 1:25 AM by manish agarwal

# re: Redirecting the copy of output assemblies for individual solutions to specified subfolders at drop site in Team Build

"... We are working on it". Are there any news?
Monday, July 03, 2006 9:39 AM by Alex Bögli

# Passing custom properties to individual solutions in Team Build

Gautam Goenka posted an article on this topic way back on April 20, 2006. It included a targets file

Monday, March 19, 2007 3:56 PM by Aaron Hallberg

# re: Redirecting the copy of output assemblies for individual solutions to specified subfolders at drop site in Team Build

This did not work for me on OrcasBeta1TFS

Friday, July 06, 2007 6:33 PM by xsignal

# Redirecting the copy of output assemblies for individual solutions

I search the net for a while for this problem: We using tfs build to perform a daily build. The following

Wednesday, March 05, 2008 2:29 AM by Your Daily Mark.Net

# TFS/MSBuild caveats &laquo; Andrzej&#8217;s Weblog

Friday, September 12, 2008 9:14 AM by TFS/MSBuild caveats &laquo; Andrzej&#8217;s Weblog

# 【日本語版】 Team Build でカスタム プロパティを個々のソリュ―ションに渡す

こんにちは! フォーラム オペレーターの服部清次です。 前回の更新から少し時間が経ち、 あっという間に2月も後半に入 ってしまいましたが、皆さん、いかがお過ごしですか? 今日は、久しぶりに、 MSDN

Monday, February 16, 2009 9:29 PM by Microsoft Japan Forum Operators Blog

# Manish Agarwal Redirecting the copy of output assemblies for | Weak Bladder

Leave a Comment

(required) 
required 
(required) 

  
Enter Code Here: Required
 
Page view tracker