Ask a questionAsk a question
 

AnswerIncremental get not detecting csproj changes?

  • Wednesday, April 11, 2007 4:06 PMPeter McEvoy Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     

    Hi there,

      As detailed in another post I've implemented Aarons incremental get hack to try and speed up CoreGet during a teambuild.  This seems to work, however, since we've started to use this trick, we've started getting some curious build errors, that have me doubting it. 

     

    Basically, it seems that even though the source code is being refreshed (I can see this by browsing to the Sources dir of the Build directory on the build machine), it appears that old versions of the csproj files are being kept in memory (or something). 

     

    Here is a sequence of steps to be executed while using the Incremental Get trick

     

    TeamBuild a project containing a number of files - all is OK

    Locally, build the project in VS - all OK

    Locally, delete, or move a .CS file in the project

    Check in project

    Locally build, all OK.

    TeamBuild the project, and we see compile errors indicating that the .cs files cannot be found

    Manually eyeball the csproj on the build server, and the <Compile> item group is correct (ie the removed file is indeed NOT within the project)

    Upon executing the TeamBuild again, (with no changes) it will compile correctly

     

    We've seen this happen with files that were moved or deleted, or indeed new files that are added to the project and referenced by existing.

     

    It's as if the csproj is somehow being kept in memory by teambuild, and not updated even though the latest is retrieved from TFS

     

    Here is the msbuild-ish that I added to my TFSBuild.proj:

     

     

    <!--

    INCREMENTAL GET HACK

    PMcE: We want to do an incremental GET, but a CLEAN build. This is not possible using

    the ForceGet, SkipClean and SkipInitializeWorkSpace properties out of the box.

    So, using solution described here:

    http://blogs.msdn.com/aaronhallberg/archive/2007/01/03/doing-an-incremental-get-in-team-build.aspx

    Which DOES do an incremental GET and a CLEAN build

    -->

    <PropertyGroup>

        <SkipClean>false</SkipClean>

        <SkipInitializeWorkspace>true</SkipInitializeWorkspace>

        <ForceGet>false</ForceGet>

    </PropertyGroup>

     

    <Target Name="BeforeClean">

        <!-- Delete BinariesRoot and TestResultsRoot to be thorough. -->

        <RemoveDir Condition="Exists('$(BinariesRoot)')"

            Directories="$(BinariesRoot)" />

        <RemoveDir Condition="Exists('$(TestResultsRoot)')"

            Directories="$(TestResultsRoot)" />

        <!-- Rather than delete SolutionRoot, set IsDesktopBuild to true for the duration of the CoreClean target. -->

        <CreateProperty Value="true">

            <Output TaskParameter="Value"

                PropertyName="IsDesktopBuild" />

        </CreateProperty>

    </Target>

     

    <Target Name="AfterClean">

        <CreateProperty Value="false">

            <Output TaskParameter="Value"

                PropertyName="IsDesktopBuild" />

        </CreateProperty>

    </Target>

    <!--

    END INCREMENTAL GET HACK

    -->

Answers

  • Friday, April 13, 2007 7:31 PMAaron HallbergMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Well, it looks like my diagnosis was correct on this issue. Unfortunately, the ability to unload projects is an MSBuild 3.5 feature, so it won't work with Team Build V1 (and MSBuild 2.0). So - you're stuck with my second idea: re-ordering the Get and Clean targets.

    Try out the following - make sure to place this property group after the import of Microsoft.TeamFoundation.Build.targets to make sure your declaration overrides the initial declaration:

    <PropertyGroup>
    <EndToEndIterationDependsOn>
    BeforeEndToEndIteration;
    BuildNumberOverrideTarget;
    InitializeEndToEndIteration;
    InitializeBuild;
    PreBuild;
    Clean;
    TeamBuild;
    DropBuild;
    AfterEndToEndIteration;
    </EndToEndIterationDependsOn>
    <TeamBuildDependsOn>
    Compile;
    PostBuild;
    Test;
    PackageBinaries;
    </TeamBuildDependsOn>
    </PropertyGroup>

    Note that this re-ordering should not be done for typical builds - it will only work in combination with the IncrementalGet hack (since otherwise the Clean will just delete all the files retrieved by the Get).

    Also note that the original blog post that detailed this hack has also been updated: http://blogs.msdn.com/aaronhallberg/archive/2007/01/03/doing-an-incremental-get-in-team-build.aspx.  Thanks, Peter, for noticing this bug!

All Replies

  • Thursday, April 12, 2007 12:54 PMAaron HallbergMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    I haven't had time to investigate this as of yet, but I think what is happening is that MSBuild loads the old version of the project for the Clean (since this comes before the Get), and then doesn't unload the project for the Compile even though it has changed in the meantime.  I suspect there should be some way to instruct MSBuild to unload the project, but I'm not entirely sure.  If not, another possibility would be to change the order of the Get and the Clean.  I'll try to look into this later today.

    -Aaron
  • Friday, April 13, 2007 7:31 PMAaron HallbergMSFT, ModeratorUsers MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     Answer
    Well, it looks like my diagnosis was correct on this issue. Unfortunately, the ability to unload projects is an MSBuild 3.5 feature, so it won't work with Team Build V1 (and MSBuild 2.0). So - you're stuck with my second idea: re-ordering the Get and Clean targets.

    Try out the following - make sure to place this property group after the import of Microsoft.TeamFoundation.Build.targets to make sure your declaration overrides the initial declaration:

    <PropertyGroup>
    <EndToEndIterationDependsOn>
    BeforeEndToEndIteration;
    BuildNumberOverrideTarget;
    InitializeEndToEndIteration;
    InitializeBuild;
    PreBuild;
    Clean;
    TeamBuild;
    DropBuild;
    AfterEndToEndIteration;
    </EndToEndIterationDependsOn>
    <TeamBuildDependsOn>
    Compile;
    PostBuild;
    Test;
    PackageBinaries;
    </TeamBuildDependsOn>
    </PropertyGroup>

    Note that this re-ordering should not be done for typical builds - it will only work in combination with the IncrementalGet hack (since otherwise the Clean will just delete all the files retrieved by the Get).

    Also note that the original blog post that detailed this hack has also been updated: http://blogs.msdn.com/aaronhallberg/archive/2007/01/03/doing-an-incremental-get-in-team-build.aspx.  Thanks, Peter, for noticing this bug!
  • Monday, April 16, 2007 8:29 AMPeter McEvoy Users MedalsUsers MedalsUsers MedalsUsers MedalsUsers Medals
     
    No worries, cheers for confirming..