-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Visual Studio restore is broken as projects are missing from the dependency closure #65552
Comments
Tagging subscribers to this area: @dotnet/area-infrastructure-libraries Issue DetailsSince I applied various fixes to the product over the last weeks that should make the overall IDE experience better I wanted to try them out and had to realize with dismay that the integrated Visual Studio restore is still broken if an upfront restore via the CLI ( The root cause for that lies in this code path: Lines 8 to 11 in cc649ac
ProjectReference items to be present in the solution file and ignores Reference items as those point to the compiled assembly and there's nothing for restore to do on those.
As an example, ref/System.Drawing.Common.csproj inside If I remove the condition in the slngen.targets file and re-generate all solution files ( Because of that I propose that we remove the condition in the slngen.targets file with the caveat that solutions get bigger but with the huge win that up-front restores aren't necessary anymore. That means instead of: build.cmd libs.ref
build.cmd -restore libs
build.cmd -vs System.Runtime I can now directly open VS after the libs.ref subset is built: build.cmd libs.ref
start src\libraries\System.Runtime\System.Runtime.sln or just continue to use the VS switch for convenience (which also uses the repo local SDK which is useful when a matching one isn't globally installed): build.cmd libs.ref
build.cmd -vs System.Runtime Ultimately at some point in the future when source projects use @ericstj @safern @joperezr @carlossanlop any objections to what I'm proposing?
|
Would love to hear people's opinion about the above described issue. What I heard from the recent community survey is that one of the top pain points is that solution files in our repositories can't be opened without ceremony involved. Fixing the VS restore by making sure that the dependency closure is satisfied by the solution files would get us closer to the community's wish. |
I'm not opposed to what you are proposing, but I think that is still not what the community wants. The main ask here would be to be able to open a solution in VS after a clean The current upfront restore in a traditional machine with a decent network, doesn't really take that much (around 2 minutes). I am sure that with your proposed changes this is reduced greatly, but have you measured that and if so can you share some of the perf impact? I guess my uber point is, before we go about and make some changes that will have notable differences to all (people will start seeing 50+ projects inside the ref/ folder in the solution) we should measure and make sure that the cost is worth the benefit, especially since the end result is not meeting the desired community result. |
I guess the tradeoff for some here is the sln size and build performance. You've also done more work recently to improve that. For example System.Runtime, System.Text.Json, and Microsoft.Extensions.Logging? I think those are somewhat representative of the developer workflows for bottom, middle, and top of stack. |
Can you change that to My opinion is roughly inline with @joperezr above - if I need to run something up front, I'd rather that "up front" cost be more and my incremental cost (building constantly in VS, running tests, etc) be lower. After pulling new code, I kick off a repo |
I spent some more time thinking about how to fix the current broken behavior without increasing the build graph. Out-of-band projects already build on-top of the shared framework since we split the libs build into "libs.sfx" and "libs.oob". As these projects already sit on the top, we can just use the default targeting pack references for OOBs and remove the ProjectReferences that point to inbox projects. Note that this is already the behavior for most OOB source projects. Overall that will actually make the build graph and by that, solution files smaller for OOBs. If I don't hear any objections I would like to give that a try and prepare a PR that will better demonstrate what I'm proposing. |
#68543 accidentally closed this issue. Reopening. |
from @joperezr
Infrastructure that lives in Arcade is built and packaged there and we consume those libraries the usual way via PackageReferences, which are part of a project's restore. Your statement that these need to be up-front restored before a solution can be opened isn't right. NuGet is part of Visual Studio and makes sure that all dependencies (PackageReferences, PackageDownload, FrameworkReferences, msbuild sdks, ...) are restored on the fly. You can test this by opening i.e. System.Runtime.sln (or any other solution where P2Ps are in sync between ref and src, like System.Runtime.ComilerServices.Unsafe) from a fresh clone and building the ref and the source assembly in it. If I'm not mistaken, everything should build just fine without an up-front restore. The reason why most src/libraries solutions can't be opened from a fresh clone is because dependencies inside the shared framework aren't defined via ProjectReference items. As an example, from @ericstj
With recent improvements (#68488, #68543 and #68603), a project's build graph is now as short as possible. Before these changes were merged, a project's build graph contained many unnecessary dependencies, which impacted both the evaluation and restore/build performance.
I can finally share some data based on #68668 which builds on top of the improvements listed above.
In some cases the number of projects in the solution file drops, in most cases it increases between 1-5 projects and in a few cases it increases between 10-15 projects. The time it takes to load and evaluate the solution file shouldn't change much by adding this number of projects. Visual Studio invested a lot in evaluation, Intellisense and restore performance over the last years. @ericstj regarding incremental build performance, I'm not sure what you ask me to verify. AFAIK Visual Studio's fast up-to-date check doesn't incrementally build projects that haven't changed (based on inputs & outputs). from @eerhardt
You probably mean that as a general statement and I fully agree with that. Just to clarify, I don't expect #68668 to increase the incremental cost in any noticeable way (based on VS's fast up-to-date check). |
My suggestion was to show others that the impact of this change on their daily work is minimal and that the tradeoff is a good one.
Very cool. Testing that out in these cases and confirming that we don't do anything funny in dotnet/runtime to break that would be a good piece of data to share here. Maybe share the time to do a build for these sln's once they are loaded with no changes over what was already built up front? Also the time for build after a comment change in the src library? I think these small checks and the new data you've shared around the actual number of projects (which is much less than 50 per sln) address the concerns raised by @joperezr and @eerhardt. |
Let me explain how Visual Studio actually performs fast up-to-date checks:
Here's an example of a fast up-to-date check from VS's output window after I made a comment change to the source assembly. You can see that VS doesn't even attempt to incrementally build dependencies that aren't impacted:
I noticed that System.Private.CoreLib always incrementally builds as fast up-to-date checks seem to not work for it. I filed #68698 to track that.
I ❤️ open source so I filed a bug that I found while working with the project system tools: dotnet/project-system-tools#439.
Numbers are from my Surface Book 2 which in contrast to most devs on the team is a quite slow machine. Visual Studio 17.2 Preview 5. As already mentioned before, the numbers below are exactly the same on main as builds of dependencies are skipped when they are up-to-date. I made to sure wait until background tasks completed and triggered multiple builds to get the right average.
My assumption is that VS uses a fallback mechanism when dependencies are missing from the solution which makes the build actually slower.
That's hard to measure as the libs root build only builds the current vertical (ie Windows on a Windows machine) in contrast to VS which builds all configurations. I could measure this with an all-configurations build but that wouldn't be representative as devs rarely build in that mode from the root. I believe that the the shared data already demonstrates that the changes doesn't regress the performance inside VS except for initially evaluating and populating the fast-up-date check cache. These two steps are naturally slower but as said, based on the low number of projects being added to the solutions I couldn't measure any real impact. |
Since I applied various fixes to the product over the last weeks that should make the overall IDE experience better I wanted to try them out and had to realize with dismay that the integrated Visual Studio restore is still broken if an upfront restore via the CLI (
dotnet restore
) isn't performed. The impact of that is that the solution is unusable.The root cause for that lies in this code path:
runtime/eng/slngen.targets
Lines 8 to 11 in cc649ac
ProjectReference
items to be present in the solution file and ignoresReference
items as those point to the compiled assembly and there's nothing for restore to do on those.As an example, ref/System.Drawing.Common.csproj inside
System.Runtime.sln
is depending on ref/System.Collections.NonGeneric.csproj but as it is missing, the restore inside Visual Studio fails.If I remove the condition in the slngen.targets file and re-generate all solution files (
dotnet.cmd build src\libraries\slngen.proj
), the solution files get larger by about 50 ref projects (as the solution now includes all dependencies) but the solution restore finally works and no up-front restore is necessary anymore. Note that because the reference projects are very small and fast to evaluate, the solution load time doesn't increase noticeably and the solution doesn't look overloaded as all the added projects are grouped inside the "ref" folder (tested with VS 2022 17.2 Preview 1).Because of that I propose that we remove the condition in the slngen.targets file with the caveat that solutions get bigger but with the huge win that up-front restores aren't necessary anymore. That means instead of:
I can now directly open VS after the libs.ref subset is built:
build.cmd libs.sfx /p:RefOnly=true start src\libraries\System.Runtime\System.Runtime.sln
or just continue to use the VS switch for convenience (which also uses the repo local SDK which is useful when a matching one isn't globally installed):
Ultimately at some point in the future when source projects use
ProjectReference
items instead ofReference
items to dynamically express their dependencies, thebuild.cmd libs.ref
step won't be necessary anymore either and a dev will be able to directly open a VS solution file from a fresh clone.@ericstj @safern @joperezr @carlossanlop any objections to what I'm proposing?
The text was updated successfully, but these errors were encountered: