Skip to content

[build] try multi-targeting .NET 8 and 9 #1148

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

Draft
wants to merge 8 commits into
base: main
Choose a base branch
from

Conversation

jonathanpeppers
Copy link
Member

Context: #1118

This is a step to narrow down the API breaks in #1118.

I want to find out if any of them occur between .NET 8 and .NET 9.

Context: #1118

This is a step to narrow down the API breaks in #1118.

I want to find out if any of them occur between .NET 8 and .NET 9.
@jonathanpeppers jonathanpeppers added the do-not-merge PR is still in progress and is not ready to be merged label May 21, 2025
This reverts commit bc6ab0f.
generated\androidx.emoji2.emoji2-emojipicker\androidx.emoji2.emoji2-emojipicker.csproj : error NU1102: Unable to find package Xamarin.AndroidX.Emoji2 with version (>= 1.2.0.3 && < 1.2.1)
jonathanpeppers added a commit that referenced this pull request May 22, 2025
Context: #1148
Context: https://www.nuget.org/packages/Xamarin.AndroidX.Emoji2/1.2.0.2

When multi-targeting .NET 8 and 9, I got the error:

    generated\androidx.emoji2.emoji2-emojipicker\androidx.emoji2.emoji2-emojipicker.csproj :
    error NU1102: Unable to find package Xamarin.AndroidX.Emoji2 with version (>= 1.2.0.3 && < 1.2.1)

`Xamarin.AndroidX.Emoji2` version 1.2.0.3 doesn't actually exist?!?

I am not 100% sure why this failed when adding .NET 9, as the block in
`config.json` seems wrong:

    "nugetVersion": "1.2.0.3",

We should just fix this in `main`, as it will cause some other issue
down the line.
jonathanpeppers added a commit that referenced this pull request May 22, 2025
Context: #1148
Context: https://www.nuget.org/packages/Xamarin.AndroidX.Emoji2/1.2.0.2

When multi-targeting .NET 8 and 9, I got the error:

    generated\androidx.emoji2.emoji2-emojipicker\androidx.emoji2.emoji2-emojipicker.csproj :
    error NU1102: Unable to find package Xamarin.AndroidX.Emoji2 with version (>= 1.2.0.3 && < 1.2.1)

`Xamarin.AndroidX.Emoji2` version 1.2.0.3 doesn't actually exist?!?

I am not 100% sure why this failed when adding .NET 9, as the block in
`config.json` seems wrong:

    "nugetVersion": "1.2.0.3",

We should just fix this in `main`, as it will cause some other issue
down the line.
@jonathanpeppers
Copy link
Member Author

On the build output of this PR, I ran:

Get-Item *.nupkg | ForEach-Object { Write-Output "apicompat package $_" ; & apicompat package $_.Name 2>&1 | ForEach-Object { "$_" } } > apidiff.txt

Results in about ~452 errors: apidiff.txt

@jonathanpeppers
Copy link
Member Author

Looks like these ~452 errors are the same for net10.0-android:

#1118 (comment)

@jonathanpeppers
Copy link
Member Author

After reviewing an example:

CP0002: Member 'AndroidX.Activity.BackEventCompat.Companion.Companion(Kotlin.Jvm.Internal.DefaultConstructorMarker?)' exists on lib/net8.0-android34.0/Xamarin.AndroidX.Activity.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.Activity.dll

CP0002: Member 'AndroidX.Activity.BackEventCompat.Companion.Companion(Kotlin.Jvm.Internal.DefaultConstructorMarker?)' exists on lib/net8.0-android34.0/Xamarin.AndroidX.Activity.dll but not on lib/net10.0-android36.0/Xamarin.AndroidX.Activity.dll

This is due to .NET 8 binding "private" Kotlin constructors, we hide them in .NET 9+:

Now we are left with a more reasonable set:

apicompat package D:\Downloads\output-windows-net9\Xamarin.AndroidX.Core.1.16.0.1.nupkg
API compatibility errors between 'lib/net8.0-android34.0/Xamarin.AndroidX.Core.dll' (left) and 'lib/net9.0-android35.0/Xamarin.AndroidX.Core.dll' (right):
CP0001: Type 'AndroidX.Core.Provider.FontsContractCompat.Columns' exists on lib/net8.0-android34.0/Xamarin.AndroidX.Core.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.Core.dll
apicompat package D:\Downloads\output-windows-net9\Xamarin.AndroidX.TvProvider.1.0.0.34.nupkg
API compatibility errors between 'lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll' (left) and 'lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll' (right):
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.BaseTvColumns' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.BaseTvColumnsConsts' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.IBaseTvColumns' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.Channels' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.PreviewPrograms' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.Programs' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.RecordedPrograms' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.WatchNextPrograms' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
apicompat package D:\Downloads\output-windows-net9\Xamarin.AndroidX.Work.Runtime.2.10.0.4.nupkg
API compatibility errors between 'lib/net8.0-android34.0/Xamarin.AndroidX.Work.Runtime.dll' (left) and 'lib/net9.0-android35.0/Xamarin.AndroidX.Work.Runtime.dll' (right):
CP0002: Member 'void AndroidX.Work.Impl.Foreground.SystemForegroundService.OnTimeout(int, int)' exists on lib/net8.0-android34.0/Xamarin.AndroidX.Work.Runtime.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.Work.Runtime.dll
apicompat package D:\Downloads\output-windows-net9\Xamarin.Google.MLKit.Language.Id.117.0.6.3.nupkg
API compatibility errors between 'lib/net8.0-android34.0/Xamarin.Google.MLKit.Language.Id.dll' (left) and 'lib/net9.0-android35.0/Xamarin.Google.MLKit.Language.Id.dll' (right):
CP0005: Cannot add abstract member 'Java.Util.ISequencedCollection? Android.Gms.Internal.MLKitLanguageIdBundled.Zbi.Reversed()' to lib/net9.0-android35.0/Xamarin.Google.MLKit.Language.Id.dll because it does not exist on lib/net8.0-android34.0/Xamarin.Google.MLKit.Language.Id.dll

@moljac
Copy link
Contributor

moljac commented May 23, 2025

API compat errors

AndroidX.Core.Provider.FontsContractCompat.Columns

apicompat package D:\Downloads\output-windows-net9\Xamarin.AndroidX.Core.1.16.0.1.nupkg
API compatibility errors between 'lib/net8.0-android34.0/Xamarin.AndroidX.Core.dll' (left) and 'lib/net9.0-android35.0/Xamarin.AndroidX.Core.dll' (right):
CP0001: Type 'AndroidX.Core.Provider.FontsContractCompat.Columns' exists on lib/net8.0-android34.0/Xamarin.AndroidX.Core.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.Core.dll
generated-net8.0/androidx.core.core/obj/Release/net8.0-android/generated/src/AndroidX.Core.Provider.FontsContractCompat.cs
generated/androidx.core.core/obj/Release/net10.0-android/generated/src/AndroidX.Core.Provider.FontsContractCompat.cs
generated/androidx.core.core/obj/Release/net8.0-android/generated/src/AndroidX.Core.Provider.FontsContractCompat.cs
    <class abstract="false" deprecated="not deprecated" extends="java.lang.Object" extends-generic-aware="java.lang.Object" jni-extends="Ljava/lang/Object;" 
    final="true" name="FontsContractCompat.Columns" static="true" visibility="public" jni-signature="Landroidx/core/provider/FontsContractCompat$Columns;">
      <implements name="android.provider.BaseColumns" name-generic-aware="android.provider.BaseColumns" jni-type="Landroid/provider/BaseColumns;" />

AndroidX.TvProvider.Media.Tv.TvContractCompat

apicompat package D:\Downloads\output-windows-net9\Xamarin.AndroidX.TvProvider.1.0.0.34.nupkg
API compatibility errors between 'lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll' (left) and 'lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll' (right):
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.BaseTvColumns' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.BaseTvColumnsConsts' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.IBaseTvColumns' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.Channels' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.PreviewPrograms' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.Programs' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.RecordedPrograms' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll
CP0001: Type 'AndroidX.TvProvider.Media.Tv.TvContractCompat.WatchNextPrograms' exists on lib/net8.0-android34.0/Xamarin.AndroidX.TvProvider.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.TvProvider.dll

Ctor internal:

[Register("androidx/tvprovider/media/tv/TvContractCompat$BaseTvColumns", DoNotGenerateAcw = true)]
public abstract class BaseTvColumns : Object
{
    [Register("COLUMN_PACKAGE_NAME")]
    public const string ColumnPackageName = "package_name";

    internal BaseTvColumns()
    {
    }
}

AndroidX.Work.Impl.Foreground.SystemForegroundService.OnTimeout

apicompat package D:\Downloads\output-windows-net9\Xamarin.AndroidX.Work.Runtime.2.10.0.4.nupkg
API compatibility errors between 'lib/net8.0-android34.0/Xamarin.AndroidX.Work.Runtime.dll' (left) and 'lib/net9.0-android35.0/Xamarin.AndroidX.Work.Runtime.dll' (right):
CP0002: Member 'void AndroidX.Work.Impl.Foreground.SystemForegroundService.OnTimeout(int, int)' exists on lib/net8.0-android34.0/Xamarin.AndroidX.Work.Runtime.dll but not on lib/net9.0-android35.0/Xamarin.AndroidX.Work.Runtime.dll
generated-net8.0/androidx.work.work-runtime/obj/Release/net8.0-android/generated/src/AndroidX.Work.Impl.Foreground.SystemForegroundService.cs
generated/androidx.work.work-runtime/obj/Release/net10.0-android/generated/src/AndroidX.Work.Impl.Foreground.SystemForegroundService.cs
generated/androidx.work.work-runtime/obj/Release/net8.0-android/generated/src/AndroidX.Work.Impl.Foreground.SystemForegroundService.cs
		// Metadata.xml XPath method reference: path="/api/package[@name='androidx.work.impl.foreground']/class[@name='SystemForegroundService']/method[@name='onTimeout' and count(parameter)=2 and parameter[1][@type='int'] and parameter[2][@type='int']]"
		[Register ("onTimeout", "(II)V", "GetOnTimeout_IIHandler")]
		public virtual unsafe void OnTimeout (int startId, int fgsType)

Impl namespace.

Android.Gms.Internal.MLKitLanguageIdBundled.Zbi.Reversed()

apicompat package D:\Downloads\output-windows-net9\Xamarin.Google.MLKit.Language.Id.117.0.6.3.nupkg
API compatibility errors between 'lib/net8.0-android34.0/Xamarin.Google.MLKit.Language.Id.dll' (left) and 'lib/net9.0-android35.0/Xamarin.Google.MLKit.Language.Id.dll' (right):
CP0005: Cannot add abstract member 'Java.Util.ISequencedCollection? Android.Gms.Internal.MLKitLanguageIdBundled.Zbi.Reversed()' to lib/net9.0-android35.0/Xamarin.Google.MLKit.Language.Id.dll because it does not exist on lib/net8.0-android34.0/Xamarin.Google.MLKit.Language.Id.dll

Seems like interface method surfaced in net10.0:

	// Metadata.xml XPath class reference: path="/api/package[@name='com.google.android.gms.internal.mlkit_language_id_bundled']/class[@name='zbi']"
	[global::Android.Runtime.Register ("com/google/android/gms/internal/mlkit_language_id_bundled/zbi", DoNotGenerateAcw=true)]
	public abstract partial class Zbi : global::Android.Gms.Internal.MLKitLanguageIdBundled.Zbf, global::Java.Util.IList, global::Java.Util.IRandomAccess {

Internal namespace.

jonathanpeppers added a commit that referenced this pull request May 23, 2025
Context: dotnet/maui#28997
Context: #1148

.NET 10 binding assemblies have changes to generate better code to
support trimming and NativeAOT scenarios.

We want to ship a copy of .NET 10 assemblies alongside their `net8.0-android`
counterparts.

To verify API compatibility between the `net8.0-android` and `net10.0-android`
assemblies you can run:

    dotnet tool install --global Microsoft.DotNet.ApiCompat.Tool
    Get-Item *.nupkg | ForEach-Object { Write-Output "apicompat package $_" ; & apicompat package $_.Name 2>&1 | ForEach-Object { "$_" } } > apidiff.txt

At first, we saw ~452 errors, but all appear to be due to changes toward
"hiding" internal Kotlin members in .NET 9:

* dotnet/java-interop@06214ff

General list of changes:

* Update `_PackageLevelCustomizations.cshtml`
* metadata + Additions cleanup for net10.0
* `nuget.config` from dotnet/android added
* <CheckEolWorkloads>false</CheckEolWorkloads> needed to work around some warnings and errors
* Create nuget-install.cake
* Provision `platforms/android-34`
* `Update Metadata.xml`

    obj/Controls.DeviceTests/Debug/net10.0-android/android/src/mono/androidx/recyclerview/widget/RecyclerView_ItemAnimator_ItemAnimatorListenerImplementor.java(8,57): javac error JAVAC0000:  error: ItemAnimatorListener is not public in ItemAnimator; cannot be accessed from outside package

* [build] remove `Install extra Android SDK packages`
* `$(AndroidManifestType)=GoogleV2`

    Warning : Dependency `platforms;android-36` should have been installed but could not be resolved. You can attempt to install it with...

* Restore BaseOnOffsetChangedListener metadata.xml

    javac.exe error JAVAC0000:  error: BaseOnOffsetChangedListener cannot be inherited with different arguments: <com.google.android.material.appbar.AppBarLayout> and <>

* Fix javac error for `ActivityChooserModel`

    Xamarin.Android.Javac.targets(161,5): error XAJVC0000: C:\a\_work\1\s\artifacts\obj\Benchmarks.Droid\Release\net10.0-android\android-arm64\android\src\mono\androidx\appcompat\widget\ActivityChooserModel_OnChooseActivityListenerImplementor.java:8: error: package androidx.appcompat.widget.ActivityChooserModel does not exist
Xamarin.Android.Javac.targets(161,5): error XAJVC0000: 		androidx.appcompat.widget.ActivityChooserModel.OnChooseActivityListener
Xamarin.Android.Javac.targets(161,5): error XAJVC0000: 		                                              ^

Co-authored-by: Peter Collins <pecolli@microsoft.com>
Co-authored-by: Jonathan Peppers <jonathan.peppers@microsoft.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
do-not-merge PR is still in progress and is not ready to be merged
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants