Owner Immo Landwerth
In .NET 5.0 we defined a new syntax for target frameworks (TFM) that makes it unnecessary for both tools and humans to use a decoder ring, such as the .NET Standard version table, to figure out what is compatible with what. In this document, we're listing which TFMs we're adding in .NET 6.0.
Sophia is building an application for Android. From her experience with
Xamarin.Android she knows the library Xamarin.FFImageLoading
and wants to
use it. The package installs successfully, but upon building she gets the
following warning:
Package 'Xamarin.FFImageLoading' was restored using 'monoandroid' instead of the project target framework 'net6.0-android'. This package may not be fully compatible with your project.
To find out more, she visits the package's project site, which is on GitHub. She decides to file an issue to ask whether the library will add support for .NET 6, but for the time being she's unblocked and can continue to develop her app.
- Support the definition of frameworks relevant for Xamarin development
- Re-design the TFM syntax
- MSBuild / SDK team
- NuGet team
- Project system team
- Xamarin team
TFM | Compatible With |
---|---|
net6.0 | (subsequent version of net5.0) |
net6.0-windows | (subsequent version of net5.0-windows) |
net6.0-android | monoandroid |
(+everything else inherited from net6.0) | |
net6.0-ios | everything inherited from net6.0 (only) |
net6.0-macos | everything inherited from net6.0 (only) |
net6.0-maccatalyst | everything inherited from net6.0 (only) |
net6.0-tvos | everything inherited from net6.0 (only) |
net6.0-tizen | tizen |
(+everything else inherited from net6.0) |
The built-in compatibility rules of the netX.Y-platform
TFMs make a
TFM automatically compatible with:
- Itself
- Earlier versions of itself
- The corresponding
netX.Y
TFM - Earlier versions of the corresponding
netX.Y
TFM
The net5.0
TFM has the additional twist that it's compatible with
netcoreapp3.1
(and earlier), netstandard2.1
(and earlier) as well as .NET
Framework (net4x
and earlier, but under a warning). The .NET Framework
compatibility is achieved as a fallback, that is, it's only used when nothing
else applies.
We don't want to model the Xamarin TFMs as a fallback but instead want them to
apply before netcoreapp
and netstandard
. Usually the existence of the
Xamarin TFM implementation is to bait a netstandard
API and switch the
platform specific implementation. Most of the Plugin type packages use this
pattern and in fact the netstandard
"implementation" is more like a reference
assembly with just stubs that throw at runtime. Xamarin.Essentials
is a good
example of this. The same rational can be applied to netcoreapp
where this
would logically be the server implementation (or maybe a .NET Core 3.x desktop
implementation).
A net6.0-android
project referencing a NuGet package should behave as
follows:
- It should prefer
monoandroid
assets overnetcoreapp
,netstandard
, andnet5.0
assets.- However, it should still prefer
net6.0
assets overmonoandroid
. - It also shouldn't be compatible with any other existing Xamarin TFM (such
as
xamarin.mac
)
- However, it should still prefer
- Generate NuGet warning NU1701 when a
monoandroid
asset is being used- Package 'packageId' was restored using 'monoandroid' instead the project target framework 'net6.0-android'. This package may not be fully compatible with your project.
- Should only use compatible
net5.0
based TFMs, namelynet5.0
,net6.0
, andnet6.0-android
.
The net6.0-ios
, net6.0-tvos
and net6.0-macos
TFMs are not compatible
with the previous xamarin*
versions, because they contain breaking changes
that makes existing assets unusable.
This reasoning results in these precedence rules:
net6.0-ios
net6.0-ios
net6.0
net5.0
netcoreapp3.1
–1.0
netstandard2.1
–1.0
net4.x
–1.0
(warning)
net6.0-maccatalyst
net6.0-maccatalyst
net6.0
net5.0
netcoreapp3.1
–1.0
netstandard2.1
–1.0
net4.x
– `1.0 (NU1701 warning)
net6.0-macos
net6.0-macos
net6.0
net5.0
netcoreapp3.1
–1.0
netstandard2.1
–1.0
net4.x
–1.0
(NU1701 warning)
net6.0-tvos
net6.0-tvos
net6.0
net5.0
netcoreapp3.1
–1.0
netstandard2.1
–1.0
net4.x
–1.0
(NU1701 warning)
net6.0-android
net6.0-android
net6.0
monoandroid12.0
-1.0
(no warning)net5.0
netcoreapp3.1
–1.0
netstandard2.1
–1.0
net4.x
–1.0
(NU1701 warning)
The currently supported monoandroid
TFMs are:
monoandroid1.0
monoandroid4.4
monoandroid4.4.87
monoandroid5.0
monoandroid5.1
monoandroid6.0
monoandroid7.0
monoandroid7.1
monoandroid8.0
monoandroid8.1
monoandroid9.0
monoandroid10.0
monoandroid11.0
monoandroid12.0
net6.0-tizen
net6.0-tizen
net6.0
tizen
(no warning)net5.0
netcoreapp3.1
–1.0
netstandard2.1
–1.0
net4.x
–1.0
(NU1701 warning)
We need to add platform detection APIs for Mac Catalyst:
namespace System
{
public partial class OperatingSystem
{
public static bool IsMacCatalyst();
public static bool IsMacCatalystVersionAtLeast(int major, int minor = 0, int build = 0);
}
}
It seems the Xamarin team wants to have a single assembly with bindings for the
iOS platforms (e.g. Mac Catalyst and iOS). The APIs should be annotated with
[SupportedOSPlatform]
and don't need any [UnsupportedOSPlatform]
(the
absence of a platform is interpreted as the platform not being supported). For
instance:
public class SomeType
{
[SupportedOSPlatform("ios8.0")]
[SupportedOSPlatform("maccatalyst13.0")]
public void MethodSupportedOn_iOS_and_Mac_Catalyst();
[SupportedOSPlatform("ios8.0")]
public void MethodSupportedOn_iOS_Only();
[SupportedOSPlatform("maccatalyst13.0")]
public void MethodSupportedOn_Mac_Catalyst_Only();
}
However, from a user experience it's irrelevant if the Xamarin team provides the
bindings in separate libraries or in a single library because there is no TFM
that developers can use to build a single binary that can work in both Mac
Catalyst and iOS. A developer either has to target Mac Catalyst (via
net6.0-maccatalyst
) or iOS (via net6.0-ios
). Of course, the developer can
multi-target for both but that means two binaries are being produced which means
the Xamarin bindings could also be provided as separate libraries.
This is slightly different for cross-platform BCL APIs. Here we'd follow the path we took for Blazor WebAssembly and mark APIs that don't work in Xamarin with attributes like `[UnsupportedOSPlatform("iOS")].
We need to add RIDs for all these platforms:
net6.0-android
android
android-arm
android-arm64
android-x64
android-x86
android.21
android.21-arm
android.21-arm64
android.21-x64
android.21-x86
android.22
android.22-arm
android.22-arm64
android.22-x64
android.22-x86
android.23
android.23-arm
android.23-arm64
android.23-x64
android.23-x86
android.24
android.24-arm
android.24-arm64
android.24-x64
android.24-x86
android.25
android.25-arm
android.25-arm64
android.25-x64
android.25-x86
android.26
android.26-arm
android.26-arm64
android.26-x64
android.26-x86
android.27
android.27-arm
android.27-arm64
android.27-x64
android.27-x86
android.28
android.28-arm
android.28-arm64
android.28-x64
android.28-x86
android.29
android.29-arm
android.29-arm64
android.29-x64
android.29-x86
android.30
android.30-arm
android.30-arm64
android.30-x64
android.30-x86
net6.0-ios
ios
ios-arm
ios-arm64
ios-x64
ios-x86
ios.8
ios.8-arm
ios.8-arm64
ios.8-x64
ios.8-x86
ios.9
ios.9-arm
ios.9-arm64
ios.9-x64
ios.9-x86
ios.10
ios.10-arm
ios.10-arm64
ios.10-x64
ios.10-x86
ios.11
ios.11-arm64
ios.11-x64
ios.12
ios.12-arm64
ios.12-x64
ios.13
ios.13-arm64
ios.13-x64
ios.14
ios.14-arm64
ios.14-x64
net6.0-maccatalyst
maccatalyst-arm64
maccatalyst-x64
maccatalyst.13-arm64
maccatalyst.13-x64
maccatalyst.14-arm64
maccatalyst.14-x64
net6.0-macos
osx
osx-arm64
osx-x64
osx.10.10
osx.10.10-arm64
osx.10.10-x64
osx.10.11
osx.10.11-arm64
osx.10.11-x64
osx.10.12
osx.10.12-arm64
osx.10.12-x64
osx.10.13
osx.10.13-arm64
osx.10.13-x64
osx.10.14
osx.10.14-arm64
osx.10.14-x64
osx.10.15
osx.10.15-arm64
osx.10.15-x64
osx.10.16
osx.10.16-arm64
osx.10.16-x64
osx.11.0
osx.11.0-arm64
osx.11.0-x64
net6.0-tvos
tvos
tvos-arm64
tvos-x64
tvos.10
tvos.10-arm64
tvos.10-x64
tvos.11
tvos.11-arm64
tvos.11-x64
tvos.12
tvos.12-arm64
tvos.12-x64
tvos.13
tvos.13-arm64
tvos.13-x64
tvos.14
tvos.14-arm64
tvos.14-x64
net6.0-tizen
tizen
tizen-armel
tizen-arm64
tizen-x86
tizen.4.0.0
tizen.4.0.0-armel
tizen.4.0.0-arm64
tizen.4.0.0-x86
tizen.5.0.0
tizen.5.0.0-armel
tizen.5.0.0-arm64
tizen.5.0.0-x86
tizen.5.5.0
tizen.5.5.0-armel
tizen.5.5.0-arm64
tizen.5.5.0-x86
tizen.6.0.0
tizen.6.0.0-armel
tizen.6.0.0-arm64
tizen.6.0.0-x86
tizen.6.5.0
tizen.6.5.0-armel
tizen.6.5.0-arm64
tizen.6.5.0-x86
We didn't want a secondary dash because it implies some relationship with
net6.0-macos
. Also, in the past we talked about supporting prefix-based
compatibility rules with more levels, using a dash for this new TFM would make
it harder to add support for this later.
Looks like Apple refers to it as "Mac Catalyst".
net6.0-ios
(and the other Apple TFMs, net6.0-tvos
and net6.0-macos
)
contains breaking changes that makes binaries built for
existing Xamarin TFMs unusable.
The expectation is that libraries that want to work on iOS and Mac Catalyst
would use net6.0
or multi-target for net6.0-ios
and net6.0-maccatalyst