我正在设置TeamCity(从CruiseControl.NET迁移),我正在努力让它通过MSBuild执行增量构建.
我有一个小的.proj文件,其中包含一个基本的构建脚本,用于调用我的解决方案的构建,其中一些参数来自TeamCity.当我手动调用脚本时,MSBuild的增量构建功能会在后续运行中完全启动并跳过构建.
通过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"文件会导致在每次构建时创建它,并在每个项目文件的构建中动态引用它.
我需要找到一种方法来防止在每次构建时重新创建此文件.
Pau*_*ner 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 "$(TargetFrameworkMonikerAssemblyAttributesPath)"" Importance="low" />
</Target>
Run Code Online (Sandbox Code Playgroud)
目标仅在TEAMCITY_VERSION指定为属性时执行,该属性应在TeamCity代理执行构建时执行.
注意:每个子元素PropertyGroup应该在一行上.它们已分布在多行中以提高可读性,但额外的换行会导致脚本失败.
当目标运行时,它会尝试根据注册表中定义的用户环境变量构建合适的路径,首先查找TMP并TEMP返回到用户的配置文件文件夹,最后返回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" />
Run Code Online (Sandbox Code Playgroud)
Import元素的位置/顺序无关紧要,但我建议<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />在每个.csproj文件中出现之后加入它.
| 归档时间: |
|
| 查看次数: |
2869 次 |
| 最近记录: |