Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save benvillalobos/c671baa1e32127f4ab582a5abd66b005 to your computer and use it in GitHub Desktop.
Save benvillalobos/c671baa1e32127f4ab582a5abd66b005 to your computer and use it in GitHub Desktop.
MSBuild vs. Generated Files

Including Generated Files Into Your Build

Files that get generated during the build behave differently from static files (eg. source files). For this reason, it's important to understand How MSBuild Builds Projects. I'll cover the main two phases here at a high level.

Evaluation Phase

  • MSBuild reads your project, imports everything, creates Properties, expands globs for Items outside of Targets, and sets up the build process.

Execution Phase

  • MSBuild runs Targets & Tasks with the provided Properties & Items in order to perform the build.

Key Takeaway: Files generated during execution don't exist during evaluation, therefore they aren't included in the build process.

The solution? When the files are generated, manually add them into the build process. The recommended way to do this is by adding the new file to the Content or None items before the BeforeBuild target.

Here's a sample target that does this:

<Target Name="Foo" BeforeTargets="BeforeBuild">
  
  <!-- Some logic that generates your file goes here -->
  <!-- Note: We recommend generating your files into $(IntermediateOutputPath)   -->

  <ItemGroup>
    <!-- If your generated file was placed in `obj\` -->
    <None Include="$(IntermediateOutputPath)my-generated-file.xyz" 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-generated-file.xyz" 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>

Adding your generated file to None or Content is sufficient for the build process to see it. You also want to ensure it gets added at the right time. Ideally, your target runs before BeforeBuild. AssignTargetPaths is another option, as it is the "final stop" before None and Content items (among others) are transformed into new items.

Relevant Links:

How MSBuild Builds Projects

Evaluation Phase

Execution Phase

Common Item Types

How the SDK imports items by default

This article, but in MSBuild's official docs page

@Kiryuumaru
Copy link

Thank you for creating this. I tried it with .NET MAUI, I generated a CSS file during build time and it was copied in the "bin" but not in both "obj" and published apps. Any suggestions on how to automatically copy the file on .NET MAUI?

@benvillalobos
Copy link
Author

Good question! If you're familiar with spelunking through binlogs, you can try to find the target that publishes stuff, probably named Publish, and working backwards to see what items get copied to the publish folder. I should create a doc about working backwards this way, as it's not intuitive...

Doing a search for \publish\ (in a binlog) might do the trick and show you all the files that point to that directory. You can work backwards from there to find the name of the item that gets copied into the publish folder. Then, you can create your own target that runs BeforeTargets=Publish to add your css file to that item.

I have some binlog docs over at https://github.com/BenVillalobos/msbuildism, but it's a WIP repo. In the meantime you can start a discussion at https://github.com/dotnet/msbuild to get more assistance if needed!

@benvillalobos
Copy link
Author

benvillalobos commented Nov 22, 2022

I added a section for this sort of problem here: https://github.com/BenVillalobos/msbuildism/tree/main/build-spelunking#1-a-file-was-copied-to-x-but-not-y

Let me know if its unclear in any way and I can get back to it another time.

Edit: Also added a section on following the paper trail, while I was there.

@Kiryuumaru
Copy link

Thank you for the fast response. I will look into it

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment