8

これは当たり前のことのように思えますが、私はWebで例を見つけたり、自分でやろうとして、ほとんどの髪の毛を抜いてしまいました。

私は19のプロジェクトとMSBuildを駆動するビルドスクリプトを実行するJenkinsビルドサーバーを備えたac#ソリューションを持っています。もちろん、MSBuildは、入力と出力に基づいて、コンパイルする必要があるものとコンパイルする必要がないものを決定します。

MSBuildがコンパイルしてファイルバージョンをインクリメントするプロジェクトのAssemblyInfo.csを条件付きで更新するカスタムターゲットを作成しようとしています。もちろん、プロジェクトを一人でコンパイルしないでおきたいです。

毎回実行されるCoreBuildの前にターゲットを挿入する方法を知っているので、変数がある場合は、動作するコンパイルが発生するかどうかをテストできます。また、コンパイルが実行されたかどうかを判断する方法も知っているため、条件付きで後処理を実行できますが、これは可能ですが理想的ではありません。

これを実現するためにビルドプロセスを微調整するにはどうすればよいですか?

質問に対する正解はないようですが、MSBuildと同じロジックを実行して、再構築が必要なプロジェクトを特定する方法を知っている人はいますか?

4

4 に答える 4

12

結局のところ、解決策は、Sayed IbrahimHashimiのブログエントリとMSDNフォーラムエントリの情報「(コア)コンパイルが実行されるときにターゲットを実行する」の組み合わせでした。

基本的に、Sayedのインジェクションメソッドを使用して、各プロジェクトファイルを編集せずにすべてのプロジェクトで「extend-corecompile.proj」を実行するようにターゲットを取得しましたが、その内容を、同じものを採用するカスタムターゲットを指す「CoreCompileDependsOn」のオーバーライドに置き換えました。 'CoreCompile'ターゲットとしての入力と出力。最終結果は、ビルドスクリプトで一元管理されている間に「CoreCompile」が実行される場合にのみ実行されるターゲットです。

入力してくれたすべての人に感謝します。これが「extend-corecompile.proj」で使用したスケルトンコードです。

<!--The following property group adds our custom post-target to the post compile call list -->
<PropertyGroup>
    <TargetsTriggeredByCompilation>
        $(TargetsTriggeredByCompilation);
        CustomPostTarget
    </TargetsTriggeredByCompilation>
</PropertyGroup>

<!--The following property group adds our custom pre-target to CoreCompileDependsOn to ensure it is called before CoreCompile -->
<PropertyGroup>
    <CoreCompileDependsOn>
        $(CoreCompileDependsOn);
        CustomPreTarget
    </CoreCompileDependsOn>
</PropertyGroup>

<!-- The following custom pre-target has the same inputs and outputs as CoreCompile so that it will only run when CoreCompile runs.
    Because we have injected this file and Targets are resolved in sequence we know this Target will fire before CoreCompile.-->
<Target Name="CustomPreTarget" 
    Inputs="$(MSBuildAllProjects);
            @(Compile);                               
            @(_CoreCompileResourceInputs);
            $(ApplicationIcon);
            $(AssemblyOriginatorKeyFile);
            @(ReferencePath);
            @(CompiledLicenseFile);
            @(EmbeddedDocumentation); 
            $(Win32Resource);
            $(Win32Manifest);
            @(CustomAdditionalCompileInputs)"
    Outputs="@(DocFileItem);
             @(IntermediateAssembly);
             @(_DebugSymbolsIntermediatePath);                 
             $(NonExistentFile);
             @(CustomAdditionalCompileOutputs)">
    <!--Do pre-compilation processing here-->
</Target>

<!--This target will be called by CoreCompile-->
<Target Name="CustomPostTarget" >
    <!--Do post-compilation processing here-->
</Target>

CoreCompileが失敗した場合に何が起こるかわかりませんが、それでもターゲットを呼び出しますか?やがてわかると思います:)

于 2012-08-08T17:04:27.727 に答える
7

これに対する答えをhttp://sedodream.com/2012/07/28/MSBuildHowToExecuteATargetAfterCoreCompilePart2.aspxでブログに書きましたが、以下に解決策を貼り付けました。

数か月前、私はブログ投稿MSBuildに、CoreCompileの後にターゲットを実行する方法を書きました。ここでは、CoreCompileターゲットが実行された場合、CoreCompileがスキップされた場合、他のターゲットもスキップされた場合にターゲットを実行する方法について説明します。以前の投稿で概説したアプローチの欠点は、.csproj / .vbproj/etcファイル自体を編集する必要があることでした。したがって、複数のプロジェクトを構築するシナリオがある場合は、すべてのプロジェクトファイルを編集する必要があります。この投稿では、プロジェクトファイル自体を編集せずに同じカスタマイズを実行する方法について説明します。

この特定のケースの解決策に入る前に、C#およびVBプロジェクトが持つ拡張性フックについて説明します。C#およびVBプロジェクトをビルドするためのロジックのほとんどは、C:\ Windows \ Microsoft.NET \ Framework \ v4.0.30319\Microsoft.Common.targetsにあるMSBuildターゲットファイルにキャプチャされています。そのファイルを見ると、上部に次のようなインポートが表示されます。

<Import Project="$(CustomBeforeMicrosoftCommonTargets)" Condition="'$(CustomBeforeMicrosoftCommonTargets)' != '' and Exists('$(CustomBeforeMicrosoftCommonTargets)')"/>

プロパティが空でなく、ファイルが存在する場合、このステートメントはファイル(CustomBeforeMicrosoftCommonTargetsの値にあります)をインポートします。CustomBeforeMicrosoftCommonTargetsのデフォルト値は、C:\ Program Files(x86)\ MSBuild \ v4.0\Custom.Before.Microsoft.Common.targetsです。したがって、その場所にMSBuildファイルをドロップすると、そのマシンでビルドされたすべてのC#/VBプロジェクトのビルドプロセスが変更されます。または、必要がない場合(または、ACLが原因でできない場合)は、ファイルを別の場所にドロップしてから、CustomBeforeMicrosoftCommonTargetsプロパティをオーバーライドしてその場所を指定できます。これが私がここでとるアプローチです。ProjAとProjBの2つのプロジェクトで構成されるサンプルソリューションを作成しました。このためのビルドを自動化するためのビルドスクリプトbuild.projもあります。以下はbuild.projの全内容です。

build.proj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <FileToInject Condition=" '$(FileToInject)'=='' ">$(MSBuildThisFileDirectory)extend-corecompile.proj</FileToInject>
  </PropertyGroup>

  <ItemGroup>
    <ProjectsToBuild Include="ProjA\ProjA.csproj"/>
    <ProjectsToBuild Include="ProjB\ProjB.csproj"/>
  </ItemGroup>

  <Target Name="Build">
    <MSBuild Projects="@(ProjectsToBuild)"
             Properties="CustomBeforeMicrosoftCommonTargets=$(FileToInject)" />   
  </Target>

  <Target Name="Clean">
    <MSBuild Projects="@(ProjectsToBuild)" Targets="Clean"/>
  </Target>

  <Target Name="Rebuild" DependsOnTargets="Clean;Build"/>

</Project>

上記のビルドターゲットでは、MSBuildタスクを使用してProjAとProjBの両方をビルドします。ご覧のとおり、extend-corecompile.projを指すプロパティCustomBeforeMicrosoftCommonTargets = $(FileToInject)を渡しています。ProjAおよびProjBのビルド時にこのプロパティを渡すことにより、ビルドプロセス用にextend-corecompile.projファイルが自動的にインポートされます。以下にextend-corecompile.projの内容を示します。

extend-corecompile.proj

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <TargetsTriggeredByCompilation>
      $(TargetsTriggeredByCompilation);
      MyCustomTarget
    </TargetsTriggeredByCompilation>
  </PropertyGroup>

  <Target Name="MyCustomTarget">
    <Message Text="MyCustomTarget called" Importance ="high"/>
  </Target>

</Project>

このプロジェクトファイルは、以前のブログ投稿で概説した手法を使用して、CoreCompileが実行された場合にのみMyCustomTargetを実行します。

注:このサンプルの最新バージョンは、 https://github.com/sayedihashimi/sayed-samples/tree/master/ExtBuildMultipleで入手できます。

于 2012-07-28T23:32:56.313 に答える
0

または、すべてのプロジェクトで参照される単一の自動生成されたVersionInfo.csファイルを使用することもできます。この手法を使用するには、プロジェクトのAssemblyInfo.csファイルからバージョンや会社情報などの属性を取り除き(はい、これは面倒ですが、これを1回だけ実行する必要があります)、バッチコマンドで吐き出します。テンプレートに基づくVersionInfo.csファイル。Visual Studioで共通ファイルを参照するには、プロジェクトのコンテキストメニューから[既存のアイテムの追加]を選択し、ファイルブラウザーでVersionInfo.csファイルに移動した後、[追加]の横のドロップダウン矢印をクリックして[名前を付けて追加]を選択します。リンク。

以下は私が使用するものの例です。このスクリプトはSCCシステムにチェックインされ、ビルドの開始時に実行され、スクリプトに%BUILD_NUMBER%を提供します。

SET BUILD=%1

@echo using System.Reflection; > "%~p0Version.cs"
@echo [assembly: AssemblyCompany("MyCompany, Inc.")] >> "%~p0Version.cs"
@echo [assembly: AssemblyProduct("MyProduct")] >> "%~p0Version.cs"
@echo [assembly: AssemblyCopyright("Copyright © 2012 MyCompany, Inc.")] >> "%~p0Version.cs"
@echo [assembly: AssemblyTrademark("")]@echo [assembly: AssemblyVersion("1.0.%BUILD%.0")] >> "%~p0Version.cs"

@echo [assembly: AssemblyFileVersion("1.0.%BUILD%.0")] >> "%~p0Version.cs"

@echo ^<Include xmlns="http://schemas.microsoft.com/wix/2006/wi"^> > "%~p0Version.wxi"
@echo   ^<?define VersionBuild="%BUILD%"?^> >> "%~p0Version.wxi"
@echo ^</Include^> >> "%~p0\Version.wxi"
于 2012-07-26T12:05:52.040 に答える
0

コンパイルが必要なプロジェクトのリストを取得した場合でも、そのうちの1つのassemblyinfo.csを更新すると、別のプロジェクトのコンパイルをトリガーする変更が発生する可能性があります。

したがって、最も簡単な方法は、ソース管理のリビジョン番号に従ってすべてのAssemblyInfo.csファイルを生成することです。このプロジェクトの「最後の」変更がいつであったかを効果的に知ることで、各プロジェクトディレクトリの最新のリビジョン番号を取得することもできます。

この質問を参照してください:MSBuildを使用してAssemblyProduct、AssemblyTitleを変更するにはどうすればよいですか?

あなたのコメントによると、BeforeBuildおよびAfterBuildターゲット(csprojファイルの最後)を調べましたか?

  <Target Name="BeforeBuild">
  </Target>
  <Target Name="AfterBuild">
  </Target>
于 2012-07-26T11:47:11.763 に答える