dotnet / dotnet/sdk

Support base TFM resolution for .NET CLI --framework options

Open
#55,821 0 comments 0 reactions 0 assignees View on GitHub
untriaged
Dominant language
C#
Stars
3.2k
Forks
1.3k
PR merge metrics
PR metrics pending

Description

### Is your feature request related to a problem?

Yes.

.NET CLI commands that accept `--framework` currently require the specified framework to match a project's target framework exactly. They do not resolve a base TFM against the project's declared `TargetFramework` or `TargetFrameworks`.

This becomes particularly problematic when a command is invoked against a **solution file containing projects with different or platform-qualified TFMs**.

For example:

MySolution.slnx
├── Framework.csproj
│ TargetFrameworks = net10.0

├── Framework.UI.Windows.csproj
│ TargetFrameworks = net10.0-windows

└── Framework.UI.csproj
TargetFrameworks = net10.0-windows;net10.0-android

Given:

`dotnet build MySolution.slnx --framework net10.0`

`net10.0` is currently treated as an exact framework selection rather than as a base TFM that can be resolved independently for each project.

Consequently, a project targeting `net10.0-windows` cannot resolve the requested `net10.0` to its applicable `net10.0-windows` target framework.

This can result in:
`
error NETSDK1136: The target platform must be set to Windows (usually by including '-windows' in the TargetFramework property) when using Windows Forms or WPF, or referencing projects or packages that do so.
`
The same issue can affect other .NET CLI commands that use `--framework`, such as `dotnet test`, `dotnet run`, and such, where applicable.

This issue is particularly relevant to solution builds because a solution does not define the `TargetFramework`/`TargetFrameworks` of its contained projects. That information belongs to each individual project.

This can also result in real-world CI failures when projects evolve from an unqualified TFM to a platform-qualified TFM, or add platform-qualified TFMs, while the CI invocation continues to request the same base TFM.

### Describe the solution you'd like

I would like .NET CLI `--framework` options to support base TFM resolution against each project's declared target frameworks.

For example, given:

`net10.0-windows;net10.0-android`

the following should be able to use `net10.0` as the framework request:

`dotnet build MyProject.csproj --framework net10.0`

and resolve the request against the project's target frameworks.

The same should apply when building a solution:

`dotnet build MySolution.slnx --framework net10.0`

The resolution should occur **independently for each project**, examining all of that project's declared `TargetFramework`/`TargetFrameworks` values and resolving **all target frameworks whose base TFM matches the requested framework**.

For example:

```
Requested framework:
net10.0

Framework.csproj
→ net10.0

Framework.UI.Windows.csproj
→ net10.0-windows

Framework.UI.csproj
→ net10.0-windows
→ net10.0-android
```

A single requested base TFM may resolve to multiple concrete target frameworks for the same project. Each resolved TFM should result in its own inner build.

For example, given:

`net10.0-windows;net10.0-android`

a single:

`--framework net10.0`

may resolve to:

```
net10.0-windows
net10.0-android
```
and therefore result in two inner builds of that project:

```
Project
├── inner build: net10.0-windows
└── inner build: net10.0-android
```
The caller should not need to specify both concrete TFMs explicitly.

The same resolution behavior should be available consistently to other applicable .NET CLI commands that expose `--framework`.

Exact framework requests should continue to work as they do today. For example:

`dotnet build MyProject.csproj --framework net10.0-windows`

should continue to select `net10.0-windows` exactly.

The precise matching and precedence rules can be determined by the SDK/MSBuild implementation. The important behavior is that a base TFM can be resolved to **all applicable concrete TFMs** in the context of the individual project.

When a solution is built with --framework, the framework request should be passed to each contained project, where it can be resolved against that project's own TargetFramework/TargetFrameworks. The solution build should not need to enumerate or resolve the target frameworks of its contained projects itself.

`--framework` should be capable of resolving a requested base TFM against all applicable target frameworks declared by each project, with each resolved target framework producing its corresponding inner build.

### Alternatives you've considered

One alternative is for external build infrastructure to enumerate every project's `TargetFramework`/`TargetFrameworks` and construct project-specific framework arguments.

For example:

```
Framework.csproj
net10.0

Framework.UI.Windows.csproj
net10.0-windows

Framework.UI.csproj
net10.0-windows;net10.0-android
```

and then invoke each project separately with its concrete TFM.

However, this duplicates project metadata in external build infrastructure and becomes increasingly verbose as projects and target frameworks evolve.

Another alternative is to require callers to specify all concrete TFMs:

`--framework "net10.0;net10.0-windows;net10.0-android"`

This does not solve the solution-level problem cleanly because the same requested base TFM can correspond to different concrete TFMs in different projects. It can also cause unnecessary framework selections for projects that do not target those TFMs.

For example, a solution containing:

```
Framework.csproj
net10.0

Framework.UI.Windows.csproj
net10.0-windows
```
should not require the caller to know both project-specific TFMs merely to request the `net10.0` framework family.

The preferred solution is therefore **project-level framework resolution within the existing `--framework` mechanism**, rather than requiring the solution, CI system, or another external caller to reproduce each project's target-framework information.

### Additional context

This feature request concerns **TFM resolution only**. It is not about the MSBuild `Platform` property such as `AnyCPU`, `x64`, or `ARM64`, and it is not about runtime identifiers.

The desired model is:

```
--framework


.NET CLI command


solution/project build

├── Project A
│ └── resolve all TargetFramework(s) matching the requested base TFM

├── Project B
│ └── resolve all TargetFramework(s) matching the requested base TFM

└── Project C
└── resolve all TargetFramework(s) matching the requested base TFM
```

rather than requiring the solution or caller to perform the resolution itself.

The existing `--framework` option can remain unchanged from the user's perspective. The requested enhancement is to make its framework-selection semantics capable of resolving a requested base TFM to **all concrete target framework(s) whose base TFM matches the requested base TFM**.

The underlying SDK/MSBuild infrastructure already has target-framework and framework/platform information available during project evaluation and multi-targeting. The requested functionality would allow that project-level information to participate in `--framework` resolution instead of limiting the option to exact TFM matching.

Contributor guide

No contributing guide indexed for this repository

Research direction

Start by tracing how dotnet build, dotnet test, and dotnet run consume --framework and how each project’s TargetFramework/TargetFrameworks is evaluated, including solution forwarding. Done means exact requests remain unchanged, while a base request resolves independently per project to all matching concrete TFMs and produces the corresponding inner builds.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
build-system, cli
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
42/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.