12

TeamCity (CruiseControl.NET からの移行) をセットアップしていますが、MSBuild を介してインクリメンタル ビルドを実行するのに苦労しています。

TeamCity から供給されるいくつかのパラメーターを使用してソリューションのビルドを呼び出すための基本的なビルド スクリプトを含む小さな .proj ファイルがあります。スクリプトを手動で呼び出すと、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存在しない場合にビルド プロセスの一部によって作成されます。すべてのビルドの前に「一時」ファイルを削除すると、ビルドごとに作成され、すべてのプロジェクト ファイルのビルドで動的に参照されます。

このファイルがビルドごとに再作成されないようにする方法を見つける必要があります。

4

3 に答える 3

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それぞれ 1 行にする必要があります。ここでは、読みやすくするために複数行に分けていますが、追加の改行によりスクリプトが失敗します。

ターゲットが実行されると、レジストリで定義されているユーザーの環境変数に基づいて適切なパスを作成しようとします。最初にTMPTEMPを検索してから、ユーザーのプロファイル フォルダーに戻り、最後にC:\Windows\Tempディレクトリに戻ります。これは、System.Path.GetTempPath() で文書化されている順序と一致し、TeamCity の外部での MSBuild の実行と一致する動作になるはずです。

これは、システムのどこかに .targets ファイルとして保存し、<Import>要素を使用して、TeamCity サーバーによってビルドされているプロジェクトの .csproj ファイルにインポートする必要があります。MSBuild 拡張機能ディレクトリ ( C:\Program Files\MSBuild\) の下にスクリプトを追加し、次のインポート要素を追加して参照しました。

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

<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />Import 要素の場所/順序は問題ではありませんが、すべての .csproj ファイルに表示される whichの後に含めることをお勧めします。

于 2012-08-13T12:00:47.267 に答える