dotnet / project-system

The .NET Project System for Visual Studio
MIT License
968 stars 387 forks source link

Build & Run - only one TFM in multi-target project #1699

Open rainersigwald opened 7 years ago

rainersigwald commented 7 years ago

Copied from original issue https://github.com/Microsoft/msbuild/issues/1818 posted by @onovotny

When making changes to multi-targeted libraries, the project system/MSBuild has to rebuild all TFM's as part of the build graph. This is not necessary if I want to run an app on a particular TFM. The build system should only build the necessary closest TFM.

Concrete example:

Actual results The library is built twice, once per TFM

Expected results Library is built once

Note, if I just build the library or the sln, it should build all. This is an optimization for when I build a specific library/app/output that depends on another one and it knows which one it needs.

rainersigwald commented 7 years ago

Migrating this here because MSBuild and the Sdk do the right thing--a command line build of the app builds only the net45 version of the lib in this example.

Visual Studio, though, sees that the project is out of date and invokes "Build" on the "outer" instance of the project, which in turn builds all TFMs.

davkean commented 7 years ago

I don't think there's a lot we can do here due to the current design of build inside Visual Studio. Unlike the command-line, MSBuild itself is not the scheduler of solution builds; the VS Solution Build Manager is.

MSBuild via command-line can be smart here and only build what's actually required for a reference because as it builds references at the point it resolves them.

Inside VS, references are built by Solution Build Manager. Previously we had told the Solution Build Manager "hey this entire project is our dependency", so when we kick off a build due to an F5 for a given project, it just looks at all the dependencies of that project and builds them (entirely) in dependency order. There's no extra context that we can pass to say "hey we only need .NET 4.5 bits from this dependency".

DomZZ commented 2 years ago

We build a web product that contains around 150 .net 4.6.2 projects, we would like to migrate to .net 6.0 framework but we can't do this in one shot, it is a long background task. To achive this it could be handy to use multi targetting and conditionnal preprocessing (#if tfm). But the problem is that it will impact a lot the compilation time since actually when we compile a solution all multitarget projets are built in all specified targets !

I could modify all csproj and change tag content on our CI but it seems a bit hackish.

Is there something more conventionnal ?

Thanks