question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Missing Linux `TargetFrameworkMoniker`

See original GitHub issue

Is your feature request related to a problem? Please describe.

I am trying to create a cross-platform project with platform-specific implementations of several classes.

For most platforms, it would be possible to use the TargetFrameworkMoniker to conditionally include files like MAUI does (see e.g. https://github.com/dotnet/maui/blob/main/src/Essentials/src/Essentials.csproj). However, no TargetFrameworkMoniker is available for Linux.

This currently being unavailable also has the consequence that APIs like https://github.com/dotnet/runtime/pull/69980/files need an [UnsupportedPlatform("windows")] attribute rather than only making the APIs available on Unix OSes.

Describe the solution you’d like

  • A net7.0-linux TargetFrameworkMoniker

  • alternative considered: OperatingSystem.IsLinux() - this relies on runtime analysis and makes methods larger or requires a wrapper that returns a platform-specific implementation at runtime. This also has the limitation that the called / referenced code needs to be referenced even when being compiled for Windows and vice versa - which leads to impossible situations. Especially for technology like bluetooth or other device support code you need to reference platform-specific TFMs which I believe you can’t do from a “neutral” net7.0 project.

  • alternative considered: using inverse #if to assume that

    if it is not Windows, iOS, Android, MacOS - it must be Linux

    Pseudocode: #if !(WINDOWS || MACOS || IOS || ANDROID). This seems brittle.

Additional context

These pages have no pointers about workarounds for this case:

Issue Analytics

  • State:open
  • Created a year ago
  • Reactions:4
  • Comments:6 (2 by maintainers)

github_iconTop GitHub Comments

10reactions
maxkatz6commented, Jan 25, 2023

This feature definitely needs more attention, as it is making it unreasonable difficult to work on multi-target libraries and applications.

Note, this issue and my comment is not about having platform specific API build-in, but about creating cross-platform projects that achieve these APIs by themselves or referencing platform specific packages.

While in theory I would agree with @mhutch and the original design idea, it doesn’t seem to reflect how Target Frameworks are used in reality.

For instance, MAUI supports multiple target frameworks - Windows, Mac Catalyst, Android, iOS, and Tizen. If a developer needs to create a library for MAUI and use native APIs, they need to target these frameworks. If a developer needs to create a single-project that will work on all of these frameworks - they can use multitargeting and include all of these targets in the same project.

It works pretty well until you want to extend the list of available frameworks. While it’s not a problem in MAUI (yet), it is already a problem in frameworks like Avalonia and Uno. We support Linux and browser targets as well. Which means we already cannot treat plain “net6.0” as Linux, because it can be a browser as well. As a reference, this PR is blocked because of missing TFM support.

In the end, we have a mix of:

  • Android and iOS which can only be differentiated by TFM. And you can’t easily run an application without such TFM.
  • Linux and Browser which can only be differentiated by RID as there is no TFM
  • Windows and Mac which has optional TFM with a set of platform-specific APIs like Android/iOS, but it also works and runs without any and has decent IDE support. Primarily because .NET Core was working fine on these platforms before “.NET 5” TFMs were introduced.

In order to support multiple platforms, developers now need to have a mix of TFM with #if/else directives for the well-supported platforms and OperatingSystem.IsLinux/IsBrowser runtime calls for “net6.0” (i.e. “other”). Not to mention, it gets complicated with NuGet packages that need to be somehow referenced from the “net6.0” for both Linux and browser (and without browser AOT compiled rightfully complaining about it).

If the .NET ecosystem switches from TFM to RID - that’s fine, but it seems to require way more changes including availability of platform-specific APIs.

As an example, there is an interesting project that has to build their own workload with custom TFM in order to achieve expected behavior.

1reaction
mhutchcommented, Nov 23, 2022

I think what’s actually missing here is the ability to compile for multiple RIDs.

TFMs are about the APIs that are available for your code to compile against, RIDs are about what platform/architecture your code runs on. If your implementation is specific to the platform that you run on, then should be a RID-specific implementation. However, we currently have no tooling for compiling a project for multiple RIDs, and packages that contain multiple RID-specific implementations currently must be constructed from the output of multiple projects. The lack of multi-RID support has les to folks using TFMs for this purpose instead.

We have two mechanisms for platform-specific APIs. We can put them in a platform-specific TFM, which is a good solution when exposing a large feature “area” such as an app model that is tightly bound to a single platform. Alternatively, we can make the API available on all platforms but only provide implementations on a subset of platforms. In this case, we use annotations and analyzers to indicate to the developer when they may need runtime checks in their code before calling the API. This is a lighter weight solution as it does not force consuming code to have platform-specific builds, and is great for smaller scale platform-specific feature such as a individual method to set a platform-specific option on a cross-platform feature. There is of course a continuum between these extremes and there’s not necessarily a “right” answer to which solution should be used. However, we do not yet have any Linux-specific APIs where a TFM would clearly be the better of the two options, which is why we don’t have the TFM (yet).

Read more comments on GitHub >

github_iconTop Results From Across the Web

How to properly target Linux as Target OS in VisualStudio ...
I am developing a .NET6.0 console app in VisualStudio 2022. The app will run on Linux. In project Properties/Application/General, there is a " ......
Read more >
Target frameworks in SDK-style projects - .NET
A target framework moniker (TFM) is a standardized token format for specifying the target framework of a .NET app or library. Target framework...
Read more >
Multi-targetting .Net Framework and .Net Core in a single project
A 15-second guide and 15-minute walk through. You have a .Net Core project, whether a netstandard library, or a netcore app, and you'd...
Read more >
What Does It Really Mean to Install a NuGet Package In ...
A: The manual package installation that we've performed (in effect a package restore operation, as we've seen in the post) is not controlled...
Read more >
.NET Core vs .NET Framework vs .NET Standard: A Guided ...
A guide for understanding the differences between .NET, .NET Core, .NET Framework, .NET Standard, etc. by exploring the history of the platform.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found