Skip to content

.NET 8: Enable build and run of project with arbitrary TFM #11613

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

Open
richlander opened this issue May 12, 2020 · 10 comments
Open

.NET 8: Enable build and run of project with arbitrary TFM #11613

richlander opened this issue May 12, 2020 · 10 comments
Milestone

Comments

@richlander
Copy link
Member

richlander commented May 12, 2020

I write a bunch of samples that I want to enable for developers to learn the product. TFMs are a limiting artifact when you want to enable a project to run on a newer runtime even though it targets an older one. I feel badly when I change the TFM solely to get to the app to run on a newer runtime.

App I am using: https://github.com/richlander/testapps/tree/master/versioninfo

In past, I used the TargetFrameworks approach, like the following:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFrameworks>netcoreapp3.0;net5.0</TargetFrameworks>
  </PropertyGroup>

</Project>

This is a pain, because dotnet build does the following:

PS D:\git\testapps\versioninfo> dotnet run
Unable to run your project
Your project targets multiple frameworks. Specify which framework to run using '--framework'.

That's unacceptable as a default experience for samples, and only to enable a more advanced scenario.

Next approach is to configure the project for the min-support TFM and then mutate via the CLI:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
  </PropertyGroup>

</Project>
PS D:\git\testapps\versioninfo> dotnet run
**.NET Core info**
Version: 3.1.2
FrameworkDescription: .NET Core 3.1.2
CoreCLR Build: 3.1.2-servicing.20066.2
CoreCLR Hash: fd22fd600a2526a7c58536da0e80325eb710d7f1
CoreFX Build: 3.1.2
CoreFX Hash: e946cebe43a510e8c6476bbc8185d1445df33a1a

**Environment info**
OSVersion: Microsoft Windows NT 6.2.9200.0
OSDescription: Microsoft Windows 10.0.19624
OSArchitecture: X64
ProcessorCount: 8

PS D:\git\testapps\versioninfo> dotnet build /p:TargetFramework=net5.0
Microsoft (R) Build Engine version 16.7.0-preview-20220-01+80e487bff for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.

  Determining projects to restore...
  Restored D:\git\testapps\versioninfo\versioninfo.csproj (in 61 ms).
  You are using a preview version of .NET. See: https://aka.ms/dotnet-core-preview
  versioninfo -> D:\git\testapps\versioninfo\bin\Debug\net5.0\versioninfo.dll

Build succeeded.
    0 Warning(s)
    0 Error(s)

Time Elapsed 00:00:00.83
PS D:\git\testapps\versioninfo> .\bin\Debug\net5.0\versioninfo.exe
**.NET Core info**
Version: 5.0.0
FrameworkDescription: .NET 5.0.0-preview.4.20227.9
CoreCLR Build: 5.0.0-preview.4.20227.9
CoreCLR Hash: 6d1f7e01d3429054ec3dcb7c75b3450b9fe1429e
CoreFX Build: 5.0.0-preview.4.20227.9
CoreFX Hash: 6d1f7e01d3429054ec3dcb7c75b3450b9fe1429e

**Environment info**
OSVersion: Microsoft Windows NT 10.0.19624.0
OSDescription: Microsoft Windows 10.0.19624
OSArchitecture: X64
ProcessorCount: 8

PS D:\git\testapps\versioninfo> dotnet run /p:TargetFramework=net5.0
/p:TargetFramework=net5.0
**.NET Core info**
Version: 3.1.2
FrameworkDescription: .NET Core 3.1.2
CoreCLR Build: 3.1.2-servicing.20066.2
CoreCLR Hash: fd22fd600a2526a7c58536da0e80325eb710d7f1
CoreFX Build: 3.1.2
CoreFX Hash: e946cebe43a510e8c6476bbc8185d1445df33a1a

**Environment info**
OSVersion: Microsoft Windows NT 6.2.9200.0
OSDescription: Microsoft Windows 10.0.19624
OSArchitecture: X64
ProcessorCount: 8

PS D:\git\testapps\versioninfo> dotnet run /p:TargetFramework=net5.0 -- arguments
/p:TargetFramework=net5.0
arguments
**.NET Core info**
Version: 3.1.2
FrameworkDescription: .NET Core 3.1.2
CoreCLR Build: 3.1.2-servicing.20066.2
CoreCLR Hash: fd22fd600a2526a7c58536da0e80325eb710d7f1
CoreFX Build: 3.1.2
CoreFX Hash: e946cebe43a510e8c6476bbc8185d1445df33a1a

**Environment info**
OSVersion: Microsoft Windows NT 6.2.9200.0
OSDescription: Microsoft Windows 10.0.19624
OSArchitecture: X64
ProcessorCount: 8

I added the following code to the app to print arguments.

            foreach(var a in args)
            {
                Console.WriteLine(a);
            }

The approach with /p:TargetFramework seems to be generally working, but is failing for the run case. The docs suggest that what I'm doing should be working.

Can my preferred pattern be enabled? This: dotnet run /p:TargetFramework=net5.0 --. That'd be awesome.

Not what I want, but I did discover that the following pattern works:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <TargetFrameworks>netcoreapp3.0;net5.0</TargetFrameworks>
  </PropertyGroup>

</Project>
PS D:\git\testapps\versioninfo> dotnet run
**.NET Core info**
Version: 3.1.2
FrameworkDescription: .NET Core 3.1.2
CoreCLR Build: 3.1.2-servicing.20066.2
CoreCLR Hash: fd22fd600a2526a7c58536da0e80325eb710d7f1
CoreFX Build: 3.1.2
CoreFX Hash: e946cebe43a510e8c6476bbc8185d1445df33a1a

**Environment info**
OSVersion: Microsoft Windows NT 6.2.9200.0
OSDescription: Microsoft Windows 10.0.19624
OSArchitecture: X64
ProcessorCount: 8

PS D:\git\testapps\versioninfo> dotnet run -f net5.0
**.NET Core info**
Version: 5.0.0
FrameworkDescription: .NET 5.0.0-preview.4.20227.9
CoreCLR Build: 5.0.0-preview.4.20227.9
CoreCLR Hash: 6d1f7e01d3429054ec3dcb7c75b3450b9fe1429e
CoreFX Build: 5.0.0-preview.4.20227.9
CoreFX Hash: 6d1f7e01d3429054ec3dcb7c75b3450b9fe1429e

**Environment info**
OSVersion: Microsoft Windows NT 10.0.19624.0
OSDescription: Microsoft Windows 10.0.19624
OSArchitecture: X64
ProcessorCount: 8

For clarity, I don't like this approach for two reasons:

  • It is an abomination of the project format.
  • It requires including all the TFMs I want to support. This is similar to how RIDs were in 1.0. Super painful.

On the one hand, the existing dotnet build support for my use case is satisfactory (super happy it works), but on the other, it seems the scenario is broken for dotnet run where run and build should have parity.

So, I think this should be fixed. Thanks!

@richlander richlander changed the title Enable building project with arbitrary TFM Enable build and run of project with arbitrary TFM May 12, 2020
@jkotas
Copy link
Member

jkotas commented May 12, 2020

<TargetFramework>netcoreapp$(NETCoreAppMaximumVersion)</TargetFramework> works as "latest" since .NET Core 3.0.

It would be nice if one can say <TargetFramework>latest</TargetFramework> to get the latest. Or even better - default to latest if TargetFramework is not specified.

@richlander
Copy link
Member Author

Ya, what Jan is talk to is really even more clearly articulating what I'm after. There are really two scenarios, ordered in (my) priority order:

  1. Target max supported TFM of the given SDK, by default.
  2. Target an arbitrary TFM via the CLI.

These two experiences are not mutually exclusive.

In terms of Jan's actual suggestions, I prefer the absence of TargetFramework to default to the latest supported TFM for the SDK. Obviously, the macro he uses should continue to work. The latest string idea is nice but I think it is more likely to confuse people since latest is defined per SDK, and is not the latest actual .NET release (in any kind of global sense).

@dsplaisted
Copy link
Member

What if you had an app that compiled against a fixed version of .NET Core (ie netcoreapp3.1) but at runtime would roll forward to the latest installed version. Wouldn't that solve your problem?

@richlander
Copy link
Member Author

That is similar but not semantically the same. For example, imagine you have 3.1, 5.0 and 6.0 on the machine, and you want the app to run on 5.0. You can do that via global.json (with the proposed scheme) but not via TFM = 3.0 and the roll-forward knobs. The roll-forward knobs offer course-grained control, while the TFM offers fine-grained.

The TFM does two things:

  • Governs the APIs you see.
  • Governs the .NET version your app will use (by default).

I'm obviously focused on the second one. The TFM is the only mechanism that has the level of control that I'm after.

@dasMulli
Copy link
Contributor

I noticed quite a few people complaining (esp on the asp.net core slack) that dotnet run has no way of passing in msbuild varaibles, so people do the dotnet build -p:Foo=Bar && dotnet run --no-build dance..

@richlander
Copy link
Member Author

This isn't working for me either.

D:\git\testapps\versioninfo>bin\Debug\netcoreapp3.0\versioninfo.exe --roll-forward=LatestMajor --
--roll-forward=LatestMajor
--
**.NET Core info**
Version: 3.1.2
FrameworkDescription: .NET Core 3.1.2
CoreCLR Build: 3.1.2-servicing.20066.2
CoreCLR Hash: fd22fd600a2526a7c58536da0e80325eb710d7f1
CoreFX Build: 3.1.2
CoreFX Hash: e946cebe43a510e8c6476bbc8185d1445df33a1a

**Environment info**
OSVersion: Microsoft Windows NT 6.2.9200.0
OSDescription: Microsoft Windows 10.0.19624
OSArchitecture: X64
ProcessorCount: 8

Same thing if I set the ENV.

D:\git\testapps\versioninfo>set DOT
DOTNET_ROLL_FORWARD=LatestMajor

/cc @vitek-karas

@vitek-karas
Copy link
Member

The command line syntax doesn't use = sign, so it should be:
versioninfo.exe --roll-forward LatestMajor

And the reason why it doesn't run on 5 is that 5 is pre-release and by default we don't roll forward from release to pre-release. (The reason is so that installing a pre-release version doesn't break existing apps ever).

You can turn that off by setting:
set DOTNET_ROLL_FORWARD_TO_PRERELEASE=1

After that both the command line (See above without the = sign) as well as the env. variable DOTNET_ROLL_FORWARD (which you got right) should make the app run on 5 (if you have it installed).

@richlander
Copy link
Member Author

Works. Thanks. I now remember discussing all these things. Thanks for your patience.

The main issue still applies, after this little interlude.

@richlander richlander added this to the 8.0.1xx milestone Jun 25, 2022
@richlander richlander changed the title Enable build and run of project with arbitrary TFM .NET 8: Enable build and run of project with arbitrary TFM Jun 25, 2022
@richlander
Copy link
Member Author

Related to: dotnet/runtime#71286

@KalleOlaviNiemitalo
Copy link
Contributor

PS D:\git\testapps\versioninfo> dotnet run
Unable to run your project
Your project targets multiple frameworks. Specify which framework to run using '--framework'.

#38990 is a request to remove this error and instead make dotnet run automatically choose a target framework.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants