Content rebuilds every single build

As far as I can tell no one else in the world is having this problem. I already asked this on the discord and on reddit and people don’t have any idea… But I’ll throw it into the void and see if anything jumps out at the experts here.

So here’s the deal, every time I build (using Visual Studio’s CTRL+SHIFT+B or F5) with zero code changes, one of two things happens:

  • All of my Content gets rebuilt. Evidenced by the output showing the paths of each item of my Content with none of them prepended with “Skipped”
  • Most of the Content gets skipped, but then the sound files (.ogg files) get rebuilt. This is basically the same as above because my content consists of mostly pngs and oggs, the pngs are really fast regardless but the oggs are agonizingly long. The only real difference is the output is slightly different.

A few weeks ago the “normal” behavior used to be that I’d start up my computer after a cold boot and the first build would need to rebuild Content (weird, right?) but then subsequent builds wouldn’t (except for random one-off times where it would?) this didn’t really get in my way so much so I didn’t care. But about a week ago it started happening every. single. build and it really sucks!

Some things that might make my environment special that could (maybe??) be the cause:

  • (I don’t think the IDE is a factor but…) I’m running Visual Studio 2019 in Windows 10, although Jetbrains Rider does the same thing (I actually first started noticing this problem when I was using Rider).
  • I’m using NuGet to get MonoGame.Framework.DesktopGL at, as well as the MonoGame.Content.Builder.Task at the same version.
  • The main csproj I’m building is straight from the DesktopGL template.
  • Build a DesktopGL project that has most of the Content, as well as a Shared Project that has some of the Content in a mirrored file structure, the resulting build output contains one file structure with xnbs from both.
  • I’m also using a csproj project reference for the Game Engine, which is also a DesktopGL project.
  • I’m using MonoGame.Extended (I highly doubt that has anything to do with it, just being thorough)
  • This isn’t just this one game project. I’ve had this same bug happen with several projects (with similar topologies to this one, so maybe that’s a hint)

Some other things I’ve learned:

  • As far as I can tell MGCB is innocent in all this. If I build straight from the MGCB GUI it’s able to detect what’s already been built and skip over it just fine.
  • I poked around in the build targets (I’m not an msbuild expert, everything I know about msbuild I learned so I could debug this problem) and I found the actual MGCB commands that were run, and if I run them in the command line they do the right thing and skip over built stuff.

Diagram of my project topology

This has been the biggest motivation killer for me. I miss my 2 second builds and I really don’t want to need to do build finaggling to just get the basic functionality that’s supposed to already come out of the box.

Remember when there was an option to copy files if newer or something like that, in the editor? I am reminded of that…

So your current problem would persist even on a NEW and unrelated project? -That eliminates your code as the problem…
All I can think of then is settings somewhere global that spans all your projects, ie your editor or some other tool. Maybe even the framework or extensions for all I know, if you are using some experimental or undercooked version.

So your current problem would persist even on a NEW and unrelated project? -That eliminates your code as the problem…

Yes and no. All of my projects use a git submodule containing the engine csproj and the shared project (and then they’re setup like the diagram I have above). So it still could be something about that configuration. I’ll try to verify that and maybe isolate some steps to reproduce.

All I can think of then is settings somewhere global that spans all your projects, ie your editor or some other tool.

Good point. I’m getting the same bad behavior when I use dotnet build in the directory with the sln, so it’s not tied to any particular editor. Might still be some other tool.

This project should theoretically repro (and it does in my local directory where it was created) but when I clone it down it stops reproing. I did with with another project and it fixed it for a little while but then after a few days it started happening again. Which is super weird!

Anyway here’s the repro-that-doesn’t-actually-repro:

git clone
cd ld49
git submodule update --init --recursive
dotnet build

The way I worked around this the first time was creating a fresh clone of my project from GitHub and working off of that instead. It seems that if it’s a freshly cloned copy of the project it doesn’t have the bug. Within a few days though it started to do it again, implying something changes over time that isn’t tracked by git. The only way I know how to reliably repro this is to try to get work done in the project until you hit it again (which isn’t helpful for you-- I’ll see if I can find a better one).

One would think that if a freshly copied clone works but a more stale repo doesn’t, then a git clean would get me back into a happy state. Let’s investigate that:

I ran git clean -dfXn in my main project that’s been having this issue to see what git isn’t tracking and I see:

git clean -dfXn
Would remove .vs/
Would remove Rogue/Content/bin/
Would remove Rogue/Content/obj/
Would remove Rogue/Properties/launchSettings.json
Would remove Rogue/bin/
Would remove Rogue/obj/
// I have some code that takes periodic progress screenshots and puts them here
Would remove Rogue/screenshots/
Would remove TestRogue/bin/
Would remove TestRogue/obj/
// text files I keep to myself at the root level of the repo, not tracked in git
Would remove notes.txt
Would remove todo.txt

// Ran it again in the submodule...
git clean -dfXn
Would remove Machina/bin/
Would remove Machina/obj/
// MachinaAssets is the one with Content
Would remove MachinaAssets/Content/bin/
Would remove MachinaAssets/Content/obj/
Would remove TestMachina/bin/
Would remove TestMachina/obj/

I ran git clean -dfX (same command minus the -n) in the main repo (not the submodule). I built once (using dotnet build so no editor involved) to get the first round of content and the second build skipped over all the ogg files (hooray!!). But then it went and rebuilt the files in the shared project (which live in the submodule and weren’t cleaned). No problem, I thought, I’ll just go into the submodule and git clean again. I did that, rebuilt and… I’m back where I started. :frowning:

I can’t even reproduce the success I had earlier. Now if I clean the main repo it just rebuilds everything.

So now we have this weird contradictory behavior where a fresh clone won’t reproduce the bug but a git cleaned old repo will still reproduce it. I have no idea what to make of that.

Don’t mean to ignore, but I have no ideas. It’s above my pay-grade. I work within the normal framework, and use locally stored files, with no versions. so good luck.

I’m not expecting anyone to have an answer for me at this point. I’m just documenting for future people.

Some key insights:

  • I switch machines to my windows laptop for a week and I rarely saw this bug. However I did see a tiny bit of overbuilding (sometimes content would rebuild after a cold boot).
  • I switched to a linux installation for a month and I never saw the bug there. It built content once when I cloned the repo and never again.

So the problem is either with Windows or something about my particular editor setup.

My normal development flow uses VS2019 (for development) and VS Code (running in my second monitor to handle git merges, etc). I noticed that the bug seems to be somewhat correlated to when VS Code is open (even though VS Code isn’t doing the building). I also have another insight I turned off the VS Code C# plugin and it seems to have gone away. My current hypothesis is the VS Code C# plugin was doing some building in the background and kept putting the content folder in a weird state.

Or there’s just something weird about my exact machine configuration. That’s also possible.