次の方法で共有


生成されたファイルを処理するようにビルドをカスタマイズする

特定のビルドでは、ビルド中に生成されるファイルは、静的ファイル (ソース ファイルなど) とは異なる動作をします。 このため、 MSBuild がプロジェクトをビルドする方法を理解することが重要です。 2 つのフェーズは 、評価フェーズ実行フェーズです。 評価フェーズ中、MSBuild はプロジェクトを読み取り、すべてをインポートし、プロパティを作成し、項目の glob を展開して、ビルド プロセスを設定します。 実行フェーズ中に、MSBuild は、評価フェーズ中に解析されたデータを使用してターゲットとタスクを実行することによってビルドを実行します。

実行中に生成されたファイルは評価フェーズ中に存在しないため、ビルド プロセスには含まれません。 この問題を解決するには、生成されたファイルをビルド プロセスに手動で追加する必要があります。 これを行うには、次の例のように、新しいファイルをBeforeBuildターゲットの前のContentまたはNone項目に追加することをお勧めします。

<Target Name="MyTarget" BeforeTargets="BeforeBuild">
  
  <!-- Some logic that generates your file goes here -->
  <!-- Generated files should be placed in $(IntermediateOutputPath) -->
  <WriteLinesToFile
      File="$(IntermediateOutputPath)GeneratedFile.cs"
      Lines='enum MyEnum { A, B }'
      Overwrite="true" />
    <ItemGroup>
      <Compile Include="$(IntermediateOutputPath)GeneratedFile.cs" />
    </ItemGroup>

  <ItemGroup>
    <!-- If your generated file was placed in `obj\` -->
    <None Include="$(IntermediateOutputPath)GeneratedFile.cs" TargetPath="GeneratedFile.cs" CopyToOutputDirectory="PreserveNewest"/>
    <!-- If you know exactly where that file is going to be, you can hard code the path. -->
    <None Include="some\specific\path\my-generatedfile" CopyToOutputDirectory="PreserveNewest"/>
    
    <!-- If you want to capture "all files of a certain type", you can glob like so. -->
    <None Include="some\specific\path\*.xyz" CopyToOutputDirectory="PreserveNewest"/>
    <None Include="some\specific\path\*.*" CopyToOutputDirectory="PreserveNewest"/>
  </ItemGroup>
</Target>

<Target Name="CleanGeneratedCode" AfterTargets="CoreClean">
  <Delete Files="$(IntermediateOutputPath)GeneratedFile.cs" />
</Target>

生成されたファイルを None または Content に追加するだけで、ビルド プロセスでファイルが表示されます。 また、適切なタイミングで追加されるようにする必要もあります。 理想的には、ターゲットは BeforeBuild前に実行されます。 AssignTargetPaths は、新しい項目に変換される前に None および Content 項目を変更する最終的な機会であるため、もう 1 つのターゲットとして考えられます。 「共通項目の種類」を参照してください。

上記をコピーしてファイルに貼り付け、 buildcodegen.targets呼び出します。 次に、 dotnet new console実行し、ファイルをインポートし、ビルドして動作を確認します。

<Project Sdk="Microsoft.NET.Sdk">
  <Import Project="buildcodegen.targets"/>
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net9.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
</Project>

msbuild.exe 実行し、出力を確認して、ファイルが生成され、出力フォルダーにコピーされたことを確認します。 ildasm.exe を使用して、生成されたコード MyEnumが出力バイナリに含まれることを確認できます。

ildasm CodeGen.dll

次のステップ

この例は、より現実的なユース ケースをサポートするように改善できます。 たとえば、生成されたコードが入力ファイルに依存する場合に インクリメンタル ビルド をサポートするには、 InputsOutputs をターゲットに提供する必要があります。 このようなターゲットでは、入力ファイルまたはファイルの日付が出力ファイルよりも新しい場合にのみ、ファイルが再生成されます。 多くの場合、コード生成用にカスタマイズするときは、カスタム タスクを作成することをお勧めします。 コード生成用のカスタム タスクの作成を参照してください。