Get better incremental build performance by opting in to reference assembly based builds by defaulting ProduceReferenceAssembly
to true.
Since this is a behaviour change, it may be good to do it in 3.0 and for SDK projects only.
@peterhuene I'm not sure who I should mention for this.
maybe @rainersigwald has more info about the current support for this across project systems, he mentioned a year ago that the classic project systems may have troubles with it, but that was when the feature was newly implemented.
@davkean were you looking into this?
@davkean ping 馃槃
@rainersigwald @dsplaisted @peterhuene @livarcocc @nguerrera any objections?
I'm still worried about the effect in VS on projects that have a reference to an SDK project but are themselves a non-SDK csproj-project-system project. Would love to find out that that's all been fixed but I don't think it has, yet.
cc @pilchie My understanding is that we intend for this to be the default in 3.0
I'm still worried about the effect in VS on projects that have a reference to an SDK project but are themselves a non-SDK csproj-project-system project
Are you worried about a mix of projects with ProduceReferenceAssembly=true/false irrespective of SDK/non-SDK? Shouldn't that be supported?
Would love to find out that that's all been fixed but I don't think it has
What is it that might not be fixed?
Are you worried about a mix of projects with ProduceReferenceAssembly=true/false irrespective of SDK/non-SDK?
Yes--but it gets worse if all SDK projects flip the switch.
What is it that might not be fixed?
Incremental build scenarios in VS like those fixed in the CPS project system by https://github.com/dotnet/project-system/pull/2414 and its follow-ups.
Incremental build scenarios in VS like those fixed in the CPS project system by dotnet/project-system#2414 and its follow-ups.
@panopticoncentral @Pilchie Are there such issues in the classic project system still unfixed? Are they tracked? Is it feasible to get them fixed in dev16?
Ok, I did a small proof-of-concept that things are still broken.
MixedSolutionWithRefAssemblies.zip
This solution has:
The unit test project tests library functionality by calling the app that calls the library.
========== Build: 3 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
diff --git a/Lib/Class1.cs b/Lib/Class1.cs
index a33c4c0..76a1c90 100644
--- a/Lib/Class1.cs
+++ b/Lib/Class1.cs
@@ -6,7 +6,7 @@ namespace Lib
{
public static int Add(int a, int b)
{
- return a - b; // note deliberate error
+ return a + b;
}
}
}
========== Build: 1 succeeded, 0 failed, 2 up-to-date, 0 skipped ==========
That's because the fast-up-to-date check in csproj doesn't understand that it needs to tell MSBuild to build the app even though its direct input (the lib.dll
reference assembly) hasn't changed. CoreCompile
will be skipped, but the build will copy the implementation assembly along, so that the updated implementation is available at runtime.
Thanks, @rainersigwald. I filed this as https://github.com/dotnet/project-system/issues/4079, which we think from the discussion yesterd would be blocking this.
Ugh - I wasn't aware that there were still issues here :(
dotnet/project-system#4079 is closed as won't fix. Does this mean we can never turn this on by default? :(
cc @tmeschter @jjmew @livarcocc
Turning it on by default will only be a problem in solutions that mix SDK and non-SDK-style projects, and even then only while CSProj is the default project system for non-SDK-style projects.
We have to draw the line somewhere for new feature work in CSProj.
I don't remember all the details of ref assemblies off the top of my head, but would it be possible to have non-SDK projects _not_ consume ref assemblies by default even if the project produces them? Then SDK projects could default to producing them and everything would work. It would also help in the situation where someone manually turns it on and breaks the up to date check for non-SDK projects.
@panopticoncentral That sounds like a good idea. It looks like the consuming side can set CompileUsingReferenceAssemblies=false if I read the code right just now. I'm not quite sure on the best way to make that default false for classic, true for sdk style. Thoughts, @rainersigwald? I'm slightly worried that this would be unexpected for someone that is already using ProduceReferenceAssembly with classic projects in the mix.
We could maybe set it to false in common.props for everyone, and rely on the SDK to set it to true? But that's a design change (it was intended as an opt-out, not opt-in, but we also didn't anticipate this problem, so . . .).
So turning it to false would make build times slower for people already using it with the caveat that they never had working intellisense for their apps.
At least it shouldn't (馃檹) break their builds if no further customization was performed.
Poking at this again - Could this be safely enabled for .NET 5 projects?
I guess people will be less likely to use .NET Standard projects so not doing anything for these would not run in to the classic project system errors since net5 projects cannot be referenced by .NET Framework.
@dasMulli your reasoning sounds correct to me, and I think that's a reasonable stake in the ground.
In our sync-up, we decided to go ahead with enabling this by default for .NET 5.0 and higher.
Potentially related: https://github.com/NuGet/Home/issues/4184
When NuGet adds support for packing ref assemblies into a package, we'd likely have to hinge off of ProduceReferenceAssembly=true in one way or another.
This change likely means NuGet would need another switch to pack ref assemblies.
It's a lesser concern, but just covering all the basis
Also related: I think .net core should move where it default places generated reference assemblies. When I tried to fix that issue on NuGet/Home, I got snagged where it would mistakenly replace the runtime version with the reference one as well which was no good at all just because the ref directory is under the one for the runtime version so moving them to $(OutDir)\ref\$(TargetFramework)
seems to me to be a more sane approach to this for net5 or newer (or with them all).
https://github.com/NuGet/Home/issues/4184#issuecomment-629020587
Also another option is to force all old style csproj's to convert to sdk style to kill off the old style.
Is this new default the root cause for all my projects getting these unwanted ref folders under $(OutDir)? Is this really the right place for these ref assemblies? Shouldn't these be under an entirely separate directory (next to obj and bin?) so that they don't get deployed together with actual binaries by default?
These files shouldn't be part of the dotnet publish
output so not end up in deployments. If so, I suggest opening new issues about that.
Most helpful comment
In our sync-up, we decided to go ahead with enabling this by default for .NET 5.0 and higher.