Reliably generating C# code in .NET Core 2.x csproj project?

Disclaimer: You seem to have things in your real project that isn't in the above, so I am unsure if this solution will work.

The following is a hacky method, in that it doesn't quite behave as it should.
However it maybe good enough for your purposes - that is for you to decide. The reason I say it is hacky is that the pre-build file deletion does seem to execute more than once.1

The csproj file that I have does this:

  1. Delete any files in the Generated directory. This is done through the CleanGen target and kicked off as an initial target in the Project node.
  2. The GeneratedCode target appends to the output file, so as to prove that it only happens once.
  3. The ItemGroup node is enabled to allow the generated file to be compiled.
  4. Echoes the variable $(NuGetPackageRoot) to show that it is set.

Complete csproj file here:

<Project InitialTargets="CleanGen" Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netstandard2.0</TargetFramework>
  </PropertyGroup>
  <Target Name="CleanGen">
    <Exec Command="echo 'Cleaning files...'" />
    <Exec Command="rm $(ProjectDir)Generated/*$(DefaultLanguageSourceExtension)" IgnoreExitCode="true" />
  </Target>
  <Target Name="GenerateCode" BeforeTargets="CoreCompile">
    <Exec Command="echo 'Generating files... $(NuGetPackageRoot)'" />
    <Exec Command="echo 'class GeneratedClass { public static int MESSAGE = 1; }' >> Generated/GeneratedClass.cs" />

    <ItemGroup>
      <Compile Include="Generated/*$(DefaultLanguageSourceExtension)" />
    </ItemGroup>
  </Target>
</Project>

This really does seem like it is harder than it should be...


1 OP notes that to avoid executing the rm command multiple times, you can add a Condition to Exec:

<Exec 
    Command="rm $(ProjectDir)Generated/*$(DefaultLanguageSourceExtension)"
    Condition="Exists('$(ProjectDir)Generated/GeneratedClass$(DefaultLanguageSourceExtension)')" />

Unfortunately Exists doesn't accept globs, so you have to specify at least one specific file that you know will be generated in that folder. With this compromise, you could also get rid of IgnoreExitCode="true" since it should only be executed when there are files to be deleted.