如何让TeamCity利用MSBuild的增量构建支持?

时间:2012-08-09 16:55:06

标签: msbuild teamcity

我正在设置TeamCity(从CruiseControl.NET迁移),我正在努力让它通过MSBuild执行增量构建。

我有一个小的.proj文件,其中包含一个基本的构建脚本,用于调用我的解决方案的构建,其中一些参数来自TeamCity。当我手动调用脚本时,MSBuild的Incremental Build功能会启动并完全在后续运行时跳过构建。

通过Team City调用此脚本时,构建日志每次都会显示一个干净编译的输出。我在构建期间观察了工作目录,并且可以看到前一版本的输出没有消失。

我还通过远程访问服务器并从命令提示符运行MSBuild来手动调用该目录中的构建脚本。以这种方式运行会在第一次调用后触发预期的增量构建。

即使从仪表板启动构建而未进行任何更改,也会发生完全重建。

我无法确定原因,但似乎有些事情让MSBuild感觉它正在获得新的变化并导致它在每次运行时执行重建。我在TeamCity文档中看不到多少可以解释这一点 - 我的期望是如果源控制系统没有变化,它就不会更新工作文件夹。

TeamCity是否将一些参数传递给构建过程,从而触发重建?我可以查看这些参数吗?


检查了详细的MSBuild日志(/v:d命令行开关)之后,完成重建的原因是由于每个.NETFramework,Version=v4.0.AssemblyAttributes.cs目录中的文件<Agent>\temp\buildTmp都在更新建立。

此文件通常位于%TMP%\.NETFramework,Version=v4.0.AssemblyAttributes.cs; TeamCity正在更改本地临时目录环境变量以引用代理程序的临时文件夹。不幸的是,这个文件是在缺席的情况下由构建过程的Microsoft.Common.targets部分创建的。在每次构建之前删除“temp”文件会导致在每次构建时创建它,并在每个项目文件的构建中动态引用。

我需要找到一种方法来阻止在每次构建时重新创建此文件。

3 个答案:

答案 0 :(得分:11)

此问题的解决方法是自定义MSBuild进程以设置“Target Framework Moniker Assembly Attributes”文件(问题中提到的文件的正确名称)的路径。

TargetFrameworkMonikerAssemblyAttributesPath属性在Microsoft.Common.targets中定义,确定应在何处创建文件。通过覆盖此属性,可以更改位置以使用其他位置。

这是一个可用于实现合适替换的脚本:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

<PropertyGroup>
    <PrepareForBuildDependsOn>
        $(PrepareForBuildDependsOn);
        _SetTargetFrameworkMonikerAssemblyAttributesPath
    </PrepareForBuildDependsOn>
</PropertyGroup>

<Target 
    Name="_SetTargetFrameworkMonikerAssemblyAttributesPath"
    Condition="'$(TEAMCITY_VERSION)' != ''">

    <PropertyGroup>
        <TargetFrameworkMonikerAssemblyAttributesDir
            Condition="'$(TargetFrameworkMonikerAssemblyAttributesDir)' == ''">
            $([MSBuild]::GetRegistryValue("HKEY_CURRENT_USER\Environment", "TMP"))
        </TargetFrameworkMonikerAssemblyAttributesDir>
        <TargetFrameworkMonikerAssemblyAttributesDir
            Condition="'$(TargetFrameworkMonikerAssemblyAttributesDir)' == ''">
            $([MSBuild]::GetRegistryValue("HKEY_CURRENT_USER\Environment", "TEMP"))
        </TargetFrameworkMonikerAssemblyAttributesDir>
        <TargetFrameworkMonikerAssemblyAttributesDir 
            Condition="'$(TargetFrameworkMonikerAssemblyAttributesDir)' == ''">
            $(USERPROFILE)
        </TargetFrameworkMonikerAssemblyAttributesDir>
        <TargetFrameworkMonikerAssemblyAttributesDir
            Condition="'$(TargetFrameworkMonikerAssemblyAttributesDir)' == ''">
            $([System.IO.Path]::Combine('$(WINDIR)', 'Temp'))
        </TargetFrameworkMonikerAssemblyAttributesDir>
        <TargetFrameworkMonikerAssemblyAttributesPath>
            $([System.IO.Path]::Combine('$(TargetFrameworkMonikerAssemblyAttributesDir)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)'))
        </TargetFrameworkMonikerAssemblyAttributesPath>
    </PropertyGroup>

    <Message Text="Target Framework Moniker Assembly Attributes path is &quot;$(TargetFrameworkMonikerAssemblyAttributesPath)&quot;" Importance="low" />

</Target>

目标仅在TEAMCITY_VERSION被指定为属性时执行,该属性应该在TeamCity代理执行构建时执行。

注意: PropertyGroup的子元素应分别在一行中。它们已分布在多行中以提高可读性,但额外的换行会导致脚本失败。

当目标运行时,它会尝试根据注册表中定义的用户环境变量构建合适的路径,首先查找TMPTEMP,然后再回到用户的配置文件文件夹最后是C:\Windows\Temp目录。这与System.Path.GetTempPath()记录的顺序相匹配,并且应该导致在TeamCity之外匹配MSBuild执行的行为。

这应该保存为系统中的某个.targets文件,并使用<Import>元素导入到TeamCity服务器正在构建的项目的.csproj文件中。我在MSBuild扩展目录(C:\Program Files\MSBuild\)下添加了脚本,并通过添加以下import元素引用它:

<Import Project="$(MSBuildExtensionsPath)\TeamCity\TeamCity.Incremental.targets" />

导入元素的位置/顺序无关紧要,但我建议在每个.csproj文件中出现的<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />之后加上它。

答案 1 :(得分:1)

正如Paul Turner所提到的,调整TargetFrameworkMonikerAssemblyAttributesPath解决了这个问题。我没有在Microsoft的构建系统脚本中与High Magick作战,而是添加了一个环境变量来在TeamCity项目参数中设置TargetFrameworkMonikerAssemblyAttributesPath。

在TeamCity的项目设置中,我将 env.TargetFrameworkMonikerAssemblyAttributesDir 设置为%env.windir%\ Temp

答案 2 :(得分:1)

TeamCity 2017.3中仍然存在此问题。

我希望找到一个更容易跟踪解决方案,而不是接受答案详细说明,所以我做了以下内容:

  1. 我已将.NETFramework,Version=v4.7.AssemblyAttributes.cs文件的副本签入我的VCS
  2. 我为使用具有以下属性的MSBuild的构建配置添加了新的构建步骤:
    • 亚军类型:命令行
    • 步骤名称:CopyAssemblyAttributesFile
    • 运行:自定义脚本
    • 自定义脚本copy "%system.teamcity.build.workingDir%\<path_to_AssemblyAttributes.cs Dir>\." "%env.TEMP%\."
  3. 这将首次使用初始VCS结帐时的时间戳复制我的AssemblyAttributes文件版本,

    随后MSBuild似乎认为它是同一个文件,因为时间戳将保持一致,现在可以正确执行增量构建,可以从代理上的构建日志验证。