如何使TeamCity充分利用MSBuild的增量构建支持? [英] How can I make TeamCity take advantage of MSBuild's incremental build support?

查看:59
本文介绍了如何使TeamCity充分利用MSBuild的增量构建支持?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在设置TeamCity(从CruiseControl.NET迁移),并且正在努力使其能够通过MSBuild执行增量构建.

I'm setting up TeamCity (migrating from CruiseControl.NET) and I'm struggling to get it to perform incremental builds through MSBuild.

我有一个很小的.proj文件,其中包含一个基本的构建脚本,以使用TeamCity输入的一些参数来调用我的解决方案的构建.当我手动调用脚本时,MSBuild的增量构建功能会启动并跳过构建完全在后续运行中进行.

I've got a small .proj file which contains a basic build script to invoke a build of my solution with some parameters fed in from TeamCity. When I invoke the script manually, MSBuild's Incremental Build features kick in and skip the build entirely on subsequent runs.

通过Team City调用此脚本时,构建日志每次都会显示干净编译的输出.我在构建过程中观察到了工作目录,并且可以看到先前构建的输出没有任何地方.

When calling this script via Team City, the build log shows the output of a clean compile every time. I've observed the working directory during builds and can see the output from the previous build hasn't gone anywhere.

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

I also manually called the build script from that directory by remoting onto the server and running MSBuild from the command-prompt. Running it this way triggers the expected incremental builds after the first invocation.

即使在不进行任何更改的情况下从仪表板开始构建,也会进行完整的重建.

Even when starting the build from the dashboard with no changes made, a complete rebuild occurs.

我无法查明原因,但是似乎有些东西给MSBuild留下了它正在获得新更改并导致它在每次运行时都执行重建的印象.我在TeamCity文档中看不到太多可以解释这一点的信息-我的期望是,如果源代码管理系统中没有任何更改,它将不会更新工作文件夹.

I can't pinpoint the cause, but something appears to be giving MSBuild the impression that it's getting new changes and causing it to perform a rebuild on every run. I can't see much in the TeamCity documentation that would explain this - my expectation is that if there are no changes in the source control system, it would not update the working folder.

TeamCity是否向构建过程传递了一些参数以触发重建?我可以查看这些参数吗?

Is TeamCity passing some parameter to the build process which triggers a rebuild? Can I view these parameters?

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

Having examined a detail MSBuild log (/v:d command-line switch), the reason a complete rebuild is occurring is due to the file .NETFramework,Version=v4.0.AssemblyAttributes.cs being updated in the <Agent>\temp\buildTmp directory on every build.

此文件通常在%TMP%\.NETFramework,Version=v4.0.AssemblyAttributes.cs上找到; TeamCity正在更改本地临时目录环境变量以引用代理的临时文件夹.不幸的是,该文件是在缺少时由构建过程的Microsoft.Common.targets部分创建的.在每次构建之前删除"temp"文件都会导致在每次构建时都将其创建,并在每个项目文件的构建中对其进行动态引用.

This file is normally found at %TMP%\.NETFramework,Version=v4.0.AssemblyAttributes.cs; TeamCity is changing the local temp directory environment variable to reference the agent's temp folder. Unfortunately, this file is created by the Microsoft.Common.targets part of the build process when absent. Deletion of the "temp" file before every build causes it to be created every build and is dynamically referenced in the build of every project file.

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

I need to find a way to prevent this file from being re-created on every build.

推荐答案

此问题的一种解决方法是自定义MSBuild进程,以设置目标框架Moniker程序集属性"文件(该文件的正确名称)所在的路径问题中提到的内容)将被创建.

A workaround for this problem is to customize the MSBuild process to set the path at which the "Target Framework Moniker Assembly Attributes" file (the proper name for the file mentioned in the question) will be created.

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

The TargetFrameworkMonikerAssemblyAttributesPath property is defined in Microsoft.Common.targets determines where the file should be created. By overriding this property, the location can be changed to use a different location.

以下是一个脚本,可用于实现适当的替换:

Here's a script that can be used to achieve a suitable replacement:

<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代理正在执行构建时执行.

The target is only executed when TEAMCITY_VERSION is specified as a property, which should be when the build is being executed by the TeamCity agent.

注意:PropertyGroup的子元素应分别位于一行上.它们已分散在多行中,以提高此处的可读性,但其他换行符导致脚本失败.

NOTE: The child elements of the PropertyGroup should each be on a single line. They have been spread over multiple lines to increase readability here, but the additional line-breaks cause the script to fail.

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

When the target runs, it tries to build a suitable path based on the user's environment variables as defined in the registry, first looking for TMP and TEMP, before falling back to the user's profile folder and finally the C:\Windows\Temp directory. This matches the order documented by System.Path.GetTempPath(), and should result in behaviour matching MSBuild execution outside of TeamCity.

应将其另存为.targets文件在系统上的某个位置,并使用<Import>元素导入到TeamCity服务器正在构建的项目的.csproj文件中.我将脚本添加到了MSBuild扩展目录(C:\Program Files\MSBuild\)下,并通过添加以下导入元素对其进行了引用:

This should be saved as a .targets file somewhere on the system and imported to the .csproj file of projects being built by the TeamCity server, using an <Import> element. I added the script under my MSBuild extensions directory (C:\Program Files\MSBuild\) and referenced it by adding the following import element:

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

Import元素的位置/顺序无关紧要,但是我建议将其包含在<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />之后,它应该出现在每个.csproj文件中.

The location/ordering of Import elements doesn't matter, but I suggest including it after the <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> which should appear in every .csproj file.

这篇关于如何使TeamCity充分利用MSBuild的增量构建支持?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆