dotnet / msbuild

The Microsoft Build Engine (MSBuild) is the build platform for .NET and Visual Studio.
https://docs.microsoft.com/visualstudio/msbuild/msbuild
MIT License
5.21k stars 1.35k forks source link

Project targeting .NET 6 cannot use Microsoft.Build 17.4.0 nuget package. #8166

Open KubaOczko opened 1 year ago

KubaOczko commented 1 year ago

I have a general question,

My project is targeting .NET 6, I won't be able to retarget it to the .NET 7 at least for a year.

I saw available updates for Microsoft.Build nuget package, but the new version of the package doesn't have target for .NET 6. The net48 was used instead (with warnings).

Should I stay on 17.3.2 ? The .NET 6 will be supported until November 2024, in case of any issue (e.g security) is there a plan to release a new 17.3.X version or I will be forced to retarged to the .NET 7?

Thanks

rainersigwald commented 1 year ago

Should I stay on 17.3.2 ?

That depends on what you're using MSBuild for. Can you describe what your project does? For instance, is it defining a task or a logger assembly? Is it using the API to evaluate or build projects?

If you want to be able to load and build projects that use the .NET 7 SDK, you must be on the .NET 7 runtime yourself (because that's a requirement for loading/using the SDK).

in case of any issue (e.g security) is there a plan to release a new 17.3.X version or I will be forced to retarged to the .NET 7?

In the event of a security issue, all supported versions of MSBuild will be updated. For MSBuild, NuGet package reference updates are generally less important than updating SDK/Visual Studio instances, because the package is generally used only at compile time--at runtime, the MSBuild assemblies should be provided by the host (if you have a task or logger), or located by MSBuildLocator. Of course, that's not to say that you shouldn't update if we issue an update :)

KubaOczko commented 1 year ago

That depends on what you're using MSBuild for. Can you describe what your project does? For instance, is it defining a task or a logger assembly? Is it using the API to evaluate or build projects?

We are using the following classes from the package

SolutionFile ProjectInSolution

It's used within our build pipeline to clean-up a development source from the public one...

TBH I don't understand what are the rules that define whether or not a package will be valid for the currently supported project (net6) within the dotnet ecosystem. All other packages generated from this repo are fine, thanks to the netstandard target.

It's not related just to this repo, we are seeing many issues across the dotnet repos/packages regarding nuget package targeting after the net7 release.

We are building a framework based on the dotnet, so we are more in a B2B position, and we can't drop the net6 support easily...

ViktorHofer commented 1 year ago

@rainersigwald FWIW for .NET 8 we support three versions of modern .NET in dotnet/runtime libraries packages.

We build, package and ship all three versions intentionally to a) satisfy source build (always target the very latest) and b) support LTS and STS customers as those runtimes are still in support when we ship .NET 8.

For .NET 7 we included the net6.0 asset in the package as .NET 6 (LTS) was still in support when we shipped.

With the upcoming "VMR - Virtual Monolithic Repository" and source build constraints, we will likely aim for something similar to what we have in runtime (just with refined names) and then just filter out TFMs during a vertical source build, so that only NetCoreAppCurrent and netstandard2.0 remain in projects.

rainersigwald commented 1 year ago

@ViktorHofer Our situtation is a bit different because we're not "just a library"; instead using our API is more like "getting access to a build environment". And that build environment is packaged with and expects a specific runtime--.NET SDK 7.0.100 cannot run on the .NET 6.0 runtime. So if you want to use APIs that are new to MSBuild-packaged-in-.NET-SDK-8.0, you must run on .NET 8. I don't think it makes sense to package a net6 version of MSBuild with those new APIs because you couldn't use them.

carstencodes commented 1 year ago

Hey,

we're actually facing a simular issue in https://github.com/dspace-group/dscom/pull/155 .

We could actually narrow it down to a - from my point of view - NuGet misbehavior. - Well, ok, NuGet behaves correctly, but the specification of this concrete NuGet Package is questionable.

The NuGet package is shipped with five Assemblies, two in the lib folder marking runtime and compile time dependencies, three in the refs repository marking compile-time only dependencies according to https://learn.microsoft.com/en-us/nuget/create-packages/creating-a-package#create-the-nuspec-file .

Our unit tests targets net6 and net48. So when running dotnet restore, the project.assets.json will be generated for net48 having two references - a runtime and a compile-time dependency. For net6, only a compile-time dependecy to .NET Standard will be generated leading to a FileNotFoundException at runtime.

At regular runtime, this will actually not affect behavior of the task, since the assembly will be loaded and provided by the MsBuild installation at run-time. Hence, for assemblies only relying on the .NET Standard interface of the task, the compile-time will succeed.

As a matter of fact, .NET Standard was the right solution outside of Multi-Targetting builds. In these days, it is only confusing.

As @rainersigwald mentioned:

So if you want to use APIs that are new to MSBuild-packaged-in-.NET-SDK-8.0, you must run on .NET 8. I don't think it makes sense to package a net6 version of MSBuild with those new APIs because you couldn't use them.

I apparently do agree.

BUT: Due to the described behavior, it is not detectable whether this package must be run with .NET 7 or .NET 6, as it complies to .NET Standard 2.0, which is fulfilled by .NET 6.

From my point of view, there are three ways of dealing with this issue:

  1. Ignore all updates of dependencies. (Heavily not recommended and just for the sake of completeness).
  2. Give dotnet restore the ability to ignore netstandard compliant packages and face only runtime-compliant packages.
  3. For this particular case: Drop the .NET Standard 2.0 compatibility of the package, as it is heavily misleading.

@rainersigwald @ViktorHofer What is your opinion on this?