From d605221dcf0f17564e62c6cdb34703a7cef9017c Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:49 +0200
Subject: [PATCH 01/46] Bump MonoTouch.Dialog and Touch.Unit.

New commits in migueldeicaza/MonoTouch.Dialog:

* migueldeicaza/MonoTouch.Dialog@f500f9a Bump to .NET 8.

Diff: https://github.com/migueldeicaza/MonoTouch.Dialog/compare/94359c74ef481ce7b5daa28b890f35a6e77d94c8..f500f9a48dbf856c693b255078e1507cf1e8edde

New commits in spouliot/Touch.Unit:

* spouliot/Touch.Unit@5739ade Bump to .NET 8.

Diff: https://github.com/spouliot/Touch.Unit/compare/8d80e1f10414ec85afa14c8c45a05334eb37c6dd..5739adefc261b7bfeb70ff718c7b2d97bdfa42ee
---
 .gitmodules               | 4 ++--
 external/MonoTouch.Dialog | 2 +-
 external/Touch.Unit       | 2 +-
 3 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/.gitmodules b/.gitmodules
index eefd1092b6d4..5a50d28b9224 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -13,7 +13,7 @@
 [submodule "external/Touch.Unit"]
     path = external/Touch.Unit
     url = ../../spouliot/Touch.Unit.git
-    branch = main
+    branch = net8.0
 [submodule "external/Xamarin.MacDev"]
     path = external/Xamarin.MacDev
     url = ../../xamarin/Xamarin.MacDev
@@ -21,7 +21,7 @@
 [submodule "external/MonoTouch.Dialog"]
     path = external/MonoTouch.Dialog
     url = ../../migueldeicaza/MonoTouch.Dialog
-    branch = dotnet
+    branch = net8.0
 [submodule "api-tools"]
     path = external/api-tools
     url = ../../rolfbjarne/api-tools
diff --git a/external/MonoTouch.Dialog b/external/MonoTouch.Dialog
index 94359c74ef48..f500f9a48dbf 160000
--- a/external/MonoTouch.Dialog
+++ b/external/MonoTouch.Dialog
@@ -1 +1 @@
-Subproject commit 94359c74ef481ce7b5daa28b890f35a6e77d94c8
+Subproject commit f500f9a48dbf856c693b255078e1507cf1e8edde
diff --git a/external/Touch.Unit b/external/Touch.Unit
index 8d80e1f10414..5739adefc261 160000
--- a/external/Touch.Unit
+++ b/external/Touch.Unit
@@ -1 +1 @@
-Subproject commit 8d80e1f10414ec85afa14c8c45a05334eb37c6dd
+Subproject commit 5739adefc261b7bfeb70ff718c7b2d97bdfa42ee

From f964b5a15798ff9823b8c463aac5e450812e445b Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:49 +0200
Subject: [PATCH 02/46] [runtime] Create a version of our runtime that can be
 used with NativeAOT.

This contributes towards https://github.com/xamarin/xamarin-macios/issues/17339.
---
 Make.config                        |  4 +++
 mk/rules.mk                        |  2 ++
 runtime/Makefile                   | 19 +++++++++++++-
 runtime/coreclr-bridge.m           | 13 ++++++---
 runtime/nativeaot-bridge.m         | 42 ++++++++++++++++++++++++++++++
 runtime/runtime.m                  |  2 ++
 runtime/xamarin/nativeaot-bridge.h | 26 ++++++++++++++++++
 src/ObjCRuntime/Runtime.cs         | 14 ++++++++++
 8 files changed, 118 insertions(+), 4 deletions(-)
 create mode 100644 runtime/nativeaot-bridge.m
 create mode 100644 runtime/xamarin/nativeaot-bridge.h

diff --git a/Make.config b/Make.config
index 4e5873937c81..453328678981 100644
--- a/Make.config
+++ b/Make.config
@@ -682,6 +682,7 @@ DOTNET_PLATFORMS=
 ifdef INCLUDE_IOS
 DOTNET_PLATFORMS+=iOS
 DOTNET_IOS_BITNESSES+=64
+DOTNET_NATIVEAOT_PLATFORMS+=iOS
 
 # 32-bit architectures
 ifdef IOS_SUPPORTS_32BIT_ARCHITECTURES
@@ -705,6 +706,7 @@ endif # INCLUDE_IOS
 ifdef INCLUDE_TVOS
 DOTNET_PLATFORMS+=tvOS
 DOTNET_TVOS_BITNESSES+=64
+DOTNET_NATIVEAOT_PLATFORMS+=tvOS
 ifdef INCLUDE_DEVICE
 DOTNET_TVOS_RUNTIME_IDENTIFIERS=tvos-arm64 tvossimulator-x64 tvossimulator-arm64
 else
@@ -728,6 +730,7 @@ endif
 ifdef INCLUDE_MACCATALYST
 DOTNET_PLATFORMS+=MacCatalyst
 DOTNET_MACCATALYST_BITNESSES+=64
+DOTNET_NATIVEAOT_PLATFORMS+=MacCatalyst
 DOTNET_MACCATALYST_RUNTIME_IDENTIFIERS=maccatalyst-x64 maccatalyst-arm64
 DOTNET_MACCATALYST_RUNTIME_IDENTIFIERS_64+=$(DOTNET_MACCATALYST_RUNTIME_IDENTIFIERS)
 endif
@@ -736,6 +739,7 @@ ifdef INCLUDE_MAC
 DOTNET_PLATFORMS+=macOS
 DOTNET_CORECLR_PLATFORMS+=macOS
 DOTNET_MACOS_BITNESSES+=64
+DOTNET_NATIVEAOT_PLATFORMS+=macOS
 DOTNET_MACOS_RUNTIME_IDENTIFIERS=osx-x64 osx-arm64
 DOTNET_MACOS_RUNTIME_IDENTIFIERS_64=$(DOTNET_MACOS_RUNTIME_IDENTIFIERS)
 endif
diff --git a/mk/rules.mk b/mk/rules.mk
index 2d309e3389fa..6910cdda651e 100644
--- a/mk/rules.mk
+++ b/mk/rules.mk
@@ -297,6 +297,8 @@ $(eval $(call NativeCompilationTemplate,-dotnet,-O2 -DDOTNET))
 $(eval $(call NativeCompilationTemplate,-dotnet-debug,-DDEBUG -DDOTNET))
 $(eval $(call NativeCompilationTemplate,-dotnet-coreclr,-O2 -DCORECLR_RUNTIME -DDOTNET))
 $(eval $(call NativeCompilationTemplate,-dotnet-coreclr-debug,-DDEBUG -DCORECLR_RUNTIME -DDOTNET))
+$(eval $(call NativeCompilationTemplate,-dotnet-nativeaot,-O2 -DCORECLR_RUNTIME -DDOTNET -DNATIVEAOT))
+$(eval $(call NativeCompilationTemplate,-dotnet-nativeaot-debug,-DDEBUG -DCORECLR_RUNTIME -DDOTNET -DNATIVEAOT))
 
 .libs/iphoneos .libs/iphonesimulator .libs/watchos .libs/watchsimulator .libs/tvos .libs/tvsimulator .libs/maccatalyst .libs/mac:
 	$(Q) mkdir -p $@
diff --git a/runtime/Makefile b/runtime/Makefile
index 2db40b5d7b0f..ea15e991e25c 100644
--- a/runtime/Makefile
+++ b/runtime/Makefile
@@ -22,7 +22,7 @@ SHIPPED_HEADERS +=         \
 	xamarin/monovm-bridge.h \
 	xamarin/coreclr-bridge.h \
 
-SHARED_SOURCES += mono-runtime.m bindings.m bindings-generated.m shared.m runtime.m trampolines.m trampolines-invoke.m xamarin-support.m nsstring-localization.m trampolines-varargs.m monovm-bridge.m coreclr-bridge.m
+SHARED_SOURCES += mono-runtime.m bindings.m bindings-generated.m shared.m runtime.m trampolines.m trampolines-invoke.m xamarin-support.m nsstring-localization.m trampolines-varargs.m monovm-bridge.m coreclr-bridge.m nativeaot-bridge.m
 SHARED_I386_SOURCES += trampolines-i386.m trampolines-i386-asm.s trampolines-i386-objc_msgSend.s trampolines-i386-objc_msgSendSuper.s trampolines-i386-objc_msgSend_stret.s trampolines-i386-objc_msgSendSuper_stret.s
 SHARED_X86_64_SOURCES += trampolines-x86_64.m trampolines-x86_64-asm.s trampolines-x86_64-objc_msgSend.s trampolines-x86_64-objc_msgSendSuper.s trampolines-x86_64-objc_msgSend_stret.s trampolines-x86_64-objc_msgSendSuper_stret.s
 SHARED_ARM64_SOURCES += trampolines-arm64.m trampolines-arm64-asm.s trampolines-arm64-objc_msgSend.s trampolines-arm64-objc_msgSendSuper.s
@@ -454,6 +454,11 @@ MAC_LIBS =                   \
 #    This is used when using the CoreCLR runtime instead of Mono.
 #    CORECLR_RUNTIME is defined for these versions of libxamarin.
 #
+# libxamarin-nativeaot.a:
+#    This is used when using NativeAOT.
+#    CORECLR_RUNTIME is defined for these versions of libxamarin (because the nativeaot bridge shares *a lot* of code with the coreclr bridge)
+#    NATIVEAOT is defined for these versions of libxamarin
+#
 
 ifdef INCLUDE_XAMARIN_LEGACY
 all-local:: $(TARGETS)
@@ -614,6 +619,15 @@ endef
 
 $(foreach platform,$(DOTNET_CORECLR_PLATFORMS),$(foreach rid,$(DOTNET_$(platform)_RUNTIME_IDENTIFIERS),$(eval $(call DotNetCoreClrLibTemplate,$(platform),$(rid)))))
 
+define DotNetNativeAotLibTemplate
+DOTNET_TARGETS += \
+	$(DOTNET_DESTDIR)/Microsoft.$(1).Runtime.$(2)/runtimes/$(2)/native/libxamarin-dotnet-nativeaot.a \
+	$(DOTNET_DESTDIR)/Microsoft.$(1).Runtime.$(2)/runtimes/$(2)/native/libxamarin-dotnet-nativeaot-debug.a \
+
+endef
+
+$(foreach platform,$(DOTNET_NATIVEAOT_PLATFORMS),$(foreach rid,$(DOTNET_$(platform)_RUNTIME_IDENTIFIERS),$(eval $(call DotNetNativeAotLibTemplate,$(platform),$(rid)))))
+
 # a few lookup tables, because the data we have is not always in the format we need it
 DOTNET_iphonesimulator_DYLIB_FLAGS=-lmonosgen-2.0 -licudata -licui18n -licuuc -framework UIKit
 DOTNET_iphoneos_DYLIB_FLAGS=-lmonosgen-2.0 -licudata -licui18n -licuuc -framework UIKit
@@ -704,6 +718,8 @@ $(foreach platform,$(DOTNET_PLATFORMS),$(foreach rid,$(DOTNET_$(platform)_RUNTIM
 $(foreach platform,$(DOTNET_PLATFORMS),$(foreach rid,$(DOTNET_$(platform)_RUNTIME_IDENTIFIERS),$(foreach arch,$(DOTNET_$(rid)_ARCHITECTURES),$(eval $(call DotNetLibXamarinTemplate,$(DOTNET_$(rid)_SDK_PLATFORM),$(rid),$(arch),_DEBUG,-dotnet-debug,,.mono)))))
 $(foreach platform,$(DOTNET_PLATFORMS),$(foreach rid,$(DOTNET_$(platform)_RUNTIME_IDENTIFIERS),$(foreach arch,$(DOTNET_$(rid)_ARCHITECTURES),$(eval $(call DotNetLibXamarinTemplate,$(DOTNET_$(rid)_SDK_PLATFORM),$(rid),$(arch),_CORECLR,-dotnet-coreclr,_CORECLR)))))
 $(foreach platform,$(DOTNET_PLATFORMS),$(foreach rid,$(DOTNET_$(platform)_RUNTIME_IDENTIFIERS),$(foreach arch,$(DOTNET_$(rid)_ARCHITECTURES),$(eval $(call DotNetLibXamarinTemplate,$(DOTNET_$(rid)_SDK_PLATFORM),$(rid),$(arch),_CORECLR_DEBUG,-dotnet-coreclr-debug,_CORECLR)))))
+$(foreach platform,$(DOTNET_PLATFORMS),$(foreach rid,$(DOTNET_$(platform)_RUNTIME_IDENTIFIERS),$(foreach arch,$(DOTNET_$(rid)_ARCHITECTURES),$(eval $(call DotNetLibXamarinTemplate,$(DOTNET_$(rid)_SDK_PLATFORM),$(rid),$(arch),_NATIVEAOT,-dotnet-nativeaot,_NATIVEAOT,.mono)))))
+$(foreach platform,$(DOTNET_PLATFORMS),$(foreach rid,$(DOTNET_$(platform)_RUNTIME_IDENTIFIERS),$(foreach arch,$(DOTNET_$(rid)_ARCHITECTURES),$(eval $(call DotNetLibXamarinTemplate,$(DOTNET_$(rid)_SDK_PLATFORM),$(rid),$(arch),_NATIVEAOT_DEBUG,-dotnet-nativeaot-debug,_NATIVEAOT,.mono)))))
 
 #
 # DotNetLibExtensionTemplate builds lib[tv]extension.a
@@ -731,6 +747,7 @@ endef
 
 $(foreach platform,$(DOTNET_PLATFORMS),$(foreach rid,$(DOTNET_$(platform)_RUNTIME_IDENTIFIERS),$(foreach arch,$(DOTNET_$(rid)_ARCHITECTURES),$(eval $(call DotNetLibExtensionTemplate,$(DOTNET_$(rid)_SDK_PLATFORM),$(rid),$(arch),,-dotnet,,)))))
 $(foreach platform,$(DOTNET_PLATFORMS),$(foreach rid,$(DOTNET_$(platform)_RUNTIME_IDENTIFIERS),$(foreach arch,$(DOTNET_$(rid)_ARCHITECTURES),$(eval $(call DotNetLibExtensionTemplate,$(DOTNET_$(rid)_SDK_PLATFORM),$(rid),$(arch),_CORECLR,-dotnet-coreclr,_CORECLR)))))
+$(foreach platform,$(DOTNET_PLATFORMS),$(foreach rid,$(DOTNET_$(platform)_RUNTIME_IDENTIFIERS),$(foreach arch,$(DOTNET_$(rid)_ARCHITECTURES),$(eval $(call DotNetLibExtensionTemplate,$(DOTNET_$(rid)_SDK_PLATFORM),$(rid),$(arch),_NATOVEAOT,-dotnet-nativeaot,_NATOVEAOT)))))
 
 dotnet: $(DOTNET_TARGETS)
 
diff --git a/runtime/coreclr-bridge.m b/runtime/coreclr-bridge.m
index 287c3f963534..ba7ec923e6fc 100644
--- a/runtime/coreclr-bridge.m
+++ b/runtime/coreclr-bridge.m
@@ -11,6 +11,7 @@
 #include <sys/stat.h>
 #include <inttypes.h>
 #include <pthread.h>
+#include <sys/mman.h>
 
 #include "product.h"
 #include "runtime-internal.h"
@@ -477,6 +478,7 @@
 		munmap ((void *) buf, fd_len);
 }
 
+#if !defined (NATIVEAOT)
 bool
 xamarin_bridge_vm_initialize (int propertyCount, const char **propertyKeys, const char **propertyValues)
 {
@@ -510,6 +512,7 @@
 
 	return rv == 0;
 }
+#endif // !defined (NATIVEAOT)
 
 void
 xamarin_install_nsautoreleasepool_hooks ()
@@ -537,18 +540,20 @@
 	xamarin_assertion_message ("%s threw an exception: %p = %s", method, gchandle, [xamarin_print_all_exceptions (gchandle) UTF8String]);
 }
 
-typedef void (*xamarin_runtime_initialize_decl)(struct InitializationOptions* options);
+#if !defined (NATIVEAOT)
+typedef void (*xamarin_runtime_initialize_decl)(struct InitializationOptions* options, GCHandle* exception_gchandle);
 void
 xamarin_bridge_call_runtime_initialize (struct InitializationOptions* options, GCHandle* exception_gchandle)
 {
 	void *del = NULL;
-	int rv = coreclr_create_delegate (coreclr_handle, coreclr_domainId, PRODUCT ", Version=0.0.0.0", "ObjCRuntime.Runtime", "Initialize", &del);
+	int rv = coreclr_create_delegate (coreclr_handle, coreclr_domainId, PRODUCT ", Version=0.0.0.0", "ObjCRuntime.Runtime", "SafeInitialize", &del);
 	if (rv != 0)
 		xamarin_assertion_message ("xamarin_bridge_call_runtime_initialize: failed to create delegate: %i\n", rv);
 
 	xamarin_runtime_initialize_decl runtime_initialize = (xamarin_runtime_initialize_decl) del;
-	runtime_initialize (options);
+	runtime_initialize (options, exception_gchandle);
 }
+#endif // !defined (NATIVEAOT)
 
 void
 xamarin_bridge_register_product_assembly (GCHandle* exception_gchandle)
@@ -737,6 +742,7 @@
 	return rv;
 }
 
+#if !defined (NATIVEAOT)
 int
 mono_jit_exec (MonoDomain * domain, MonoAssembly * assembly, int argc, const char** argv)
 {
@@ -766,6 +772,7 @@
 
 	return (int) exitCode;
 }
+#endif // !defined (NATIVEAOT)
 
 MonoGHashTable *
 mono_g_hash_table_new_type (GHashFunc hash_func, GEqualFunc key_equal_func, MonoGHashGCType type)
diff --git a/runtime/nativeaot-bridge.m b/runtime/nativeaot-bridge.m
new file mode 100644
index 000000000000..74587bb31399
--- /dev/null
+++ b/runtime/nativeaot-bridge.m
@@ -0,0 +1,42 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+*  Authors: Rolf Bjarne Kvinge
+*
+*  Copyright (C) 2023 Microsoft Corp.
+*
+*/
+
+#if defined (NATIVEAOT)
+
+#include <sys/stat.h>
+#include <inttypes.h>
+#include <pthread.h>
+#include <sys/mman.h>
+#include <dlfcn.h>
+
+#include "product.h"
+#include "runtime-internal.h"
+#include "slinked-list.h"
+#include "xamarin/xamarin.h"
+#include "xamarin/coreclr-bridge.h"
+#include "xamarin/nativeaot-bridge.h"
+
+void
+xamarin_bridge_call_runtime_initialize (struct InitializationOptions* options, GCHandle* exception_gchandle)
+{
+	xamarin_objcruntime_runtime_nativeaotinitialize (options, exception_gchandle);
+}
+
+bool
+xamarin_bridge_vm_initialize (int propertyCount, const char **propertyKeys, const char **propertyValues)
+{
+	return true;
+}
+
+int
+mono_jit_exec (MonoDomain * domain, MonoAssembly * assembly, int argc, const char** argv)
+{
+	return __managed__Main (argc, argv);
+}
+
+#endif // NATIVEAOT
diff --git a/runtime/runtime.m b/runtime/runtime.m
index b38ff6661f8a..5b08ef437011 100644
--- a/runtime/runtime.m
+++ b/runtime/runtime.m
@@ -1304,12 +1304,14 @@ -(void) xamarinSetFlags: (enum XamarinGCHandleFlags) flags;
 #endif
 
 #if defined (CORECLR_RUNTIME)
+#if !defined(__arm__) // the dynamic trampolines haven't been implemented in 32-bit ARM assembly.
 	options.xamarin_objc_msgsend = (void *) xamarin_dyn_objc_msgSend;
 	options.xamarin_objc_msgsend_super = (void *) xamarin_dyn_objc_msgSendSuper;
 #if !defined(__aarch64__)
 	options.xamarin_objc_msgsend_stret = (void *) xamarin_dyn_objc_msgSend_stret;
 	options.xamarin_objc_msgsend_super_stret = (void *) xamarin_dyn_objc_msgSendSuper_stret;
 #endif // !defined(__aarch64__)
+#endif // !defined(__arm__)
 	options.unhandled_exception_handler = (void *) &xamarin_coreclr_unhandled_exception_handler;
 	options.reference_tracking_begin_end_callback = (void *) &xamarin_coreclr_reference_tracking_begin_end_callback;
 	options.reference_tracking_is_referenced_callback = (void *) &xamarin_coreclr_reference_tracking_is_referenced_callback;
diff --git a/runtime/xamarin/nativeaot-bridge.h b/runtime/xamarin/nativeaot-bridge.h
new file mode 100644
index 000000000000..6de5ad88117b
--- /dev/null
+++ b/runtime/xamarin/nativeaot-bridge.h
@@ -0,0 +1,26 @@
+
+/* Support for using NativeAOT */
+
+#if defined (NATIVEAOT)
+
+#ifndef __NATIVEAOT_BRIDGE__
+#define __NATIVEAOT_BRIDGE__
+
+#include <stdatomic.h>
+
+#include "runtime.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void xamarin_objcruntime_runtime_nativeaotinitialize (struct InitializationOptions* options, GCHandle* exception_gchandle);
+int __managed__Main (int argc, const char** argv);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* __NATIVEAOT_BRIDGE__ */
+
+#endif // NATIVEAOT
diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs
index f411a851b93e..7d63d96aba60 100644
--- a/src/ObjCRuntime/Runtime.cs
+++ b/src/ObjCRuntime/Runtime.cs
@@ -249,6 +249,20 @@ internal static bool Initialized {
 		static extern int _NSGetExecutablePath (byte[] buf, ref int bufsize);
 #endif
 
+#if NET
+		[Preserve] // called from native - nativeaot-bridge.m and coreclr-bridge.m.
+		[UnmanagedCallersOnly (EntryPoint = "xamarin_objcruntime_runtime_nativeaotinitialize")]
+		unsafe static void SafeInitialize (InitializationOptions* options, IntPtr* exception_gchandle)
+		{
+			*exception_gchandle = IntPtr.Zero;
+			try {
+				Initialize (options);
+			} catch (Exception e) {
+				*exception_gchandle = AllocGCHandle (e);
+			}
+		}
+#endif
+
 		[Preserve] // called from native - runtime.m.
 		[BindingImpl (BindingImplOptions.Optimizable)] // To inline the Runtime.DynamicRegistrationSupported code if possible.
 		unsafe static void Initialize (InitializationOptions* options)

From a76690198fc4a847a84c5d465e492b905314e986 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:49 +0200
Subject: [PATCH 03/46] [dotnet] Choose the correct runtime library depending
 on which runtime we're using.

---
 .../Xamarin.Shared.Sdk.DefaultItems.targets   |  3 ++-
 dotnet/targets/Xamarin.Shared.Sdk.targets     | 20 +++++++++++--------
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets b/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets
index d100091037f5..0b41c3a8fdf3 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets
@@ -11,8 +11,9 @@
     <EnableDefaultmacOSItems Condition=" '$(_PlatformName)' == 'macOS' And '$(EnableDefaultmacOSItems)' == '' ">$(EnableDefaultItems)</EnableDefaultmacOSItems>
     <EnableDefaultMacCatalystItems Condition=" '$(_PlatformName)' == 'MacCatalyst' And '$(EnableDefaultMacCatalystItems)' == '' ">$(EnableDefaultItems)</EnableDefaultMacCatalystItems>
 
-    <UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' And '$(_PlatformName)' != 'macOS'">true</UseMonoRuntime>
     <UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' And '$(_PlatformName)' == 'macOS'">false</UseMonoRuntime>
+    <UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' And '$(PublishAot)' == 'true'">false</UseMonoRuntime>
+    <UseMonoRuntime Condition=" '$(UseMonoRuntime)' == ''">true</UseMonoRuntime>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index 496a66b7537b..c75585b22fff 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -456,9 +456,6 @@
 			<_LinkerCacheDirectory>$([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)linker-cache'))</_LinkerCacheDirectory>
 			<_LinkerCacheDirectory Condition="'$(BuildSessionId)' != ''">$(IntermediateOutputPath)linker-cache</_LinkerCacheDirectory>
 
-			<_XamarinRuntime Condition="'$(UseMonoRuntime)' == 'true'">MonoVM</_XamarinRuntime>
-			<_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true'">CoreCLR</_XamarinRuntime>
-
 			<!-- TrimMode specifies what the linker will do with framework assemblies -->
 			<TrimMode Condition="'$(_LinkMode)' == 'TrimMode'">$(TrimMode)</TrimMode>
 			<TrimMode Condition="'$(_LinkMode)' == 'None'">copy</TrimMode>
@@ -853,7 +850,11 @@
 
 	<Target Name="_ComputeFrameworkVariables" DependsOnTargets="ResolveRuntimePackAssets;ResolveFrameworkReferences">
 		<PropertyGroup>
-			<_PackageIdInfix Condition="'$(UseMonoRuntime)' == 'true'">Mono.</_PackageIdInfix>
+			<_XamarinRuntime Condition="'$(UseMonoRuntime)' == 'true'">MonoVM</_XamarinRuntime>
+			<_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(PublishAot)' != 'true'">CoreCLR</_XamarinRuntime>
+			<_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(PublishAot)' == 'true'">NativeAOT</_XamarinRuntime>
+
+			<_PackageIdInfix Condition="'$(_XamarinRuntime)' == 'MonoVM'">Mono.</_PackageIdInfix>
 
 			<_MonoNugetPackageId>Microsoft.NETCore.App.Runtime.$(_PackageIdInfix)$(RuntimeIdentifier)</_MonoNugetPackageId>
 			<_XamarinNugetPackageId>Microsoft.$(_PlatformName).Runtime.$(RuntimeIdentifier)</_XamarinNugetPackageId>
@@ -871,8 +872,9 @@
 			<_XamarinRefAssemblyDirectory>$(_XamarinRefPackageDirectory)/ref/net8.0/</_XamarinRefAssemblyDirectory>
 			<_XamarinRefAssemblyPath>$(_XamarinRefAssemblyDirectory)$(_PlatformAssemblyName).dll</_XamarinRefAssemblyPath>
 
-			<_LibPartialStaticRegistrar Condition="'$(UseMonoRuntime)' == 'true'">$(_XamarinNativeLibraryDirectory)/Microsoft.$(_PlatformName).registrar.a</_LibPartialStaticRegistrar>
-			<_LibPartialStaticRegistrar Condition="'$(UseMonoRuntime)' != 'true'">$(_XamarinNativeLibraryDirectory)/Microsoft.$(_PlatformName).registrar.coreclr.a</_LibPartialStaticRegistrar>
+			<_LibPartialStaticRegistrar Condition="'$(_XamarinRuntime)' == 'MonoVM'">$(_XamarinNativeLibraryDirectory)/Microsoft.$(_PlatformName).registrar.a</_LibPartialStaticRegistrar>
+			<_LibPartialStaticRegistrar Condition="'$(_XamarinRuntime)' == 'CoreCLR'">$(_XamarinNativeLibraryDirectory)/Microsoft.$(_PlatformName).registrar.coreclr.a</_LibPartialStaticRegistrar>
+			<_LibPartialStaticRegistrar Condition="'$(_XamarinRuntime)' == 'NativeAOT'">$(_XamarinNativeLibraryDirectory)/Microsoft.$(_PlatformName).registrar.nativeaot.a</_LibPartialStaticRegistrar>
 
 			<_MonoRuntimePackPath>%(_MonoFrameworkReference.RuntimePackPath)/runtimes/$(RuntimeIdentifier)/</_MonoRuntimePackPath>
 		</PropertyGroup>
@@ -952,7 +954,9 @@
 			<_LibXamarinLinkMode Condition="'$(_LibXamarinLinkMode)' == ''">static</_LibXamarinLinkMode>
 			<_LibXamarinExtension Condition="'$(_LibXamarinLinkMode)' == 'dylib'">dylib</_LibXamarinExtension>
 			<_LibXamarinExtension Condition="'$(_LibXamarinLinkMode)' == 'static'">a</_LibXamarinExtension>
-			<_LibXamarinRuntime Condition="'$(UseMonoRuntime)' != 'true'">-coreclr</_LibXamarinRuntime>
+			<_LibXamarinRuntime Condition="'$(_XamarinRuntime)' == 'MonoVM'"></_LibXamarinRuntime>
+			<_LibXamarinRuntime Condition="'$(_XamarinRuntime)' == 'CoreCLR'">-coreclr</_LibXamarinRuntime>
+			<_LibXamarinRuntime Condition="'$(_XamarinRuntime)' == 'NativeAOT'">-nativeaot</_LibXamarinRuntime>
 			<_LibXamarinDebug Condition="'$(_BundlerDebug)' == 'true'">-debug</_LibXamarinDebug>
 			<_LibXamarinName Condition="'$(_LibXamarinName)' == ''">libxamarin-dotnet$(_LibXamarinRuntime)$(_LibXamarinDebug).$(_LibXamarinExtension)</_LibXamarinName>
 
@@ -1528,7 +1532,7 @@
 			<!-- Ref: https://github.com/xamarin/xamarin-macios/issues/11432 -->
 			<_CreateDumpExecutable
 				Include="@(ResolvedFileToPublish)"
-				Condition=" '$(UseMonoRuntime)' == 'false' And
+				Condition=" '$(_XamarinRuntime)' == 'CoreCLR' And
 				            '%(ResolvedFileToPublish.Filename)' == 'createdump' And
 				            '%(ResolvedFileToPublish.Extension)' == '' And
 				            '%(ResolvedFileToPublish.AssetType)' == 'native' And

From 7f15d8625e43e969be3d841c008d5713f94720ed Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:50 +0200
Subject: [PATCH 04/46] [xharness] Add a NativeAOT variation of monotouch-test.

---
 tests/xharness/Jenkins/TestData.cs              |  1 +
 tests/xharness/Jenkins/TestVariationsFactory.cs | 15 ++++++++++++++-
 2 files changed, 15 insertions(+), 1 deletion(-)

diff --git a/tests/xharness/Jenkins/TestData.cs b/tests/xharness/Jenkins/TestData.cs
index 0fcfe71e46da..62e33f6f21de 100644
--- a/tests/xharness/Jenkins/TestData.cs
+++ b/tests/xharness/Jenkins/TestData.cs
@@ -23,5 +23,6 @@ class TestData {
 		public string XamMacArch;
 		public string RuntimeIdentifier;
 		public string Registrar;
+		public bool PublishAot; // NativeAOT
 	}
 }
diff --git a/tests/xharness/Jenkins/TestVariationsFactory.cs b/tests/xharness/Jenkins/TestVariationsFactory.cs
index 3af7db146ba6..47b6d61a9606 100644
--- a/tests/xharness/Jenkins/TestVariationsFactory.cs
+++ b/tests/xharness/Jenkins/TestVariationsFactory.cs
@@ -101,6 +101,8 @@ IEnumerable<TestData> GetTestData (RunTestTask test)
 						yield return new TestData { Variation = "Debug (managed static registrar)", Registrar = "managed-static", Debug = true, Profiling = false, Ignored = ignore };
 						yield return new TestData { Variation = "Release (managed static registrar, all optimizations)", BundlerArguments = "--optimize:all", Registrar = "managed-static", Debug = false, Profiling = false, LinkMode = "Full", Defines = "OPTIMIZEALL", Ignored = ignore };
 					}
+					if (test.TestProject.IsDotNetProject)
+						yield return new TestData { Variation = "Release (NativeAOT)", Debug = false, PublishAot = true, Ignored = ignore, Defines = "NATIVEAOT", LinkMode = "Full" };
 					break;
 				case string name when name.StartsWith ("mscorlib", StringComparison.Ordinal):
 					if (supports_debug)
@@ -127,11 +129,14 @@ IEnumerable<TestData> GetTestData (RunTestTask test)
 					yield return new TestData { Variation = "Release (all optimizations)", BundlerArguments = "--optimize:all", Registrar = "static", Debug = false, Profiling = false, LinkMode = "Full", Defines = "OPTIMIZEALL", Ignored = ignore };
 					yield return new TestData { Variation = "Debug (all optimizations)", BundlerArguments = "--optimize:all,-remove-uithread-checks", Registrar = "static", Debug = true, Profiling = false, LinkMode = "Full", Defines = "OPTIMIZEALL", Ignored = ignore ?? !jenkins.TestSelection.IsEnabled (TestLabel.All) };
 
-					if (test.TestProject.IsDotNetProject && mac_supports_arm64)
+					if (test.TestProject.IsDotNetProject && mac_supports_arm64) {
 						yield return new TestData { Variation = "Debug (ARM64)", Debug = true, Profiling = false, Ignored = !mac_supports_arm64 ? true : ignore, RuntimeIdentifier = arm64_sim_runtime_identifier, };
+						yield return new TestData { Variation = "Release (NativeAOT, ARM64)", Debug = false, PublishAot = true, Ignored = ignore, Defines = "NATIVEAOT", RuntimeIdentifier = arm64_sim_runtime_identifier, LinkMode = "Full" };
+					}
 					if (test.TestProject.IsDotNetProject) {
 						yield return new TestData { Variation = "Debug (managed static registrar)", Registrar = "managed-static", Debug = true, Profiling = false, Ignored = ignore };
 						yield return new TestData { Variation = "Release (managed static registrar, all optimizations)", BundlerArguments = "--optimize:all", Registrar = "managed-static", Debug = false, Profiling = false, LinkMode = "Full", Defines = "OPTIMIZEALL", Ignored = ignore };
+						yield return new TestData { Variation = "Release (NativeAOT)", Debug = false, PublishAot = true, Ignored = ignore, Defines = "NATIVEAOT", LinkMode = "Full" };
 					}
 					break;
 				case "introspection":
@@ -157,10 +162,15 @@ IEnumerable<TestData> GetTestData (RunTestTask test)
 						if (test.Platform != TestPlatform.MacCatalyst) {
 							yield return new TestData { Variation = "Debug (static registrar)", Registrar = "static", Debug = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.Mac), };
 							yield return new TestData { Variation = "Debug (static registrar, ARM64)", Registrar = "static", Debug = true, Profiling = false, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.Mac) || !mac_supports_arm64, RuntimeIdentifier = arm64_runtime_identifier, };
+							yield return new TestData { Variation = "Release (NativeAOT)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.Mac), Defines = "NATIVEAOT", LinkMode = "Full" };
+							yield return new TestData { Variation = "Release (NativeAOT, ARM64)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.Mac) || !mac_supports_arm64, Defines = "NATIVEAOT", RuntimeIdentifier = arm64_runtime_identifier, LinkMode = "Full" };
 						}
 						if (test.Platform == TestPlatform.MacCatalyst) {
 							yield return new TestData { Variation = "Release (ARM64, LLVM)", Debug = false, UseLlvm = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst) || !mac_supports_arm64, RuntimeIdentifier = arm64_runtime_identifier };
 							yield return new TestData { Variation = "Release", Debug = false, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst) };
+							yield return new TestData { Variation = "Release (NativeAOT)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst), Defines = "NATIVEAOT", LinkMode = "Full" };
+							yield return new TestData { Variation = "Release (NativeAOT, ARM64)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst) || !mac_supports_arm64, Defines = "NATIVEAOT", RuntimeIdentifier = arm64_runtime_identifier, LinkMode = "Full" };
+							yield return new TestData { Variation = "Release (NativeAOT, x64)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst), Defines = "NATIVEAOT", LinkMode = "Full", RuntimeIdentifier = "maccatalyst-x64" };
 						}
 						if (test.Platform == TestPlatform.Mac) {
 							yield return new TestData { Variation = "Release", Debug = false, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.Mac) };
@@ -220,6 +230,7 @@ public IEnumerable<T> CreateTestVariations<T> (IEnumerable<T> tests, Func<MSBuil
 					var runtime_identifer = test_data.RuntimeIdentifier;
 					var use_llvm = test_data.UseLlvm;
 					var registrar = test_data.Registrar;
+					var publishaot = test_data.PublishAot;
 
 					if (task.TestProject.IsDotNetProject)
 						variation += " [dotnet]";
@@ -285,6 +296,8 @@ public IEnumerable<T> CreateTestVariations<T> (IEnumerable<T> tests, Func<MSBuil
 							clone.Xml.SetProperty ("RuntimeIdentifier", runtime_identifer);
 						if (!string.IsNullOrEmpty (registrar))
 							clone.Xml.SetProperty ("Registrar", registrar);
+						if (publishaot)
+							clone.Xml.SetProperty ("PublishAot", "true");
 						clone.Xml.Save (clone.Path);
 					});
 

From d584840c1cc2cd7248246fa135476838b6edda07 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:50 +0200
Subject: [PATCH 05/46] [dotnet] Force the managed static registrar when using
 NativeAot.

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index c75585b22fff..e339ddbb4bb9 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -443,6 +443,11 @@
 		<!-- it's invariant or it's one of the ICU data files, not both -->
 		<Error Text="Can not set values for both InvariantGlobalization '$(InvariantGlobalization)' and _GlobalizationDataFile '$(_GlobalizationDataFile)'" Condition="'$(_GlobalizationDataFile)' != '' And '$(InvariantGlobalization)' == 'true'" />
 
+		<Error Text="The only valid registrar when using NativeAOT is 'managed-static' (current value: '$(Registrar)'). Please either delete the 'Registrar' property, or change it to be 'managed-static'." Condition="'$(PublishAot)' == 'true' And '$(Registrar)' != '' And '$(Registrar)' != 'managed-static'" />
+		<PropertyGroup Condition="'$(PublishAot)' == 'true'">
+			<Registrar Condition="'$(Registrar)' == ''">managed-static</Registrar>
+		</PropertyGroup>
+
 		<PropertyGroup>
 			<!-- Pass the custom options to our custom steps -->
 			<_CustomLinkerOptionsFile>$([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)custom-linker-options.txt'))</_CustomLinkerOptionsFile>

From 607cc785555ce88a0d8896f178b07a2c63fc1ecd Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:50 +0200
Subject: [PATCH 06/46] [dotnet] Use the correct package infix for NativeAOT

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 1 +
 1 file changed, 1 insertion(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index e339ddbb4bb9..fa84c015a7b5 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -860,6 +860,7 @@
 			<_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(PublishAot)' == 'true'">NativeAOT</_XamarinRuntime>
 
 			<_PackageIdInfix Condition="'$(_XamarinRuntime)' == 'MonoVM'">Mono.</_PackageIdInfix>
+			<_PackageIdInfix Condition="'$(_XamarinRuntime)' == 'NativeAOT'">NativeAOT.</_PackageIdInfix>
 
 			<_MonoNugetPackageId>Microsoft.NETCore.App.Runtime.$(_PackageIdInfix)$(RuntimeIdentifier)</_MonoNugetPackageId>
 			<_XamarinNugetPackageId>Microsoft.$(_PlatformName).Runtime.$(RuntimeIdentifier)</_XamarinNugetPackageId>

From ca6f2e4d2eda3aec3af205996f4719ba3266433a Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:50 +0200
Subject: [PATCH 07/46] [Foundation] Use the correct toggle ref implementation
 on !macOS since NativeAOT (aka CoreCLR) is a possibility now

---
 src/Foundation/NSObject2.cs | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/Foundation/NSObject2.cs b/src/Foundation/NSObject2.cs
index f88f1a0492c2..1f645d3044ba 100644
--- a/src/Foundation/NSObject2.cs
+++ b/src/Foundation/NSObject2.cs
@@ -305,6 +305,12 @@ static void RegisterToggleReference (NSObject obj, IntPtr handle, bool isCustomT
 		{
 #if NET && __MACOS__
 			Runtime.RegisterToggleReferenceCoreCLR (obj, handle, isCustomType);
+#elif NET
+			if (Runtime.IsCoreCLR) {
+				Runtime.RegisterToggleReferenceCoreCLR (obj, handle, isCustomType);
+			} else {
+				RegisterToggleRef (obj, handle, isCustomType);
+			}
 #else
 			RegisterToggleRef (obj, handle, isCustomType);
 #endif

From 94c96ec263b881a4edc9e14aa2631d7a3cc25f39 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:50 +0200
Subject: [PATCH 08/46] [dotnet] Don't run Mono's AOT compiler if we're using
 NativeAOT.

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index fa84c015a7b5..f5411a309f56 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -916,6 +916,9 @@
 		<PropertyGroup Condition="'$(_RunAotCompiler)' == ''">
 			<!-- Don't run the AOT compiler by default -->
 			<_RunAotCompiler>false</_RunAotCompiler>
+		</PropertyGroup>
+		<!-- We don't run Mono's AOT compiler if we're using NativeAOT -->
+		<PropertyGroup Condition="'$(PublishAot)' != 'true'" >
 			<!-- We need it for device builds for mobile platforms -->
 			<_RunAotCompiler Condition="'$(_SdkIsSimulator)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst'">true</_RunAotCompiler>
 			<!-- We need it if the interpreter is enabled, no matter where -->

From a3b466b89e56bb79166f5ed4e07e8771bbb45077 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:51 +0200
Subject: [PATCH 09/46] [tools] Don't allow keeping the dynamic registrar when
 using NativeAOT.

---
 tools/common/Optimizations.cs   | 11 ++++++++++-
 tools/mtouch/Errors.designer.cs |  9 +++++++++
 tools/mtouch/Errors.resx        |  4 ++++
 3 files changed, 23 insertions(+), 1 deletion(-)

diff --git a/tools/common/Optimizations.cs b/tools/common/Optimizations.cs
index ca6a7af6119d..16e40bdf4c4d 100644
--- a/tools/common/Optimizations.cs
+++ b/tools/common/Optimizations.cs
@@ -176,6 +176,13 @@ public void Initialize (Application app, out List<ProductException> messages)
 				if (!values [i].HasValue)
 					continue;
 
+				// The remove-dynamic-registrar optimization is required when using NativeAOT
+				if (app.XamarinRuntime == XamarinRuntime.NativeAOT && (Opt) i == Opt.RemoveDynamicRegistrar && values [i] == false) {
+					messages.Add (ErrorHelper.CreateWarning (2016, Errors.MX2016 /* Keeping the dynamic registrar (by passing '--optimize=-remove-dynamic-registrar') is not possible, because the dynamic registrar is not supported when using NativeAOT. Support for dynamic registration will still be removed. */));
+					values [i] = true;
+					continue;
+				}
+
 				// The remove-dynamic-registrar optimization is a bit if a special case on macOS:
 				// it only works in very specific circumstances, so we don't add it to valid_platforms.
 				// This means it won't be listed in --help, and it won't be enabled if all optimizations
@@ -275,7 +282,9 @@ public void Initialize (Application app, out List<ProductException> messages)
 				StaticBlockToDelegateLookup = true;
 
 			if (!RemoveDynamicRegistrar.HasValue) {
-				if (InlineDynamicRegistrationSupported != true) {
+				if (app.XamarinRuntime == XamarinRuntime.NativeAOT) {
+					RemoveDynamicRegistrar = true;
+				} else if (InlineDynamicRegistrationSupported != true) {
 					// Can't remove the dynamic registrar unless also inlining Runtime.DynamicRegistrationSupported
 					RemoveDynamicRegistrar = false;
 				} else if (StaticBlockToDelegateLookup != true) {
diff --git a/tools/mtouch/Errors.designer.cs b/tools/mtouch/Errors.designer.cs
index d770fa6bddc0..9c382bd3f3b8 100644
--- a/tools/mtouch/Errors.designer.cs
+++ b/tools/mtouch/Errors.designer.cs
@@ -3901,6 +3901,15 @@ public static string MX2005 {
             }
         }
         
+        /// <summary>
+        ///   Looks up a localized string similar to Keeping the dynamic registrar (by passing &apos;--optimize=-remove-dynamic-registrar&apos;) is not possible, because the dynamic registrar is not supported when using NativeAOT. Support for dynamic registration will still be removed..
+        /// </summary>
+        public static string MX2016 {
+            get {
+                return ResourceManager.GetString("MX2016", resourceCulture);
+            }
+        }
+        
         /// <summary>
         ///   Looks up a localized string similar to Could not process XML description: {0}
         ///		.
diff --git a/tools/mtouch/Errors.resx b/tools/mtouch/Errors.resx
index 8ebe9f75b579..76e6fc7c5b1b 100644
--- a/tools/mtouch/Errors.resx
+++ b/tools/mtouch/Errors.resx
@@ -1190,6 +1190,10 @@
 		</value>
 	</data>
 
+	<data name="MX2016" xml:space="preserve">
+		<value>Keeping the dynamic registrar (by passing '--optimize=-remove-dynamic-registrar') is not possible, because the dynamic registrar is not supported when using NativeAOT. Support for dynamic registration will still be removed.</value>
+	</data>
+
 	<data name="MX2017" xml:space="preserve">
 		<value>Could not process XML description: {0}
 		</value>

From ab8f928e4a67a48c94e8185a568d9d1975983425 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:51 +0200
Subject: [PATCH 10/46] [tools] Don't call mono_jit_set_aot_mode from main when
 using NativeAOT

---
 tools/common/Target.cs         | 2 ++
 tools/common/XamarinRuntime.cs | 1 +
 2 files changed, 3 insertions(+)

diff --git a/tools/common/Target.cs b/tools/common/Target.cs
index c952d93fed1f..d64332e032d3 100644
--- a/tools/common/Target.cs
+++ b/tools/common/Target.cs
@@ -797,6 +797,8 @@ void GenerateIOSMain (StringWriter sw, Abi abi)
 				} else {
 					sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_INTERP);");
 				}
+			} else if (app.XamarinRuntime == XamarinRuntime.NativeAOT) {
+				// don't call mono_jit_set_aot_mode
 			} else if (app.IsDeviceBuild) {
 				sw.WriteLine ("\tmono_jit_set_aot_mode (MONO_AOT_MODE_FULL);");
 			} else if (app.Platform == ApplePlatform.MacCatalyst && ((abi & Abi.ARM64) == Abi.ARM64)) {
diff --git a/tools/common/XamarinRuntime.cs b/tools/common/XamarinRuntime.cs
index af78ec9c2e78..ecab1567fe08 100644
--- a/tools/common/XamarinRuntime.cs
+++ b/tools/common/XamarinRuntime.cs
@@ -2,5 +2,6 @@ namespace Xamarin.Bundler {
 	public enum XamarinRuntime {
 		MonoVM,
 		CoreCLR,
+		NativeAOT,
 	}
 }

From 60e493649c1852536b7a121c15355b9fab319ff5 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:51 +0200
Subject: [PATCH 11/46] [tools] Don't generate calls to
 mono_aot_register_module in main when using NativeAOT

---
 tools/common/Target.cs | 26 ++++++++++++++------------
 1 file changed, 14 insertions(+), 12 deletions(-)

diff --git a/tools/common/Target.cs b/tools/common/Target.cs
index d64332e032d3..6b20a8a51abe 100644
--- a/tools/common/Target.cs
+++ b/tools/common/Target.cs
@@ -687,20 +687,22 @@ void GenerateIOSMain (StringWriter sw, Abi abi)
 			var assembly_location_count = 0;
 			var enable_llvm = (abi & Abi.LLVM) != 0;
 
-			register_assemblies.AppendLine ("\tGCHandle exception_gchandle = INVALID_GCHANDLE;");
-			foreach (var s in assemblies) {
-				if (!s.IsAOTCompiled)
-					continue;
+			if (app.XamarinRuntime != XamarinRuntime.NativeAOT) {
+				register_assemblies.AppendLine ("\tGCHandle exception_gchandle = INVALID_GCHANDLE;");
+				foreach (var s in assemblies) {
+					if (!s.IsAOTCompiled)
+						continue;
 
-				var info = s.AssemblyDefinition.Name.Name;
-				info = EncodeAotSymbol (info);
-				assembly_externs.Append ("extern void *mono_aot_module_").Append (info).AppendLine ("_info;");
-				assembly_aot_modules.Append ("\tmono_aot_register_module (mono_aot_module_").Append (info).AppendLine ("_info);");
+					var info = s.AssemblyDefinition.Name.Name;
+					info = EncodeAotSymbol (info);
+					assembly_externs.Append ("extern void *mono_aot_module_").Append (info).AppendLine ("_info;");
+					assembly_aot_modules.Append ("\tmono_aot_register_module (mono_aot_module_").Append (info).AppendLine ("_info);");
 
-				string sname = s.FileName;
-				if (assembly_name != sname && IsBoundAssembly (s)) {
-					register_assemblies.Append ("\txamarin_open_and_register (\"").Append (sname).Append ("\", &exception_gchandle);").AppendLine ();
-					register_assemblies.AppendLine ("\txamarin_process_managed_exception_gchandle (exception_gchandle);");
+					string sname = s.FileName;
+					if (assembly_name != sname && IsBoundAssembly (s)) {
+						register_assemblies.Append ("\txamarin_open_and_register (\"").Append (sname).Append ("\", &exception_gchandle);").AppendLine ();
+						register_assemblies.AppendLine ("\txamarin_process_managed_exception_gchandle (exception_gchandle);");
+					}
 				}
 			}
 

From 9b24c5dba63d434d39854be536ef47ef8f9e059e Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:51 +0200
Subject: [PATCH 12/46] [runtime] NativeAOT does not support dynamic
 registration

---
 runtime/monotouch-main.m | 2 ++
 runtime/runtime.m        | 9 +++++++++
 runtime/xamarin/main.h   | 8 ++++++++
 tools/common/Target.cs   | 3 ++-
 4 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/runtime/monotouch-main.m b/runtime/monotouch-main.m
index 4f9646b6bd47..c2f8cc0ed30f 100644
--- a/runtime/monotouch-main.m
+++ b/runtime/monotouch-main.m
@@ -454,12 +454,14 @@ - (void) memoryWarning: (NSNotification *) sender
 		xamarin_process_fatal_exception_gchandle (exception_gchandle, "An exception occurred while opening an assembly");
 	}
 
+#if SUPPORTS_DYNAMIC_REGISTRATION
 	if (xamarin_supports_dynamic_registration) {
 		MonoReflectionAssembly *rassembly = mono_assembly_get_object (mono_domain_get (), assembly);
 		xamarin_register_entry_assembly (rassembly, &exception_gchandle);
 		xamarin_mono_object_release (&rassembly);
 		xamarin_process_fatal_exception_gchandle (exception_gchandle, "An exception occurred while opening the entry assembly");
 	}
+#endif // SUPPORTS_DYNAMIC_REGISTRATION
 
 	DEBUG_LAUNCH_TIME_PRINT ("\tAssembly register time");
 
diff --git a/runtime/runtime.m b/runtime/runtime.m
index 5b08ef437011..c13f751c358b 100644
--- a/runtime/runtime.m
+++ b/runtime/runtime.m
@@ -82,7 +82,9 @@
 enum MarshalManagedExceptionMode xamarin_marshal_managed_exception_mode = MarshalManagedExceptionModeDefault;
 enum XamarinTriState xamarin_log_exceptions = XamarinTriStateNone;
 enum XamarinLaunchMode xamarin_launch_mode = XamarinLaunchModeApp;
+#if SUPPORTS_DYNAMIC_REGISTRATION
 bool xamarin_supports_dynamic_registration = true;
+#endif
 const char *xamarin_runtime_configuration_name = NULL;
 
 #if DOTNET
@@ -966,7 +968,9 @@ -(void) xamarinSetFlags: (enum XamarinGCHandleFlags) flags;
 xamarin_register_monoassembly (MonoAssembly *assembly, GCHandle *exception_gchandle)
 {
 	// COOP: this is a function executed only at startup, I believe the mode here doesn't matter.
+#if SUPPORTS_DYNAMIC_REGISTRATION
 	if (!xamarin_supports_dynamic_registration) {
+#endif
 #if defined (CORECLR_RUNTIME)
 		if (xamarin_log_level > 0) {
 			MonoReflectionAssembly *rassembly = mono_assembly_get_object (mono_domain_get (), assembly);
@@ -983,11 +987,16 @@ -(void) xamarinSetFlags: (enum XamarinGCHandleFlags) flags;
 		LOG (PRODUCT ": Skipping assembly registration for %s since it's not needed (dynamic registration is not supported)", mono_assembly_name_get_name (mono_assembly_get_name (assembly)));
 #endif
 		return true;
+#if SUPPORTS_DYNAMIC_REGISTRATION
 	}
+#endif
+
+#if SUPPORTS_DYNAMIC_REGISTRATION
 	MonoReflectionAssembly *rassembly = mono_assembly_get_object (mono_domain_get (), assembly);
 	xamarin_register_assembly (rassembly, exception_gchandle);
 	xamarin_mono_object_release (&rassembly);
 	return *exception_gchandle == INVALID_GCHANDLE;
+#endif // SUPPORTS_DYNAMIC_REGISTRATION
 }
 
 // Returns a retained MonoObject. Caller must release.
diff --git a/runtime/xamarin/main.h b/runtime/xamarin/main.h
index 201a09a24d82..a3b51d7745e5 100644
--- a/runtime/xamarin/main.h
+++ b/runtime/xamarin/main.h
@@ -99,6 +99,12 @@ enum XamarinTriState : int {
 
 extern bool mono_use_llvm; // this is defined inside mono
 
+#if defined (NATIVEAOT)
+#define SUPPORTS_DYNAMIC_REGISTRATION 0
+#else
+#define SUPPORTS_DYNAMIC_REGISTRATION 1
+#endif
+
 #if DEBUG
 extern bool xamarin_gc_pump;
 #endif
@@ -121,7 +127,9 @@ extern bool xamarin_is_gc_coop;
 extern enum MarshalObjectiveCExceptionMode xamarin_marshal_objectivec_exception_mode;
 extern enum MarshalManagedExceptionMode xamarin_marshal_managed_exception_mode;
 extern enum XamarinLaunchMode xamarin_launch_mode;
+#if SUPPORTS_DYNAMIC_REGISTRATION
 extern bool xamarin_supports_dynamic_registration;
+#endif
 extern const char *xamarin_runtime_configuration_name;
 extern enum XamarinNativeLinkMode xamarin_libmono_native_link_mode;
 extern const char** xamarin_runtime_libraries;
diff --git a/tools/common/Target.cs b/tools/common/Target.cs
index 6b20a8a51abe..5cc2a4e90ad0 100644
--- a/tools/common/Target.cs
+++ b/tools/common/Target.cs
@@ -856,7 +856,8 @@ void GenerateIOSMain (StringWriter sw, Abi abi)
 			// Do this last, so that the app developer can override any other environment variable we set.
 			foreach (var kvp in app.EnvironmentVariables)
 				sw.WriteLine ("\tsetenv (\"{0}\", \"{1}\", 1);", kvp.Key.Replace ("\"", "\\\""), kvp.Value.Replace ("\"", "\\\""));
-			sw.WriteLine ("\txamarin_supports_dynamic_registration = {0};", app.DynamicRegistrationSupported ? "TRUE" : "FALSE");
+			if (app.XamarinRuntime != XamarinRuntime.NativeAOT)
+				sw.WriteLine ("\txamarin_supports_dynamic_registration = {0};", app.DynamicRegistrationSupported ? "TRUE" : "FALSE");
 #if NET
 			sw.WriteLine ("\txamarin_runtime_configuration_name = {0};", string.IsNullOrEmpty (app.RuntimeConfigurationFile) ? "NULL" : $"\"{app.RuntimeConfigurationFile}\"");
 #endif

From d5a53d65b7f2996048a9e3e2f19aa4285dabef73 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:52 +0200
Subject: [PATCH 13/46] [runtime] Add a native IsNativeAOT flag.

---
 runtime/runtime.m          | 4 ++++
 src/ObjCRuntime/Runtime.cs | 9 +++++++++
 2 files changed, 13 insertions(+)

diff --git a/runtime/runtime.m b/runtime/runtime.m
index c13f751c358b..1c0e08f544a4 100644
--- a/runtime/runtime.m
+++ b/runtime/runtime.m
@@ -143,6 +143,7 @@
 	/* unused									= 0x08,*/
 	InitializationFlagsIsSimulator				= 0x10,
 	InitializationFlagsIsCoreCLR                = 0x20,
+	InitializationFlagsIsNativeAOT              = 0x40,
 };
 
 struct InitializationOptions {
@@ -1302,6 +1303,9 @@ -(void) xamarinSetFlags: (enum XamarinGCHandleFlags) flags;
 #if defined (CORECLR_RUNTIME)
 	options.flags = (enum InitializationFlags) (options.flags | InitializationFlagsIsCoreCLR);
 #endif
+#if defined (NATIVEAOT)
+	options.flags = (enum InitializationFlags) (options.flags | InitializationFlagsIsNativeAOT);
+#endif
 
 	options.Delegates = &delegates;
 	options.Trampolines = &trampolines;
diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs
index 7d63d96aba60..f86fc65711d0 100644
--- a/src/ObjCRuntime/Runtime.cs
+++ b/src/ObjCRuntime/Runtime.cs
@@ -159,6 +159,7 @@ internal enum InitializationFlags : int {
 			IsSimulator = 0x10,
 #if NET
 			IsCoreCLR				= 0x20,
+			IsNativeAOT				= 0x40,
 #endif
 		}
 
@@ -222,6 +223,14 @@ internal unsafe static bool IsCoreCLR {
 				return (options->Flags.HasFlag (InitializationFlags.IsCoreCLR));
 			}
 		}
+
+		[BindingImpl (BindingImplOptions.Optimizable)]
+		internal unsafe static bool IsNativeAOT {
+			get {
+				// The linker may turn calls to this property into a constant
+				return (options->Flags.HasFlag (InitializationFlags.IsNativeAOT));
+			}
+		}
 #endif
 
 		[BindingImpl (BindingImplOptions.Optimizable)]

From b4a67c69c8bcf9059441da4e6698ada98cf0c6a6 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:52 +0200
Subject: [PATCH 14/46] [src] Make the Runtime.IsNativeAOT property a constant
 in the linker.

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 4 ++++
 src/ILLink.Substitutions.MacCatalyst.xml  | 5 ++++-
 src/ILLink.Substitutions.ios.xml          | 5 ++++-
 src/ILLink.Substitutions.macOS.xml        | 2 ++
 src/ILLink.Substitutions.tvos.xml         | 5 ++++-
 5 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index f5411a309f56..1459ea3f2612 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -572,6 +572,10 @@
 			<_ExtraTrimmerArgs Condition="'$(Registrar)' == 'managed-static'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsManagedStaticRegistrar true</_ExtraTrimmerArgs>
 			<_ExtraTrimmerArgs Condition="'$(Registrar)' != 'managed-static'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsManagedStaticRegistrar false</_ExtraTrimmerArgs>
 
+			<!-- Set NativeAOT value -->
+			<_ExtraTrimmerArgs Condition="'$(_XamarinRuntime)' == 'NativeAOT'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsNativeAOT true</_ExtraTrimmerArgs>
+			<_ExtraTrimmerArgs Condition="'$(_XamarinRuntime)' != 'NativeAOT'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsNativeAOT false</_ExtraTrimmerArgs>
+
 			<!-- Enable serialization discovery. Ref: https://github.com/xamarin/xamarin-macios/issues/15676 -->
 			<_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --enable-serialization-discovery</_ExtraTrimmerArgs>
 
diff --git a/src/ILLink.Substitutions.MacCatalyst.xml b/src/ILLink.Substitutions.MacCatalyst.xml
index 82dfcf97ae5c..21704812349f 100644
--- a/src/ILLink.Substitutions.MacCatalyst.xml
+++ b/src/ILLink.Substitutions.MacCatalyst.xml
@@ -4,7 +4,10 @@
       <method signature="System.Void WarnOnce()" body="stub" feature="System.Diagnostics.Debugger.IsSupported" featurevalue="false" />
     </type>
     <type fullname="ObjCRuntime.Runtime">
-      <method signature="System.Boolean get_IsCoreCLR()" body="stub" value="false" />
+      <method signature="System.Boolean get_IsCoreCLR()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="false" value="false" />
+      <method signature="System.Boolean get_IsCoreCLR()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="true" value="true" />
+      <method signature="System.Boolean get_IsNativeAOT()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="false" value="false" />
+      <method signature="System.Boolean get_IsNativeAOT()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="true" value="true" />
       <method signature="System.Boolean get_IsManagedStaticRegistrar()" body="stub" feature="ObjCRuntime.Runtime.IsManagedStaticRegistrar" featurevalue="false" value="false" />
       <method signature="System.Boolean get_IsManagedStaticRegistrar()" body="stub" feature="ObjCRuntime.Runtime.IsManagedStaticRegistrar" featurevalue="true" value="true" />
     </type>
diff --git a/src/ILLink.Substitutions.ios.xml b/src/ILLink.Substitutions.ios.xml
index 00e9e50e50e6..c4d2a0a4228e 100644
--- a/src/ILLink.Substitutions.ios.xml
+++ b/src/ILLink.Substitutions.ios.xml
@@ -4,7 +4,10 @@
       <method signature="System.Void WarnOnce()" body="stub" feature="System.Diagnostics.Debugger.IsSupported" featurevalue="false" />
     </type>
     <type fullname="ObjCRuntime.Runtime">
-      <method signature="System.Boolean get_IsCoreCLR()" body="stub" value="false" />
+      <method signature="System.Boolean get_IsCoreCLR()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="false" value="false" />
+      <method signature="System.Boolean get_IsCoreCLR()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="true" value="true" />
+      <method signature="System.Boolean get_IsNativeAOT()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="false" value="false" />
+      <method signature="System.Boolean get_IsNativeAOT()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="true" value="true" />
       <method signature="System.Int32 GetRuntimeArch()" body="stub" feature="ObjCRuntime.Runtime.Arch.IsSimulator" featurevalue="false" value="0" />
       <method signature="System.Int32 GetRuntimeArch()" body="stub" feature="ObjCRuntime.Runtime.Arch.IsSimulator" featurevalue="true" value="1" />
       <method signature="System.Boolean get_IsManagedStaticRegistrar()" body="stub" feature="ObjCRuntime.Runtime.IsManagedStaticRegistrar" featurevalue="false" value="false" />
diff --git a/src/ILLink.Substitutions.macOS.xml b/src/ILLink.Substitutions.macOS.xml
index a0fd78280ac9..e993b4cc124c 100644
--- a/src/ILLink.Substitutions.macOS.xml
+++ b/src/ILLink.Substitutions.macOS.xml
@@ -5,6 +5,8 @@
     </type>
     <type fullname="ObjCRuntime.Runtime">
       <method signature="System.Boolean get_IsCoreCLR()" body="stub" value="true" />
+      <method signature="System.Boolean get_IsNativeAOT()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="false" value="false" />
+      <method signature="System.Boolean get_IsNativeAOT()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="true" value="true" />
       <method signature="System.Boolean get_IsManagedStaticRegistrar()" body="stub" feature="ObjCRuntime.Runtime.IsManagedStaticRegistrar" featurevalue="false" value="false" />
       <method signature="System.Boolean get_IsManagedStaticRegistrar()" body="stub" feature="ObjCRuntime.Runtime.IsManagedStaticRegistrar" featurevalue="true" value="true" />
     </type>
diff --git a/src/ILLink.Substitutions.tvos.xml b/src/ILLink.Substitutions.tvos.xml
index e03cc08a2fba..d057a9395ad0 100644
--- a/src/ILLink.Substitutions.tvos.xml
+++ b/src/ILLink.Substitutions.tvos.xml
@@ -4,7 +4,10 @@
       <method signature="System.Void WarnOnce()" body="stub" feature="System.Diagnostics.Debugger.IsSupported" featurevalue="false" />
     </type>
     <type fullname="ObjCRuntime.Runtime">
-      <method signature="System.Boolean get_IsCoreCLR()" body="stub" value="false" />
+      <method signature="System.Boolean get_IsCoreCLR()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="false" value="false" />
+      <method signature="System.Boolean get_IsCoreCLR()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="true" value="true" />
+      <method signature="System.Boolean get_IsNativeAOT()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="false" value="false" />
+      <method signature="System.Boolean get_IsNativeAOT()" body="stub" feature="ObjCRuntime.Runtime.IsNativeAOT" featurevalue="true" value="true" />
       <method signature="System.Int32 GetRuntimeArch()" body="stub" feature="ObjCRuntime.Runtime.Arch.IsSimulator" featurevalue="false" value="0" />
       <method signature="System.Int32 GetRuntimeArch()" body="stub" feature="ObjCRuntime.Runtime.Arch.IsSimulator" featurevalue="true" value="1" />
       <method signature="System.Boolean get_IsManagedStaticRegistrar()" body="stub" feature="ObjCRuntime.Runtime.IsManagedStaticRegistrar" featurevalue="false" value="false" />

From e0e4b77a55b6e7733367ed7ab9cf8477c31846ef Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:52 +0200
Subject: [PATCH 15/46] [dotnet] Set AutoreleasePoolSupport earlier so that the
 linker doesn't set it first.

Might not be necessary: https://github.com/dotnet/runtime/pull/86753
---
 dotnet/targets/Xamarin.Shared.Sdk.props   | 7 +++++++
 dotnet/targets/Xamarin.Shared.Sdk.targets | 2 +-
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.props b/dotnet/targets/Xamarin.Shared.Sdk.props
index 3bff654e6993..c23cf981c0c1 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.props
+++ b/dotnet/targets/Xamarin.Shared.Sdk.props
@@ -58,6 +58,13 @@
 
 		<!-- Explicitly export symbols using clang command-line option "-exported_symbols_list export_list" -->
 		<_ExportSymbolsExplicitly Condition="'$(_ExportSymbolsExplicitly)' == ''">true</_ExportSymbolsExplicitly>
+
+		<!--
+			Some runtime libraries feature switches defaults that need to be set early
+			Available feature switches: https://github.com/dotnet/runtime/blob/master/docs/workflow/trimming/feature-switches.md
+		-->
+		<!-- AutoreleasePoolSupport needs to be set earlier than other switches, so that illink doesn't override it - https://github.com/dotnet/runtime/pull/86753 - so it's set here, instead of in Xamarin.Shared.Sdk.targets -->
+		<AutoreleasePoolSupport Condition="'$(AutoreleasePoolSupport)' == ''">true</AutoreleasePoolSupport>
 	</PropertyGroup>
 
 	<!-- Set the default RuntimeIdentifier if not already specified. -->
diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index 1459ea3f2612..d0a0032313b7 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -130,7 +130,7 @@
 		<UseSystemResourceKeys Condition="'$(UseSystemResourceKeys)' == '' And '$(_BundlerDebug)' != 'true'">true</UseSystemResourceKeys>
 		<UseSystemResourceKeys Condition="'$(UseSystemResourceKeys)' == '' And '$(_BundlerDebug)' == 'true'">false</UseSystemResourceKeys>
 		<UseNativeHttpHandler Condition="'$(_PlatformName)' != 'macOS' And '$(UseNativeHttpHandler)' == ''">true</UseNativeHttpHandler>
-		<AutoreleasePoolSupport Condition="'$(AutoreleasePoolSupport)' == ''">true</AutoreleasePoolSupport>
+		<!-- AutoreleasePoolSupport needs to be set earlier, so that illink doesn't override it - https://github.com/dotnet/runtime/pull/86753 - so it's set in Xamarin.Shared.Sdk.props -->
 		<_AggressiveAttributeTrimming Condition="'$(_AggressiveAttributeTrimming)' == ''">true</_AggressiveAttributeTrimming>		
 		<NullabilityInfoContextSupport Condition="'$(NullabilityInfoContextSupport)' == ''">false</NullabilityInfoContextSupport>
 		<BuiltInComInteropSupport Condition="'$(BuiltInComInteropSupport)' == ''">false</BuiltInComInteropSupport>

From 901be399257eba41320aa37a1e125a8182df9938 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:52 +0200
Subject: [PATCH 16/46] [ObjCRuntime] Avoid using Assembly.Location for
 NativeAOT, use an alternative implementation instead.

The Runtime.GetAssemblyLocation method is only used for diagnostic purposes, so the
exact value returned doesn't matter all that much, as long as it makes sense.
---
 src/ObjCRuntime/Runtime.CoreCLR.cs | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/src/ObjCRuntime/Runtime.CoreCLR.cs b/src/ObjCRuntime/Runtime.CoreCLR.cs
index b9f3622fda0e..5dfe7e77734e 100644
--- a/src/ObjCRuntime/Runtime.CoreCLR.cs
+++ b/src/ObjCRuntime/Runtime.CoreCLR.cs
@@ -506,7 +506,16 @@ static IntPtr GetAssemblyName (IntPtr gchandle)
 		static IntPtr GetAssemblyLocation (IntPtr gchandle)
 		{
 			var asm = (Assembly?) GetGCHandleTarget (gchandle);
-			return Marshal.StringToHGlobalAuto (asm?.Location);
+			if (asm is null)
+				return IntPtr.Zero;
+
+			string location;
+			if (IsNativeAOT) {
+				location = Path.Combine (System.AppContext.BaseDirectory, asm.GetName ().Name + ".dll");
+			} else {
+				location = asm.Location;
+			}
+			return Marshal.StringToHGlobalAuto (location);
 		}
 
 		static void SetFlagsForNSObject (IntPtr gchandle, byte flags)

From 31052141e7da97ad9aa77c75b4afd57d01c611da Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:52 +0200
Subject: [PATCH 17/46] [tests] Detect NativeAOT correctly in the Symbols test

---
 tests/monotouch-test/mono/Symbols.cs | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/tests/monotouch-test/mono/Symbols.cs b/tests/monotouch-test/mono/Symbols.cs
index cb24398bbd5f..61aea05ea396 100644
--- a/tests/monotouch-test/mono/Symbols.cs
+++ b/tests/monotouch-test/mono/Symbols.cs
@@ -20,6 +20,7 @@ public void FunctionNames ()
 
 			Collect ();
 			bool aot = symbols [1].Contains ("MonoTouchFixtures_Symbols_Collect");
+			bool nativeaot = symbols [1].Contains ("MonoTouchFixtures_Symbols__Collect");
 			bool llvmonly = symbols [1].Contains ("mono_llvmonly_runtime_invoke"); // LLVM inlines the Collect function, so 'Collect' doesn't show up in the stack trace :/
 			bool interp = false;
 
@@ -32,7 +33,7 @@ public void FunctionNames ()
 				}
 			}
 
-			Assert.IsTrue (aot || interp || llvmonly, $"#1\n\t{string.Join ("\n\t", symbols)}");
+			Assert.IsTrue (aot || interp || llvmonly || nativeaot, $"#1\n\t{string.Join ("\n\t", symbols)}");
 		}
 
 		void Collect ()

From 5b8d60bbe36f75d653d185f17c9640130487a801 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:53 +0200
Subject: [PATCH 18/46] [tests] Adjust RegistrarTest to always expected the
 dynamic registrar to be removed for NativeAOT

---
 tests/monotouch-test/ObjCRuntime/RegistrarTest.cs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs
index c9e7eb495195..dd17244c45c2 100644
--- a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs
+++ b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs
@@ -111,7 +111,7 @@ public void RegistrarRemoval ()
 			// It's not safe to remove the dynamic registrar in monotouch-test (by design; some of the tested API makes it unsafe, and the linker correctly detects this),
 			// so the dynamic registrar will only be removed if manually requested.
 			// Also removal of the dynamic registrar is not supported in XM
-#if OPTIMIZEALL && !__MACOS__
+#if (OPTIMIZEALL && !__MACOS__) || NATIVEAOT
 			var shouldBeRemoved = true;
 #else
 			var shouldBeRemoved = false;

From 890d3cadf68c28653431bbaa0236d8a8be3216f8 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:53 +0200
Subject: [PATCH 19/46] [tests] Adjust asserts since some collection assert
 doesn't work with NativeAOT.

Rewrite a few asserts, since NUnitLite isn't actually trimmer-safe, and some collection
asserts don't work with NativeAOT.
---
 tests/bindings-test/ProtocolTest.cs | 109 ++++++++++++++++------------
 1 file changed, 62 insertions(+), 47 deletions(-)

diff --git a/tests/bindings-test/ProtocolTest.cs b/tests/bindings-test/ProtocolTest.cs
index ba1d57be1f92..d1fa363842a0 100644
--- a/tests/bindings-test/ProtocolTest.cs
+++ b/tests/bindings-test/ProtocolTest.cs
@@ -164,50 +164,50 @@ public void ProtocolMembers ()
 			methods = protocol_copyMethodDescriptionList (protocol, true, true);
 			CleanupSignatures (methods);
 			Assert.AreEqual (4, methods.Length, "Required Instance Methods: Count");
-			Assert.That (methods, Contains.Item (new objc_method_description ("requiredInstanceMethod", "v@:")), "Required Instance Methods: requiredInstanceMethod");
-			Assert.That (methods, Contains.Item (new objc_method_description ("requiredInstanceProperty", "@@:")), "Required Instance Methods: requiredInstanceProperty");
-			Assert.That (methods, Contains.Item (new objc_method_description ("setRequiredInstanceProperty:", "v@:@")), "Required Instance Methods: setRequiredInstanceProperty");
-			Assert.That (methods, Contains.Item (new objc_method_description ("requiredReadonlyProperty", "@@:")), "Required Instance Methods: requiredReadonlyProperty:");
+			AssertContains (methods, new objc_method_description ("requiredInstanceMethod", "v@:"), "Required Instance Methods: requiredInstanceMethod");
+			AssertContains (methods, new objc_method_description ("requiredInstanceProperty", "@@:"), "Required Instance Methods: requiredInstanceProperty");
+			AssertContains (methods, new objc_method_description ("setRequiredInstanceProperty:", "v@:@"), "Required Instance Methods: setRequiredInstanceProperty");
+			AssertContains (methods, new objc_method_description ("requiredReadonlyProperty", "@@:"), "Required Instance Methods: requiredReadonlyProperty:");
 
 			// Required static methods
 			methods = protocol_copyMethodDescriptionList (protocol, true, false);
 			CleanupSignatures (methods);
 			Assert.AreEqual (3, methods.Length, "Required Static Methods: Count");
-			Assert.That (methods, Contains.Item (new objc_method_description ("requiredStaticMethod", "v@:")), "Required Static Methods: requiredStaticMethod");
-			Assert.That (methods, Contains.Item (new objc_method_description ("setRequiredStaticProperty:", "v@:@")), "Required Static Methods: setRequiredStaticProperty:");
-			Assert.That (methods, Contains.Item (new objc_method_description ("requiredStaticProperty", "@@:")), "Required Static Methods: requiredStaticProperty");
+			AssertContains (methods, new objc_method_description ("requiredStaticMethod", "v@:"), "Required Static Methods: requiredStaticMethod");
+			AssertContains (methods, new objc_method_description ("setRequiredStaticProperty:", "v@:@"), "Required Static Methods: setRequiredStaticProperty:");
+			AssertContains (methods, new objc_method_description ("requiredStaticProperty", "@@:"), "Required Static Methods: requiredStaticProperty");
 
 			// Optional instance methods
 			methods = protocol_copyMethodDescriptionList (protocol, false, true);
 			CleanupSignatures (methods);
 			Assert.AreEqual (19, methods.Length, "Optional Instance Methods: Count");
-			Assert.That (methods, Contains.Item (new objc_method_description ("variadicMethod:", "v@:^v")), "Optional Instance Methods: variadicMethod:");
-			Assert.That (methods, Contains.Item (new objc_method_description ("methodWithReturnType", "@@:")), "Optional Instance Methods: methodWithReturnType");
-			Assert.That (methods, Contains.Item (new objc_method_description ("methodWithParameter:", "v@:i")), "Optional Instance Methods: methodWithParameter:");
-			Assert.That (methods, Contains.Item (new objc_method_description ("methodWithParameters:second:third:fourth:", "v@:iiii")), "Optional Instance Methods: methodWithParameters:second:third:fourth:");
-			Assert.That (methods, Contains.Item (new objc_method_description ("optionalInstanceMethod", "v@:")), "Optional Instance Methods: optionalInstanceMethod");
-			Assert.That (methods, Contains.Item (new objc_method_description ("methodWithRefParameters:second:third:fourth:", "v@:i^i^ii")), "Optional Instance Methods: methodWithRefParameters:second:third:fourth:");
-			Assert.That (methods, Contains.Item (new objc_method_description ("optionalInstanceProperty", "@@:")), "Optional Instance Methods: optionalInstanceProperty");
-			Assert.That (methods, Contains.Item (new objc_method_description ("setOptionalInstanceProperty:", "v@:@")), "Optional Instance Methods: setOptionalInstanceProperty:");
-			Assert.That (methods, Contains.Item (new objc_method_description ("get_propertyWithCustomAccessors", "@@:")), "Optional Instance Methods: get_propertyWithCustomAccessors");
-			Assert.That (methods, Contains.Item (new objc_method_description ("set_propertyWithCustomAccessors:", "v@:@")), "Optional Instance Methods: set_propertyWithCustomAccessors:");
-			Assert.That (methods, Contains.Item (new objc_method_description ("propertyWithArgumentSemanticNone", "@@:")), "Optional Instance Methods: propertyWithArgumentSemanticNone");
-			Assert.That (methods, Contains.Item (new objc_method_description ("setPropertyWithArgumentSemanticNone:", "v@:@")), "Optional Instance Methods: setPropertyWithArgumentSemanticNone:");
-			Assert.That (methods, Contains.Item (new objc_method_description ("propertyWithArgumentSemanticCopy", "@@:")), "Optional Instance Methods: propertyWithArgumentSemanticCopy");
-			Assert.That (methods, Contains.Item (new objc_method_description ("setPropertyWithArgumentSemanticCopy:", "v@:@")), "Optional Instance Methods: setPropertyWithArgumentSemanticCopy:");
-			Assert.That (methods, Contains.Item (new objc_method_description ("propertyWithArgumentSemanticAssign", "@@:")), "Optional Instance Methods: propertyWithArgumentSemanticAssign");
-			Assert.That (methods, Contains.Item (new objc_method_description ("setPropertyWithArgumentSemanticAssign:", "v@:@")), "Optional Instance Methods: setPropertyWithArgumentSemanticAssign:");
-			Assert.That (methods, Contains.Item (new objc_method_description ("readonlyProperty", "@@:")), "Optional Instance Methods: readonlyProperty:");
-			Assert.That (methods, Contains.Item (new objc_method_description ("propertyWithArgumentSemanticRetain", "@@:")), "Optional Instance Methods: propertyWithArgumentSemanticRetain");
-			Assert.That (methods, Contains.Item (new objc_method_description ("setPropertyWithArgumentSemanticRetain:", "v@:@")), "Optional Instance Methods: setPropertyWithArgumentSemanticRetain:");
+			AssertContains (methods, new objc_method_description ("variadicMethod:", "v@:^v"), "Optional Instance Methods: variadicMethod:");
+			AssertContains (methods, new objc_method_description ("methodWithReturnType", "@@:"), "Optional Instance Methods: methodWithReturnType");
+			AssertContains (methods, new objc_method_description ("methodWithParameter:", "v@:i"), "Optional Instance Methods: methodWithParameter:");
+			AssertContains (methods, new objc_method_description ("methodWithParameters:second:third:fourth:", "v@:iiii"), "Optional Instance Methods: methodWithParameters:second:third:fourth:");
+			AssertContains (methods, new objc_method_description ("optionalInstanceMethod", "v@:"), "Optional Instance Methods: optionalInstanceMethod");
+			AssertContains (methods, new objc_method_description ("methodWithRefParameters:second:third:fourth:", "v@:i^i^ii"), "Optional Instance Methods: methodWithRefParameters:second:third:fourth:");
+			AssertContains (methods, new objc_method_description ("optionalInstanceProperty", "@@:"), "Optional Instance Methods: optionalInstanceProperty");
+			AssertContains (methods, new objc_method_description ("setOptionalInstanceProperty:", "v@:@"), "Optional Instance Methods: setOptionalInstanceProperty:");
+			AssertContains (methods, new objc_method_description ("get_propertyWithCustomAccessors", "@@:"), "Optional Instance Methods: get_propertyWithCustomAccessors");
+			AssertContains (methods, new objc_method_description ("set_propertyWithCustomAccessors:", "v@:@"), "Optional Instance Methods: set_propertyWithCustomAccessors:");
+			AssertContains (methods, new objc_method_description ("propertyWithArgumentSemanticNone", "@@:"), "Optional Instance Methods: propertyWithArgumentSemanticNone");
+			AssertContains (methods, new objc_method_description ("setPropertyWithArgumentSemanticNone:", "v@:@"), "Optional Instance Methods: setPropertyWithArgumentSemanticNone:");
+			AssertContains (methods, new objc_method_description ("propertyWithArgumentSemanticCopy", "@@:"), "Optional Instance Methods: propertyWithArgumentSemanticCopy");
+			AssertContains (methods, new objc_method_description ("setPropertyWithArgumentSemanticCopy:", "v@:@"), "Optional Instance Methods: setPropertyWithArgumentSemanticCopy:");
+			AssertContains (methods, new objc_method_description ("propertyWithArgumentSemanticAssign", "@@:"), "Optional Instance Methods: propertyWithArgumentSemanticAssign");
+			AssertContains (methods, new objc_method_description ("setPropertyWithArgumentSemanticAssign:", "v@:@"), "Optional Instance Methods: setPropertyWithArgumentSemanticAssign:");
+			AssertContains (methods, new objc_method_description ("readonlyProperty", "@@:"), "Optional Instance Methods: readonlyProperty:");
+			AssertContains (methods, new objc_method_description ("propertyWithArgumentSemanticRetain", "@@:"), "Optional Instance Methods: propertyWithArgumentSemanticRetain");
+			AssertContains (methods, new objc_method_description ("setPropertyWithArgumentSemanticRetain:", "v@:@"), "Optional Instance Methods: setPropertyWithArgumentSemanticRetain:");
 
 			// Optional static methods
 			methods = protocol_copyMethodDescriptionList (protocol, false, false);
 			CleanupSignatures (methods);
 			Assert.AreEqual (3, methods.Length, "Optional Static Methods: Count");
-			Assert.That (methods, Contains.Item (new objc_method_description ("optionalStaticMethod", "v@:")), "Optional Static Methods: optionalStaticMethod");
-			Assert.That (methods, Contains.Item (new objc_method_description ("optionalStaticProperty", "@@:")), "Optional Static Methods: optionalStaticProperty");
-			Assert.That (methods, Contains.Item (new objc_method_description ("setOptionalStaticProperty:", "v@:@")), "Optional Static Methods: setOptionalStaticProperty:");
+			AssertContains (methods, new objc_method_description ("optionalStaticMethod", "v@:"), "Optional Static Methods: optionalStaticMethod");
+			AssertContains (methods, new objc_method_description ("optionalStaticProperty", "@@:"), "Optional Static Methods: optionalStaticProperty");
+			AssertContains (methods, new objc_method_description ("setOptionalStaticProperty:", "v@:@"), "Optional Static Methods: setOptionalStaticProperty:");
 
 			objc_property [] properties;
 			properties = protocol_copyPropertyList (protocol);
@@ -221,60 +221,75 @@ public void ProtocolMembers ()
 				Assert.AreEqual (2, properties.Length, "Properties: Count");
 			}
 
-			Assert.That (properties, Contains.Item (new objc_property ("requiredInstanceProperty", "T@\"NSString\",N", new objc_property_attribute [] {
+			AssertContains (properties, new objc_property ("requiredInstanceProperty", "T@\"NSString\",N", new objc_property_attribute [] {
 				new objc_property_attribute ("T", "@\"NSString\""),
 				new objc_property_attribute ("N", "")
-			})), "Properties: requiredInstanceProperty");
+			}), "Properties: requiredInstanceProperty");
 
-			Assert.That (properties, Contains.Item (new objc_property ("requiredReadonlyProperty", "T@\"NSString\",R,N", new objc_property_attribute [] {
+			AssertContains (properties, new objc_property ("requiredReadonlyProperty", "T@\"NSString\",R,N", new objc_property_attribute [] {
 				new objc_property_attribute ("T", "@\"NSString\""),
 				new objc_property_attribute ("R", ""),
 				new objc_property_attribute ("N", "")
-			})), "Properties: requiredReadonlyProperty");
+			}), "Properties: requiredReadonlyProperty");
 
 			if (XamarinTests.ObjCRuntime.Registrar.IsStaticRegistrar) {
-				Assert.That (properties, Contains.Item (new objc_property ("optionalInstanceProperty", "T@\"NSString\",N", new objc_property_attribute [] {
+				AssertContains (properties, new objc_property ("optionalInstanceProperty", "T@\"NSString\",N", new objc_property_attribute [] {
 					new objc_property_attribute ("T", "@\"NSString\""),
 					new objc_property_attribute ("N", "")
-				})), "Properties: optionalInstanceProperty");
+				}), "Properties: optionalInstanceProperty");
 
-				Assert.That (properties, Contains.Item (new objc_property ("propertyWithCustomAccessors", "T@\"NSString\",N,Gget_propertyWithCustomAccessors,Sset_propertyWithCustomAccessors:", new objc_property_attribute [] {
+				AssertContains (properties, new objc_property ("propertyWithCustomAccessors", "T@\"NSString\",N,Gget_propertyWithCustomAccessors,Sset_propertyWithCustomAccessors:", new objc_property_attribute [] {
 					new objc_property_attribute ("T", "@\"NSString\""),
 					new objc_property_attribute ("N", ""),
 					new objc_property_attribute ("G", "get_propertyWithCustomAccessors"),
 					new objc_property_attribute ("S", "set_propertyWithCustomAccessors:")
-				})), "Properties: propertyWithCustomAccessors");
+				}), "Properties: propertyWithCustomAccessors");
 
-				Assert.That (properties, Contains.Item (new objc_property ("propertyWithArgumentSemanticNone", "T@\"NSString\",N", new objc_property_attribute [] {
+				AssertContains (properties, new objc_property ("propertyWithArgumentSemanticNone", "T@\"NSString\",N", new objc_property_attribute [] {
 					new objc_property_attribute ("T", "@\"NSString\""),
 					new objc_property_attribute ("N", "")
-				})), "Properties: propertyWithArgumentSemanticNone");
+				}), "Properties: propertyWithArgumentSemanticNone");
 
-				Assert.That (properties, Contains.Item (new objc_property ("propertyWithArgumentSemanticCopy", "T@\"NSString\",C,N", new objc_property_attribute [] {
+				AssertContains (properties, new objc_property ("propertyWithArgumentSemanticCopy", "T@\"NSString\",C,N", new objc_property_attribute [] {
 					new objc_property_attribute ("T", "@\"NSString\""),
 					new objc_property_attribute ("N", ""),
 					new objc_property_attribute ("C", "")
-				})), "Properties: propertyWithArgumentSemanticCopy");
+				}), "Properties: propertyWithArgumentSemanticCopy");
 
-				Assert.That (properties, Contains.Item (new objc_property ("propertyWithArgumentSemanticAssign", "T@\"NSString\",N", new objc_property_attribute [] {
+				AssertContains (properties, new objc_property ("propertyWithArgumentSemanticAssign", "T@\"NSString\",N", new objc_property_attribute [] {
 					new objc_property_attribute ("T", "@\"NSString\""),
 					new objc_property_attribute ("N", "")
-				})), "Properties: propertyWithArgumentSemanticAssign");
+				}), "Properties: propertyWithArgumentSemanticAssign");
 
-				Assert.That (properties, Contains.Item (new objc_property ("propertyWithArgumentSemanticRetain", "T@\"NSString\",&,N", new objc_property_attribute [] {
+				AssertContains (properties, new objc_property ("propertyWithArgumentSemanticRetain", "T@\"NSString\",&,N", new objc_property_attribute [] {
 					new objc_property_attribute ("T", "@\"NSString\""),
 					new objc_property_attribute ("&", ""),
 					new objc_property_attribute ("N", "")
-				})), "Properties: propertyWithArgumentSemanticRetain");
+				}), "Properties: propertyWithArgumentSemanticRetain");
 
-				Assert.That (properties, Contains.Item (new objc_property ("readonlyProperty", "T@\"NSString\",R,N", new objc_property_attribute [] {
+				AssertContains (properties, new objc_property ("readonlyProperty", "T@\"NSString\",R,N", new objc_property_attribute [] {
 					new objc_property_attribute ("T", "@\"NSString\""),
 					new objc_property_attribute ("R", ""),
 					new objc_property_attribute ("N", "")
-				})), "Properties: readonlyProperty");
+				}), "Properties: readonlyProperty");
 			}
 		}
 
+		static void AssertContains<T> (T [] array, T item, string message) where T : IEquatable<T>
+		{
+			for (var i = 0; i < array.Length; i++) {
+				var element = array [i];
+				if (element is null && item is null)
+					return;
+				if (element is null || item is null)
+					continue;
+				if (element.Equals (item))
+					return;
+			}
+
+			throw new Exception ($"Collection {array} does not contain item {item}: {message}");
+		}
+
 		[DllImport ("/usr/lib/libobjc.dylib")]
 		internal extern static IntPtr objc_getProtocol (string name);
 

From 0db2c5c53fc674a85129850ab338ed93450f1fb6 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:53 +0200
Subject: [PATCH 20/46] [dotnet] Rework feature detection and notification a
 bit.

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 52 ++++++++++++++++-------
 1 file changed, 37 insertions(+), 15 deletions(-)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index d0a0032313b7..a9875c51e0e1 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -433,9 +433,46 @@
 			_DetectAppManifest;
 			_ReadAppManifest;
 			_WriteAppManifest;
+			_ComputeLinkerFeatures;
 		</_ComputeLinkerArgumentsDependsOn>
 	</PropertyGroup>
 
+	<Target Name="_ComputeLinkerFeatures">
+		<PropertyGroup Condition="'$(PublishAot)' == 'true'">
+			<!-- The one and only registrar is 'managed-static' when using NativeAOT -->
+			<Registrar Condition="'$(Registrar)' == ''">managed-static</Registrar>
+
+			<!-- Yep, we want to run ILLink as well, because we need our custom steps to run (NativeAOT sets this to false, so set it back to true) -->
+			<RunILLink>true</RunILLink>
+		</PropertyGroup>
+
+		<PropertyGroup>
+			<!-- Set linker feature flags for device/simulator builds -->
+			<_IsSimulatorFeature Condition="('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS') And '$(_SdkIsSimulator)' == 'true'">true</_IsSimulatorFeature>
+			<_IsSimulatorFeature Condition="'$(_IsSimulatorFeature)' == ''">false</_IsSimulatorFeature>
+
+			<!-- Set managed static registrar value -->
+			<_IsManagedStaticRegistrarFeature Condition="'$(Registrar)' == 'managed-static'">true</_IsManagedStaticRegistrarFeature>
+			<_IsManagedStaticRegistrarFeature Condition="'$(Registrar)' != 'managed-static'">false</_IsManagedStaticRegistrarFeature>
+
+			<!-- Set NativeAOT value -->
+			<_IsNativeAOTFeature Condition="'$(_XamarinRuntime)' == 'NativeAOT'">true</_IsNativeAOTFeature>
+			<_IsNativeAOTFeature Condition="'$(_XamarinRuntime)' != 'NativeAOT'">false</_IsNativeAOTFeature>
+
+			<!-- Set the features for ILLink -->
+			<_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.Arch.IsSimulator $(_IsSimulatorFeature)</_ExtraTrimmerArgs>
+			<_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsManagedStaticRegistrar $(_IsManagedStaticRegistrarFeature)</_ExtraTrimmerArgs>
+			<_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsNativeAOT $(_IsNativeAOTFeature)</_ExtraTrimmerArgs>
+		</PropertyGroup>
+
+		<ItemGroup>
+			<!-- Set the features for ILC -->
+			<IlcArg Include="--feature:ObjCRuntime.Runtime.Arch.IsSimulator=$(_IsSimulatorFeature)" />
+			<IlcArg Include="--feature:ObjCRuntime.Runtime.IsManagedStaticRegistrar=$(_IsManagedStaticRegistrarFeature)" />
+			<IlcArg Include="--feature:ObjCRuntime.Runtime.IsNativeAOT=$(_IsNativeAOTFeature)" />
+		</ItemGroup>
+	</Target>
+
 	<Target Name="_ComputeLinkerArguments" DependsOnTargets="$(_ComputeLinkerArgumentsDependsOn)">
 		<!-- Validate the linker mode -->
 		<Error Text="Invalid link mode: '$(_LinkMode)'. Valid link modes are: 'None', 'SdkOnly' and 'Full'" Condition="'$(_LinkMode)' != 'None' And '$(_LinkMode)' != 'SdkOnly' And '$(_LinkMode)' != 'Full' And '$(_LinkMode)' != 'TrimMode'" />
@@ -444,9 +481,6 @@
 		<Error Text="Can not set values for both InvariantGlobalization '$(InvariantGlobalization)' and _GlobalizationDataFile '$(_GlobalizationDataFile)'" Condition="'$(_GlobalizationDataFile)' != '' And '$(InvariantGlobalization)' == 'true'" />
 
 		<Error Text="The only valid registrar when using NativeAOT is 'managed-static' (current value: '$(Registrar)'). Please either delete the 'Registrar' property, or change it to be 'managed-static'." Condition="'$(PublishAot)' == 'true' And '$(Registrar)' != '' And '$(Registrar)' != 'managed-static'" />
-		<PropertyGroup Condition="'$(PublishAot)' == 'true'">
-			<Registrar Condition="'$(Registrar)' == ''">managed-static</Registrar>
-		</PropertyGroup>
 
 		<PropertyGroup>
 			<!-- Pass the custom options to our custom steps -->
@@ -564,18 +598,6 @@
 			<!-- If a release build and the app is not extensible (no interpreter or JIT/code-loading for macOS) then the sealer optimization can be used -->
 			<_ExtraTrimmerArgs Condition="'$(_BundlerDebug)' != 'true' And '$(MtouchInterpreter)' == '' And '$(_RunAotCompiler)' == 'true' And '$(_PlatformName)' != 'macOS'">$(_ExtraTrimmerArgs) --enable-opt sealer</_ExtraTrimmerArgs>
 
-			<!-- Set linker feature flags for device/simulator builds -->
-			<_ExtraTrimmerArgs Condition="('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS') And '$(_SdkIsSimulator)' == 'true'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.Arch.IsSimulator true</_ExtraTrimmerArgs>
-			<_ExtraTrimmerArgs Condition="('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS') And '$(_SdkIsSimulator)' != 'true'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.Arch.IsSimulator false</_ExtraTrimmerArgs>
-
-			<!-- Set managed static registrar value -->
-			<_ExtraTrimmerArgs Condition="'$(Registrar)' == 'managed-static'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsManagedStaticRegistrar true</_ExtraTrimmerArgs>
-			<_ExtraTrimmerArgs Condition="'$(Registrar)' != 'managed-static'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsManagedStaticRegistrar false</_ExtraTrimmerArgs>
-
-			<!-- Set NativeAOT value -->
-			<_ExtraTrimmerArgs Condition="'$(_XamarinRuntime)' == 'NativeAOT'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsNativeAOT true</_ExtraTrimmerArgs>
-			<_ExtraTrimmerArgs Condition="'$(_XamarinRuntime)' != 'NativeAOT'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsNativeAOT false</_ExtraTrimmerArgs>
-
 			<!-- Enable serialization discovery. Ref: https://github.com/xamarin/xamarin-macios/issues/15676 -->
 			<_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --enable-serialization-discovery</_ExtraTrimmerArgs>
 

From 595bcdb92f10d019c3882d9c656d1f55f5aecaeb Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:53 +0200
Subject: [PATCH 21/46] [dotnet] Don't call ComputeResolvedFilesToPublishList
 when using NativeAOT.

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index a9875c51e0e1..645c6643c047 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -424,7 +424,13 @@
 			_ComputeLinkMode;
 			_ComputeFrameworkVariables;
 			_ComputeFrameworkAssemblies;
+		</_ComputeLinkerArgumentsDependsOn>
+		<_ComputeLinkerArgumentsDependsOn Condition="'$(PublishAot)' != 'true'">
+			$(_ComputeLinkerArgumentsDependsOn);
 			ComputeResolvedFilesToPublishList;
+		</_ComputeLinkerArgumentsDependsOn>
+		<_ComputeLinkerArgumentsDependsOn>
+			$(_ComputeLinkerArgumentsDependsOn);
 			_ParseBundlerArguments;
 			_ComputeVariables;
 			_CreateRuntimeConfiguration;
@@ -935,7 +941,7 @@
 			publish (except the merged app bundle, which we'll handle
 			ourselves).
 		-->
-		<_ComputeVariablesDependsOn Condition="'$(RuntimeIdentifiers)' == ''">$(_ComputeVariablesDependsOn);ComputeResolvedFilesToPublishList</_ComputeVariablesDependsOn>
+		<_ComputeVariablesDependsOn Condition="'$(RuntimeIdentifiers)' == '' And '$(PublishAot)' != 'true'">$(_ComputeVariablesDependsOn);ComputeResolvedFilesToPublishList</_ComputeVariablesDependsOn>
 	</PropertyGroup>
 
 	<Target Name="_ComputeVariables" DependsOnTargets="$(_ComputeVariablesDependsOn)">

From 13fa76923fc0b84bcf9e9ea1ddab600c88cbbe3e Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:54 +0200
Subject: [PATCH 22/46] [dotnet] Disable our own IL stripping when using
 NativeAOT, because NativeAOT already does something equivalent

---
 dotnet/targets/Xamarin.Shared.Sdk.props | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.props b/dotnet/targets/Xamarin.Shared.Sdk.props
index c23cf981c0c1..a92e4f0af15a 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.props
+++ b/dotnet/targets/Xamarin.Shared.Sdk.props
@@ -112,4 +112,13 @@
 	<PropertyGroup Condition="'$(MtouchUseLlvm)' == '' And '$(Configuration)' == 'Release' And ('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS')">
 		<MtouchUseLlvm>true</MtouchUseLlvm>
 	</PropertyGroup>
+
+	<!-- Various options when using NativeAOT -->
+	<PropertyGroup Condition="'$(PublishAot)' == 'true'">
+		<!-- Disable our own assembly IL stripping logic, because ILC does that already -->
+		<EnableAssemblyILStripping>false</EnableAssemblyILStripping>
+
+		<!-- We're using our own native main function when using NativeAOT -->
+		<CustomNativeMain>true</CustomNativeMain>
+	</PropertyGroup>
 </Project>

From b36db052750ad8dc48673047fe01fae573447516 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:54 +0200
Subject: [PATCH 23/46] [dotnet] Call ILC, the NativeAOT compiler, before we
 link the native executable

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index 645c6643c047..4a1d45b61ce6 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -1210,6 +1210,11 @@
 			_ComputeNativeExecutableInputs;
 			_AOTCompile;
 		</_CompileNativeExecutableDependsOn>
+
+		<_CompileNativeExecutableDependsOn Condition="'$(PublishAot)' == 'true'">
+			$(_CompileNativeExecutableDependsOn);
+			IlcCompile;
+		</_CompileNativeExecutableDependsOn>
 	</PropertyGroup>
 
 	<Target Name="_CompileNativeExecutable"

From 00b2865f0d39dd16d613096aa31eae8fa8eeb70c Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:54 +0200
Subject: [PATCH 24/46] [dotnet] Adjust ILC's build dependencies to cope with
 the fact that ILC doesn't support executing after ILLink.

Currently, NativeAOT is implemented as a replacement (of sorts) for ILLink. However,
we need to execute both, and in order to do that, we force our own logic to execute
to determine what ILC does.

This might be improved in the future. Ref: https://github.com/dotnet/runtime/issues/87187.
---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index 4a1d45b61ce6..45bb64bd6380 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -443,6 +443,10 @@
 		</_ComputeLinkerArgumentsDependsOn>
 	</PropertyGroup>
 
+	<PropertyGroup Condition="'$(PublishAot)' == 'true'">
+		<IlcCompileDependsOn>Compile;_ComputeLinkerArguments;_ComputeManagedAssemblyToLink;SetupOSSpecificProps;PrepareForILLink;_XamarinComputeIlcCompileInputs</IlcCompileDependsOn>
+	</PropertyGroup>
+
 	<Target Name="_ComputeLinkerFeatures">
 		<PropertyGroup Condition="'$(PublishAot)' == 'true'">
 			<!-- The one and only registrar is 'managed-static' when using NativeAOT -->
@@ -1166,6 +1170,13 @@
 		</ItemGroup>
 	</Target>
 
+	<Target Name="_XamarinComputeIlcCompileInputs">
+		<PropertyGroup>
+			<!-- Ask ILC to produce a static library -->
+			<NativeLib>static</NativeLib>
+		</PropertyGroup>
+	</Target>
+
 	<PropertyGroup>
 		<_GenerateBindingsDependsOn>
 			_ComputeBindingVariables;

From 8cfee8b599d204ae087088142d3fa26ab0cbf007 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:54 +0200
Subject: [PATCH 25/46] [dotnet] Ask ILC to treat all P/Invokes to __Internal
 as direct P/Invokes

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index 45bb64bd6380..d91f176d3f0b 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -1175,6 +1175,11 @@
 			<!-- Ask ILC to produce a static library -->
 			<NativeLib>static</NativeLib>
 		</PropertyGroup>
+
+		<ItemGroup>
+			<!-- We need to mark all __Internal P/Invokes as direct, so that the native linker doesn't remove them -->
+			<DirectPInvoke Include="__Internal" />
+		</ItemGroup>
 	</Target>
 
 	<PropertyGroup>

From 6bd8915d1aa49ce565ec13d5a28d2215dfa47713 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:54 +0200
Subject: [PATCH 26/46] [dotnet] Rearrange items in item groups so that ILC
 gets the output from ILLink

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index d91f176d3f0b..ebe549d3e725 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -1179,6 +1179,14 @@
 		<ItemGroup>
 			<!-- We need to mark all __Internal P/Invokes as direct, so that the native linker doesn't remove them -->
 			<DirectPInvoke Include="__Internal" />
+
+			<!-- Give ILLink's output to ILC -->
+			<_UpdatedManagedAssemblyToLink Include="@(ManagedAssemblyToLink->'$(IntermediateLinkDir)%(Filename)%(Extension)')" Condition="Exists('$(IntermediateLinkDir)%(Filename)%(Extension)')" />
+			<ManagedAssemblyToLink Remove="@(ManagedAssemblyToLink)" />
+			<ManagedAssemblyToLink Include="@(PrivateSdkAssemblies);@(_UpdatedManagedAssemblyToLink)" />
+			<ManagedBinary Include="$(IntermediateLinkDir)$(TargetName)$(TargetExt)" />
+			<IlcCompileInput Include="@(ManagedBinary)" />
+			<IlcReference Include="@(ManagedAssemblyToLink)" Exclude="@(ManagedBinary)" />
 		</ItemGroup>
 	</Target>
 

From 39774937bab4c367a69dd56e1da2c6f9df26a05d Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:55 +0200
Subject: [PATCH 27/46] [dotnet] Ask ILC to process all unmanaged callers only
 methods from all assemblies

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index ebe549d3e725..dd5e7023600f 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -1187,6 +1187,10 @@
 			<ManagedBinary Include="$(IntermediateLinkDir)$(TargetName)$(TargetExt)" />
 			<IlcCompileInput Include="@(ManagedBinary)" />
 			<IlcReference Include="@(ManagedAssemblyToLink)" Exclude="@(ManagedBinary)" />
+
+			<!-- Process UnmanagedCallersOnly attributes from every assembly -->
+			<UnmanagedEntryPointsAssembly Remove="System.Private.CoreLib" />
+			<UnmanagedEntryPointsAssembly Include="@(_UpdatedManagedAssemblyToLink->'%(Filename)')" />
 		</ItemGroup>
 	</Target>
 

From 79b76574c7f2440dd3474d84979a461950ce9ebc Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:55 +0200
Subject: [PATCH 28/46] [dotnet] Ask ILC to only trim assemblies if trimming is
 explicitly enabled

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index dd5e7023600f..57ad31cdd95d 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -1191,6 +1191,9 @@
 			<!-- Process UnmanagedCallersOnly attributes from every assembly -->
 			<UnmanagedEntryPointsAssembly Remove="System.Private.CoreLib" />
 			<UnmanagedEntryPointsAssembly Include="@(_UpdatedManagedAssemblyToLink->'%(Filename)')" />
+
+			<!-- Disable trimming by default (assemblies aren't trimmed unless they're marked IsTrimmable) -->
+			<IlcArg Include="--defaultrooting" />
 		</ItemGroup>
 	</Target>
 

From c48d5830258905f6ad65836035a02a458149e620 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:55 +0200
Subject: [PATCH 29/46] [dotnet] Link the output from ILC into the native
 executable

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index 57ad31cdd95d..73b0c327825b 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -1194,6 +1194,9 @@
 
 			<!-- Disable trimming by default (assemblies aren't trimmed unless they're marked IsTrimmable) -->
 			<IlcArg Include="--defaultrooting" />
+
+			<!-- Link in the output from ILC -->
+			<_NativeExecutableObjectFiles Include="$(NativeObject)" />
 		</ItemGroup>
 	</Target>
 

From 2ee532690af0dd41ac22accaa4b6338e2cb4bac6 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:55 +0200
Subject: [PATCH 30/46] [dotnet] Collect all the native linker arguments ILC
 would have used and use them ourselves.

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 44 +++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index 73b0c327825b..c002f95451a5 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -1198,6 +1198,50 @@
 			<!-- Link in the output from ILC -->
 			<_NativeExecutableObjectFiles Include="$(NativeObject)" />
 		</ItemGroup>
+
+		<!--
+
+			Collect all the native linker args ILC would have used and use
+			them ourselves when we link natively.
+
+			Unfortunately there's a major difference between LinkerArgs (as
+			used by ILC) and our _CustomLinkerFlags: ILC splits on space in
+			LinkerArg, while we quote (when necessary) the items in
+			_CustomLinkerFlags.
+
+			Example:
+
+				<LinkerArg Include="-framework UIKit" />
+
+					ILC will pass that as two separate arguments to the native
+					compiler
+
+				<_CustomLinkFlags Include="-framework UIKit" />
+
+					We'll pass that as a single argument ('-framework UIKit')
+					to the native compiler (which the native compiler doesn't
+					like)
+
+			So we need to convert the list of space-separated items in
+			LinkerArg to space-preserved items in _CustomLinkFlags.
+
+			How to do this in MSBuild is somewhat non-obvious: first we
+			convert the LinkerArg item group to a property where every item is
+			separated by a semi-colon, and where we've also replaced spaces by
+			semi-colons. This means we have a property where every flag we
+			want is separated by a semi-colon. Then we split on the property
+			string on a semi-colon and add those items to the _CustomLinkFlags
+			item group.
+
+			Note: this means ILC doesn't support linker flags with spaces in them.
+
+		-->
+		<PropertyGroup>
+			<_LinkerArgsSplitBySemiColon>@(LinkerArg->Replace(' ',';'))</_LinkerArgsSplitBySemiColon>
+		</PropertyGroup>
+		<ItemGroup>
+			<_CustomLinkFlags Include="$(_LinkerArgsSplitBySemiColon.Split(';'))" />
+		</ItemGroup>
 	</Target>
 
 	<PropertyGroup>

From 617f64e52d02ba6b1bc0a9afbdb066dbfc8c4cb8 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:56 +0200
Subject: [PATCH 31/46] [dotnet] Enforce that the linker must be enabled for
 all assemblies when using NativeAOT (and warn if someone asks otherwise).

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index c002f95451a5..0ab91ae96964 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -492,6 +492,9 @@
 
 		<Error Text="The only valid registrar when using NativeAOT is 'managed-static' (current value: '$(Registrar)'). Please either delete the 'Registrar' property, or change it to be 'managed-static'." Condition="'$(PublishAot)' == 'true' And '$(Registrar)' != '' And '$(Registrar)' != 'managed-static'" />
 
+		<Warning Text="Only the managed static registrar is supported when using NativeAOT." Condition="'$(PublishAot)' == 'true' And '$(Registrar)' != 'managed-static'" />
+		<Warning Text="All assemblies must be processed by the linker when using NativeAOT. Please don't set neither the '$(_LinkModeProperty)' nor the 'TrimMode' property, so that the build can default to linking all assemblies." Condition="'$(PublishAot)' == 'true' And '$(_LinkMode)' != 'Full'" />
+
 		<PropertyGroup>
 			<!-- Pass the custom options to our custom steps -->
 			<_CustomLinkerOptionsFile>$([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)custom-linker-options.txt'))</_CustomLinkerOptionsFile>
@@ -1506,11 +1509,12 @@
 			<_DefaultLinkMode>TrimMode</_DefaultLinkMode>
 		</PropertyGroup>
 		<PropertyGroup Condition="'$(TrimMode)' == ''">
-			<_DefaultLinkMode Condition="'$(_PlatformName)' == 'macOS'">None</_DefaultLinkMode> <!-- Linking is off by default for macOS apps -->
-			<_DefaultLinkMode Condition="'$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' == 'Release'">SdkOnly</_DefaultLinkMode> <!-- Default linking is on for release builds for Mac Catalyst apps -->
-			<_DefaultLinkMode Condition="'$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' != 'Release'">None</_DefaultLinkMode> <!-- Default linking is off for non-release builds for Mac Catalyst apps -->
-			<_DefaultLinkMode Condition="'$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' == 'true'">None</_DefaultLinkMode> <!-- Linking is off by default in the simulator -->
-			<_DefaultLinkMode Condition="'$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' != 'true'">SdkOnly</_DefaultLinkMode> <!-- Linking is SdkOnly for iOS/tvOS/watchOS apps on device -->
+			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true'">Full</_DefaultLinkMode> <!-- Linking is always on for all assemblies when using NativeAOT - this is because we need to modify all assemblies in the linker for them to be compatible with NativeAOT -->
+			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'macOS'">None</_DefaultLinkMode> <!-- Linking is off by default for macOS apps -->
+			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' == 'Release'">SdkOnly</_DefaultLinkMode> <!-- Default linking is on for release builds for Mac Catalyst apps -->
+			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' != 'Release'">None</_DefaultLinkMode> <!-- Default linking is off for non-release builds for Mac Catalyst apps -->
+			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' == 'true'">None</_DefaultLinkMode> <!-- Linking is off by default in the simulator -->
+			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' != 'true'">SdkOnly</_DefaultLinkMode> <!-- Linking is SdkOnly for iOS/tvOS/watchOS apps on device -->
 		</PropertyGroup>
 	</Target>
 	<PropertyGroup>

From d601e516983fd3d6562abab6237fbfdb8211fdbf Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:56 +0200
Subject: [PATCH 32/46] [dotnet] Set PublishAotUsingRuntimePack=true when using
 NativeAOT to get the correct BCL libraries.

---
 dotnet/targets/Xamarin.Shared.Sdk.props | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.props b/dotnet/targets/Xamarin.Shared.Sdk.props
index a92e4f0af15a..95c5ddb936d1 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.props
+++ b/dotnet/targets/Xamarin.Shared.Sdk.props
@@ -120,5 +120,8 @@
 
 		<!-- We're using our own native main function when using NativeAOT -->
 		<CustomNativeMain>true</CustomNativeMain>
+
+		<!-- We must find the BCL libraries using the runtime pack instead of using the built-in NativeAOT BCL -->
+		<PublishAotUsingRuntimePack>true</PublishAotUsingRuntimePack>
 	</PropertyGroup>
 </Project>

From 183c76af4046ca90cff356e02568df97611be396 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:56 +0200
Subject: [PATCH 33/46] [dotnet] Use a different min OS version when building
 with NativeAOT.

This is because NativeAOT contains swift code, and we'd have to add code to
embed the Swift libraries in any apps that target early OS versions. We could
eventually implement this, but let's wait and see if there's a demand first.
---
 Make.config                             |  6 ++++++
 dotnet/generate-target-platforms.csharp | 20 ++++++++++++++++----
 2 files changed, 22 insertions(+), 4 deletions(-)

diff --git a/Make.config b/Make.config
index 453328678981..2c2747c4950e 100644
--- a/Make.config
+++ b/Make.config
@@ -273,6 +273,12 @@ DOTNET_MIN_TVOS_SDK_VERSION=11.0
 DOTNET_MIN_MACCATALYST_SDK_VERSION=13.1
 DOTNET_MIN_MACOS_SDK_VERSION=10.15
 
+# Minimum OS versions when using NativeOAT - these are at least the general min versions above (but may be higher).
+DOTNET_MIN_NATIVEAOT_IOS_SDK_VERSION=12.2
+DOTNET_MIN_NATIVEAOT_TVOS_SDK_VERSION=12.2
+DOTNET_MIN_NATIVEAOT_MACCATALYST_SDK_VERSION=13.1
+DOTNET_MIN_NATIVEAOT_MACOS_SDK_VERSION=10.15
+
 # The min simulator version available in the Xcode we're using
 MIN_IOS_SIMULATOR_VERSION=13.7
 MIN_WATCHOS_SIMULATOR_VERSION=7.0
diff --git a/dotnet/generate-target-platforms.csharp b/dotnet/generate-target-platforms.csharp
index ddd6a5a0aa1a..f44815e74a7b 100755
--- a/dotnet/generate-target-platforms.csharp
+++ b/dotnet/generate-target-platforms.csharp
@@ -24,10 +24,16 @@ var doc = new XmlDocument ();
 doc.Load (plistPath);
 var nodes = doc.SelectNodes ($"/plist/dict/key[text()='KnownVersions']/following-sibling::dict[1]/key[text()='{platform}']/following-sibling::array[1]/string");
 
+var allLines = File.ReadAllLines ("../Make.config");
+
 var minSdkVersionName = $"DOTNET_MIN_{platform.ToUpper ()}_SDK_VERSION";
-var minSdkVersionString = File.ReadAllLines ("../Make.config").Single (v => v.StartsWith (minSdkVersionName + "=", StringComparison.Ordinal)).Substring (minSdkVersionName.Length + 1);
+var minSdkVersionString = allLines.Single (v => v.StartsWith (minSdkVersionName + "=", StringComparison.Ordinal)).Substring (minSdkVersionName.Length + 1);
 var minSdkVersion = Version.Parse (minSdkVersionString);
 
+var minNativeAotSdkVersionName = $"DOTNET_MIN_NATIVEAOT_{platform.ToUpper ()}_SDK_VERSION";
+var minNativeAotSdkVersionString = allLines.Single (v => v.StartsWith (minNativeAotSdkVersionName + "=", StringComparison.Ordinal)).Substring (minNativeAotSdkVersionName.Length + 1);
+var minNativeAotSdkVersion = Version.Parse (minNativeAotSdkVersionString);
+
 using (TextWriter writer = new StreamWriter (outputPath)) {
 	writer.WriteLine ($"<!-- This file contains a generated list of the {platform} platform versions that are supported for this SDK -->");
 	writer.WriteLine ($"<!-- Generation script: https://github.com/xamarin/xamarin-macios/blob/main/dotnet/generate-target-platforms.csharp -->");
@@ -36,9 +42,14 @@ using (TextWriter writer = new StreamWriter (outputPath)) {
 
 	foreach (XmlNode n in nodes) {
 		var version = n.InnerText;
-		if (Version.Parse (version) < minSdkVersion)
+		var parsedVersion = Version.Parse (version);
+		if (parsedVersion < minSdkVersion)
 			continue;
-		writer.WriteLine ($"\t\t<{platform}SdkSupportedTargetPlatformVersion Include=\"{n.InnerText}\" />");
+		if (parsedVersion < minNativeAotSdkVersion) {
+			writer.WriteLine ($"\t\t<{platform}SdkSupportedTargetPlatformVersion Include=\"{n.InnerText}\" Condition=\"'$(PublishAot)' != 'true'\" />");
+		} else {
+			writer.WriteLine ($"\t\t<{platform}SdkSupportedTargetPlatformVersion Include=\"{n.InnerText}\" />");
+		}
 	}
 
 	writer.WriteLine ("\t</ItemGroup>");
@@ -46,7 +57,8 @@ using (TextWriter writer = new StreamWriter (outputPath)) {
 	writer.WriteLine ($"\t\t<SdkSupportedTargetPlatformVersion Condition=\"'$(TargetPlatformIdentifier)' == '{platform}'\" Include=\"@({platform}SdkSupportedTargetPlatformVersion)\" />");
 	writer.WriteLine ("\t</ItemGroup>");
 	writer.WriteLine ("\t<PropertyGroup>");
-	writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion>{minSdkVersionString}</{platform}MinSupportedOSPlatformVersion>");
+	writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion Condition=\"'$(PublishAot)' != 'true'\">{minSdkVersionString}</{platform}MinSupportedOSPlatformVersion>");
+	writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion Condition=\"'$(PublishAot)' == 'true'\">{minNativeAotSdkVersionString}</{platform}MinSupportedOSPlatformVersion>");
 	writer.WriteLine ("\t</PropertyGroup>");
 	writer.WriteLine ("</Project>");
 }

From e3228d04eaf79a128979b6e7c37de7ac838f3e19 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:56 +0200
Subject: [PATCH 34/46] [dotnet] Turn off some publishing behavior we don't
 need

---
 dotnet/targets/Xamarin.Shared.Sdk.props | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.props b/dotnet/targets/Xamarin.Shared.Sdk.props
index 95c5ddb936d1..2217f22a157e 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.props
+++ b/dotnet/targets/Xamarin.Shared.Sdk.props
@@ -123,5 +123,8 @@
 
 		<!-- We must find the BCL libraries using the runtime pack instead of using the built-in NativeAOT BCL -->
 		<PublishAotUsingRuntimePack>true</PublishAotUsingRuntimePack>
+
+		<!-- This turns off some NativeAOT logic we don't want nor need -->
+		<NativeCompilationDuringPublish>false</NativeCompilationDuringPublish>
 	</PropertyGroup>
 </Project>

From a1d707c0134aa3a967db36fcdc25b16c34bb597b Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:57 +0200
Subject: [PATCH 35/46] [dotnet] Fix items in TrimmerRootAssembly to follow
 docs and what ILC supports.

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index 0ab91ae96964..b0d378fb5907 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -1202,6 +1202,28 @@
 			<_NativeExecutableObjectFiles Include="$(NativeObject)" />
 		</ItemGroup>
 
+		<ItemGroup>
+			<!--
+
+				We need to adjust TrimmerRootAssembly, because ILLink sets it
+				to @(IntermediateAssembly), but for ILC it must be the output
+				from ILLink and not its input.
+
+				Here we first create the intersection of TrimmerRootAssembly
+				and IntermediateAssembly (so that we only add the fixed
+				versions of IntermediateAssembly to TrimmerRootAssembly if
+				it's already there in the first place), then we remove it from
+				TrimmerRootAssembly, before adding the fixed version back.
+
+				Note that we only need the filename in TrimmerRootAssembly,
+				not the full path.
+
+			-->
+			<_TrimmerRootAssemblyButOnlyIntermediateAssembly Include="@(TrimmerRootAssembly)" Condition="'@(TrimmerRootAssembly)' == '@(IntermediateAssembly)' And '%(Identity)' != ''" />
+			<TrimmerRootAssembly Remove="@(_TrimmerRootAssemblyButOnlyIntermediateAssembly)" />
+			<TrimmerRootAssembly Include="@(_TrimmerRootAssemblyButOnlyIntermediateAssembly->'%(Filename)')" />
+		</ItemGroup>
+
 		<!--
 
 			Collect all the native linker args ILC would have used and use

From 0adbf77643dd9c9a1c8f74d69a0803df5ecea8c7 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:57 +0200
Subject: [PATCH 36/46] [tests] Fix computing when the dynamic registrar is
 used.

---
 tests/ComputeRegistrarConstant.targets | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/tests/ComputeRegistrarConstant.targets b/tests/ComputeRegistrarConstant.targets
index 6e6c743e890e..9d5d2e9dcaf5 100644
--- a/tests/ComputeRegistrarConstant.targets
+++ b/tests/ComputeRegistrarConstant.targets
@@ -1,12 +1,12 @@
 <?xml version="1.0" encoding="utf-8"?>
 <Project>
 	<Target Name="ComputeRegistrarConstant" BeforeTargets="BeforeBuild">
-		<PropertyGroup Condition="'$(_PlatformName)' == 'iOS' Or $(TargetFramework.EndsWith('-ios')) Or '$(_PlatformName)' == 'tvOS' Or $(TargetFramework.EndsWith('-tvos'))">
+		<PropertyGroup Condition="('$(_PlatformName)' == 'iOS' Or $(TargetFramework.EndsWith('-ios')) Or '$(_PlatformName)' == 'tvOS' Or $(TargetFramework.EndsWith('-tvos'))) And '$(_UseNativeAot)' != 'true'">
 			<IsDynamicRegistrar Condition="'$(ComputedPlatform)' == 'iPhoneSimulator' And '$(Registrar)' == ''">true</IsDynamicRegistrar>
 			<IsDynamicRegistrar Condition="'$(Registrar)' == 'dynamic'">true</IsDynamicRegistrar>
 		</PropertyGroup>
 
-		<PropertyGroup Condition="'$(_PlatformName)' == 'macOS' Or $(TargetFramework.EndsWith('-macos')) Or '$(_PlatformName)' == 'MacCatalyst' Or $(TargetFramework.EndsWith('-maccatalyst'))">
+		<PropertyGroup Condition="('$(_PlatformName)' == 'macOS' Or $(TargetFramework.EndsWith('-macos')) Or '$(_PlatformName)' == 'MacCatalyst' Or $(TargetFramework.EndsWith('-maccatalyst'))) And '$(_UseNativeAot)' != 'true'">
 			<IsDynamicRegistrar Condition="'$(Configuration)' == 'Debug' And '$(Registrar)' == ''">true</IsDynamicRegistrar>
 			<IsDynamicRegistrar Condition="'$(Registrar)' == 'dynamic'">true</IsDynamicRegistrar>
 		</PropertyGroup>

From 7d65804e326ce66114137b580ea754d729571c58 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:57 +0200
Subject: [PATCH 37/46] [dotnet/tests] Only use NativeAOT when publishing.

This matches how NativeAOT works for other platforms.
---
 dotnet/generate-target-platforms.csharp       |  6 ++--
 .../Xamarin.Shared.Sdk.DefaultItems.targets   | 10 +++++-
 dotnet/targets/Xamarin.Shared.Sdk.props       |  2 +-
 dotnet/targets/Xamarin.Shared.Sdk.targets     | 34 +++++++++----------
 .../xharness/Jenkins/TestVariationsFactory.cs |  4 ++-
 5 files changed, 33 insertions(+), 23 deletions(-)

diff --git a/dotnet/generate-target-platforms.csharp b/dotnet/generate-target-platforms.csharp
index f44815e74a7b..9e0a1b82628f 100755
--- a/dotnet/generate-target-platforms.csharp
+++ b/dotnet/generate-target-platforms.csharp
@@ -46,7 +46,7 @@ using (TextWriter writer = new StreamWriter (outputPath)) {
 		if (parsedVersion < minSdkVersion)
 			continue;
 		if (parsedVersion < minNativeAotSdkVersion) {
-			writer.WriteLine ($"\t\t<{platform}SdkSupportedTargetPlatformVersion Include=\"{n.InnerText}\" Condition=\"'$(PublishAot)' != 'true'\" />");
+			writer.WriteLine ($"\t\t<{platform}SdkSupportedTargetPlatformVersion Include=\"{n.InnerText}\" Condition=\"!('$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true')\" />");
 		} else {
 			writer.WriteLine ($"\t\t<{platform}SdkSupportedTargetPlatformVersion Include=\"{n.InnerText}\" />");
 		}
@@ -57,8 +57,8 @@ using (TextWriter writer = new StreamWriter (outputPath)) {
 	writer.WriteLine ($"\t\t<SdkSupportedTargetPlatformVersion Condition=\"'$(TargetPlatformIdentifier)' == '{platform}'\" Include=\"@({platform}SdkSupportedTargetPlatformVersion)\" />");
 	writer.WriteLine ("\t</ItemGroup>");
 	writer.WriteLine ("\t<PropertyGroup>");
-	writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion Condition=\"'$(PublishAot)' != 'true'\">{minSdkVersionString}</{platform}MinSupportedOSPlatformVersion>");
-	writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion Condition=\"'$(PublishAot)' == 'true'\">{minNativeAotSdkVersionString}</{platform}MinSupportedOSPlatformVersion>");
+	writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion Condition=\"!('$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true')\">{minSdkVersionString}</{platform}MinSupportedOSPlatformVersion>");
+	writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion Condition=\"'$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true'\">{minNativeAotSdkVersionString}</{platform}MinSupportedOSPlatformVersion>");
 	writer.WriteLine ("\t</PropertyGroup>");
 	writer.WriteLine ("</Project>");
 }
diff --git a/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets b/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets
index 0b41c3a8fdf3..c13dc5def78a 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.DefaultItems.targets
@@ -11,9 +11,17 @@
     <EnableDefaultmacOSItems Condition=" '$(_PlatformName)' == 'macOS' And '$(EnableDefaultmacOSItems)' == '' ">$(EnableDefaultItems)</EnableDefaultmacOSItems>
     <EnableDefaultMacCatalystItems Condition=" '$(_PlatformName)' == 'MacCatalyst' And '$(EnableDefaultMacCatalystItems)' == '' ">$(EnableDefaultItems)</EnableDefaultMacCatalystItems>
 
+    <!--
+        PublishAot should only take effect when doing 'dotnet publish', not when doing 'dotnet build'. We distinguish these cases using the '_IsPublishing' property,
+        but it's rather annoying to always have to check both PublishAot and _IsPublishing to see if we're using NativeAOT, so introduce a third property that's
+        only set to true if both PublishAot=true and _IsPublishing=true
+    -->
+    <_UseNativeAot Condition="'$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true'">true</_UseNativeAot>
+
     <UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' And '$(_PlatformName)' == 'macOS'">false</UseMonoRuntime>
-    <UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' And '$(PublishAot)' == 'true'">false</UseMonoRuntime>
+    <UseMonoRuntime Condition=" '$(UseMonoRuntime)' == '' And '$(_UseNativeAot)' == 'true'">false</UseMonoRuntime>
     <UseMonoRuntime Condition=" '$(UseMonoRuntime)' == ''">true</UseMonoRuntime>
+
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/dotnet/targets/Xamarin.Shared.Sdk.props b/dotnet/targets/Xamarin.Shared.Sdk.props
index 2217f22a157e..87d7b777b60b 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.props
+++ b/dotnet/targets/Xamarin.Shared.Sdk.props
@@ -114,7 +114,7 @@
 	</PropertyGroup>
 
 	<!-- Various options when using NativeAOT -->
-	<PropertyGroup Condition="'$(PublishAot)' == 'true'">
+	<PropertyGroup Condition="'$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true'">
 		<!-- Disable our own assembly IL stripping logic, because ILC does that already -->
 		<EnableAssemblyILStripping>false</EnableAssemblyILStripping>
 
diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index b0d378fb5907..a214d43dae3f 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -425,7 +425,7 @@
 			_ComputeFrameworkVariables;
 			_ComputeFrameworkAssemblies;
 		</_ComputeLinkerArgumentsDependsOn>
-		<_ComputeLinkerArgumentsDependsOn Condition="'$(PublishAot)' != 'true'">
+		<_ComputeLinkerArgumentsDependsOn Condition="'$(_UseNativeAot)' != 'true'">
 			$(_ComputeLinkerArgumentsDependsOn);
 			ComputeResolvedFilesToPublishList;
 		</_ComputeLinkerArgumentsDependsOn>
@@ -443,12 +443,12 @@
 		</_ComputeLinkerArgumentsDependsOn>
 	</PropertyGroup>
 
-	<PropertyGroup Condition="'$(PublishAot)' == 'true'">
+	<PropertyGroup Condition="'$(_UseNativeAot)' == 'true'">
 		<IlcCompileDependsOn>Compile;_ComputeLinkerArguments;_ComputeManagedAssemblyToLink;SetupOSSpecificProps;PrepareForILLink;_XamarinComputeIlcCompileInputs</IlcCompileDependsOn>
 	</PropertyGroup>
 
 	<Target Name="_ComputeLinkerFeatures">
-		<PropertyGroup Condition="'$(PublishAot)' == 'true'">
+		<PropertyGroup Condition="'$(_UseNativeAot)' == 'true'">
 			<!-- The one and only registrar is 'managed-static' when using NativeAOT -->
 			<Registrar Condition="'$(Registrar)' == ''">managed-static</Registrar>
 
@@ -490,10 +490,10 @@
 		<!-- it's invariant or it's one of the ICU data files, not both -->
 		<Error Text="Can not set values for both InvariantGlobalization '$(InvariantGlobalization)' and _GlobalizationDataFile '$(_GlobalizationDataFile)'" Condition="'$(_GlobalizationDataFile)' != '' And '$(InvariantGlobalization)' == 'true'" />
 
-		<Error Text="The only valid registrar when using NativeAOT is 'managed-static' (current value: '$(Registrar)'). Please either delete the 'Registrar' property, or change it to be 'managed-static'." Condition="'$(PublishAot)' == 'true' And '$(Registrar)' != '' And '$(Registrar)' != 'managed-static'" />
+		<Error Text="The only valid registrar when using NativeAOT is 'managed-static' (current value: '$(Registrar)'). Please either delete the 'Registrar' property, or change it to be 'managed-static'." Condition="'$(_UseNativeAot)' == 'true' And '$(Registrar)' != '' And '$(Registrar)' != 'managed-static'" />
 
-		<Warning Text="Only the managed static registrar is supported when using NativeAOT." Condition="'$(PublishAot)' == 'true' And '$(Registrar)' != 'managed-static'" />
-		<Warning Text="All assemblies must be processed by the linker when using NativeAOT. Please don't set neither the '$(_LinkModeProperty)' nor the 'TrimMode' property, so that the build can default to linking all assemblies." Condition="'$(PublishAot)' == 'true' And '$(_LinkMode)' != 'Full'" />
+		<Warning Text="Only the managed static registrar is supported when using NativeAOT." Condition="'$(_UseNativeAot)' == 'true' And '$(Registrar)' != 'managed-static'" />
+		<Warning Text="All assemblies must be processed by the linker when using NativeAOT. Please don't set neither the '$(_LinkModeProperty)' nor the 'TrimMode' property, so that the build can default to linking all assemblies." Condition="'$(_UseNativeAot)' == 'true' And '$(_LinkMode)' != 'Full'" />
 
 		<PropertyGroup>
 			<!-- Pass the custom options to our custom steps -->
@@ -895,8 +895,8 @@
 	<Target Name="_ComputeFrameworkVariables" DependsOnTargets="ResolveRuntimePackAssets;ResolveFrameworkReferences">
 		<PropertyGroup>
 			<_XamarinRuntime Condition="'$(UseMonoRuntime)' == 'true'">MonoVM</_XamarinRuntime>
-			<_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(PublishAot)' != 'true'">CoreCLR</_XamarinRuntime>
-			<_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(PublishAot)' == 'true'">NativeAOT</_XamarinRuntime>
+			<_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(_UseNativeAot)' != 'true'">CoreCLR</_XamarinRuntime>
+			<_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(_UseNativeAot)' == 'true'">NativeAOT</_XamarinRuntime>
 
 			<_PackageIdInfix Condition="'$(_XamarinRuntime)' == 'MonoVM'">Mono.</_PackageIdInfix>
 			<_PackageIdInfix Condition="'$(_XamarinRuntime)' == 'NativeAOT'">NativeAOT.</_PackageIdInfix>
@@ -948,7 +948,7 @@
 			publish (except the merged app bundle, which we'll handle
 			ourselves).
 		-->
-		<_ComputeVariablesDependsOn Condition="'$(RuntimeIdentifiers)' == '' And '$(PublishAot)' != 'true'">$(_ComputeVariablesDependsOn);ComputeResolvedFilesToPublishList</_ComputeVariablesDependsOn>
+		<_ComputeVariablesDependsOn Condition="'$(RuntimeIdentifiers)' == '' And '$(_UseNativeAot)' != 'true'">$(_ComputeVariablesDependsOn);ComputeResolvedFilesToPublishList</_ComputeVariablesDependsOn>
 	</PropertyGroup>
 
 	<Target Name="_ComputeVariables" DependsOnTargets="$(_ComputeVariablesDependsOn)">
@@ -957,7 +957,7 @@
 			<_RunAotCompiler>false</_RunAotCompiler>
 		</PropertyGroup>
 		<!-- We don't run Mono's AOT compiler if we're using NativeAOT -->
-		<PropertyGroup Condition="'$(PublishAot)' != 'true'" >
+		<PropertyGroup Condition="'$(_UseNativeAot)' != 'true'" >
 			<!-- We need it for device builds for mobile platforms -->
 			<_RunAotCompiler Condition="'$(_SdkIsSimulator)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst'">true</_RunAotCompiler>
 			<!-- We need it if the interpreter is enabled, no matter where -->
@@ -1314,7 +1314,7 @@
 			_AOTCompile;
 		</_CompileNativeExecutableDependsOn>
 
-		<_CompileNativeExecutableDependsOn Condition="'$(PublishAot)' == 'true'">
+		<_CompileNativeExecutableDependsOn Condition="'$(_UseNativeAot)' == 'true'">
 			$(_CompileNativeExecutableDependsOn);
 			IlcCompile;
 		</_CompileNativeExecutableDependsOn>
@@ -1531,12 +1531,12 @@
 			<_DefaultLinkMode>TrimMode</_DefaultLinkMode>
 		</PropertyGroup>
 		<PropertyGroup Condition="'$(TrimMode)' == ''">
-			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true'">Full</_DefaultLinkMode> <!-- Linking is always on for all assemblies when using NativeAOT - this is because we need to modify all assemblies in the linker for them to be compatible with NativeAOT -->
-			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'macOS'">None</_DefaultLinkMode> <!-- Linking is off by default for macOS apps -->
-			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' == 'Release'">SdkOnly</_DefaultLinkMode> <!-- Default linking is on for release builds for Mac Catalyst apps -->
-			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' != 'Release'">None</_DefaultLinkMode> <!-- Default linking is off for non-release builds for Mac Catalyst apps -->
-			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' == 'true'">None</_DefaultLinkMode> <!-- Linking is off by default in the simulator -->
-			<_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' != 'true'">SdkOnly</_DefaultLinkMode> <!-- Linking is SdkOnly for iOS/tvOS/watchOS apps on device -->
+			<_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true'">Full</_DefaultLinkMode> <!-- Linking is always on for all assemblies when using NativeAOT - this is because we need to modify all assemblies in the linker for them to be compatible with NativeAOT -->
+			<_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true' And '$(_PlatformName)' == 'macOS'">None</_DefaultLinkMode> <!-- Linking is off by default for macOS apps -->
+			<_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' == 'Release'">SdkOnly</_DefaultLinkMode> <!-- Default linking is on for release builds for Mac Catalyst apps -->
+			<_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' != 'Release'">None</_DefaultLinkMode> <!-- Default linking is off for non-release builds for Mac Catalyst apps -->
+			<_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' == 'true'">None</_DefaultLinkMode> <!-- Linking is off by default in the simulator -->
+			<_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' != 'true'">SdkOnly</_DefaultLinkMode> <!-- Linking is SdkOnly for iOS/tvOS/watchOS apps on device -->
 		</PropertyGroup>
 	</Target>
 	<PropertyGroup>
diff --git a/tests/xharness/Jenkins/TestVariationsFactory.cs b/tests/xharness/Jenkins/TestVariationsFactory.cs
index 47b6d61a9606..56318ec238ad 100644
--- a/tests/xharness/Jenkins/TestVariationsFactory.cs
+++ b/tests/xharness/Jenkins/TestVariationsFactory.cs
@@ -296,8 +296,10 @@ public IEnumerable<T> CreateTestVariations<T> (IEnumerable<T> tests, Func<MSBuil
 							clone.Xml.SetProperty ("RuntimeIdentifier", runtime_identifer);
 						if (!string.IsNullOrEmpty (registrar))
 							clone.Xml.SetProperty ("Registrar", registrar);
-						if (publishaot)
+						if (publishaot) {
 							clone.Xml.SetProperty ("PublishAot", "true");
+							clone.Xml.SetProperty ("_IsPublishing", "true"); // quack like "dotnet publish", otherwise PublishAot=true has no effect.
+						}
 						clone.Xml.Save (clone.Path);
 					});
 

From 97b91f16002d5b0d7844793681a8ba5f129d85ba Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:57 +0200
Subject: [PATCH 38/46] [dotnet] Remove libSystem.Net.Security.Native from tvOS
 builds when using NativeAOT.

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index a214d43dae3f..469e14bdc97e 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -1179,6 +1179,14 @@
 			<NativeLib>static</NativeLib>
 		</PropertyGroup>
 
+		<!-- Remove libSystem.Net.Security.Native.a from tvOS when using NativeAOT, it's not shipped on tvOS -->
+		<ItemGroup>
+			<DirectPInvoke Remove="libSystem.Net.Security.Native" />
+			<NetCoreAppNativeLibrary Remove="System.Net.Security.Native" />
+			<NativeLibrary Remove="@(NativeLibrary)" Condition="'%(Filename)' == 'libSystem.Net.Security.Native'" />
+			<LinkerArg Remove="@(LinkerArg)" Condition="'%(Filename)' == 'libSystem.Net.Security.Native'" />
+		</ItemGroup>
+
 		<ItemGroup>
 			<!-- We need to mark all __Internal P/Invokes as direct, so that the native linker doesn't remove them -->
 			<DirectPInvoke Include="__Internal" />

From c49888bee16b81168c232d7f5e75248f7a9a1fa8 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:58 +0200
Subject: [PATCH 39/46] [tests] Adjust ConfigTest to cope with different
 behavior when using NativeAOT.

---
 tests/monotouch-test/mono/ConfigTest.cs | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/tests/monotouch-test/mono/ConfigTest.cs b/tests/monotouch-test/mono/ConfigTest.cs
index 36a554f1151d..32e7fd682ee8 100644
--- a/tests/monotouch-test/mono/ConfigTest.cs
+++ b/tests/monotouch-test/mono/ConfigTest.cs
@@ -13,8 +13,17 @@ public partial class ConfigTest {
 		[Test]
 		public void Existence ()
 		{
+#if NATIVEAOT
+#if __MACCATALYST__ || __MACOS__
+			var config_dir = Path.Combine (Path.GetDirectoryName (AppContext.BaseDirectory.TrimEnd ('/')), "MonoBundle");
+#else
+			var config_dir = AppContext.BaseDirectory;
+#endif
+			var config_file = Path.Combine (config_dir, Assembly.GetExecutingAssembly ().GetName ().Name + ".dll.config");
+#else
 			var config_file = Assembly.GetExecutingAssembly ().Location + ".config";
-			Assert.True (File.Exists (config_file), "existence");
+#endif
+			Assert.That (config_file, Does.Exist, "existence");
 			Assert.That (File.ReadAllText (config_file), Contains.Substring ("<secretMessage>Xamarin rocks</secretMessage>"), "content");
 		}
 	}

From 264be7055e0c83d14e9ff8509c28c151d05f070a Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:58 +0200
Subject: [PATCH 40/46] [dotnet] Disable SelfContained for the outer build of a
 universal app build when using NativeAOT.

---
 dotnet/targets/Xamarin.Shared.Sdk.props | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.props b/dotnet/targets/Xamarin.Shared.Sdk.props
index 87d7b777b60b..f823bae323c2 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.props
+++ b/dotnet/targets/Xamarin.Shared.Sdk.props
@@ -102,6 +102,20 @@
 		<SelfContained>true</SelfContained>
 	</PropertyGroup>
 
+	<!--
+
+		SelfContained is automatically enabled if PublishAot is true, and that
+		doesn't work properly (restore fails because RuntimeIdentifier is not
+		set) when doing the outer build of a universal apps (when
+		RuntimeIdentifier=''), so manually disable SelfContained in that case.
+
+		This might not be necessary after: https://github.com/dotnet/sdk/pull/33229
+
+	-->
+	<PropertyGroup Condition="'$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true' And '$(RuntimeIdentifiers)' != '' And '$(RuntimeIdentifier)' == '' And '$(SelfContained)' == ''">
+		<SelfContained>false</SelfContained>
+	</PropertyGroup>
+
 	<!--
 		Enable LLVM by default for mobile release builds.
 

From 8ac35baf44ebc8ab681d1a8211989a35577c32cd Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:58 +0200
Subject: [PATCH 41/46] [tests] Disable the NUnitLite and Touch.Unit references
 for the .NET 7 tests.

We had to bump NUnitLite and Touch.Unit's TargetFramework properties to
net8.0-* (otherwise projects using NativeAOT fails if these projects are
referenced), which means they can't be used from .NET 7 (aka our .NET 7
tests).

So just don't reference NUnitLite and Touch.Unit in this test.
---
 tests/dotnet/Net7_0SimpleApp/shared.csproj | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tests/dotnet/Net7_0SimpleApp/shared.csproj b/tests/dotnet/Net7_0SimpleApp/shared.csproj
index cda1f92953a6..ccb12ab98835 100644
--- a/tests/dotnet/Net7_0SimpleApp/shared.csproj
+++ b/tests/dotnet/Net7_0SimpleApp/shared.csproj
@@ -6,6 +6,9 @@
 		<ApplicationTitle>MySimpleApp</ApplicationTitle>
 		<ApplicationId>com.xamarin.mysimpleapp</ApplicationId>
 		<ApplicationVersion>7.0</ApplicationVersion>
+
+		<ExcludeNUnitLiteReference>true</ExcludeNUnitLiteReference>
+		<ExcludeTouchUnitReference>true</ExcludeTouchUnitReference>
 	</PropertyGroup>
 
 	<Import Project="../../common/shared-dotnet.csproj" />

From e31b0a6dc407f1f78022bbe66ed9d5a7e2c9c3e4 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:58 +0200
Subject: [PATCH 42/46] [xharness] Disable NativeAOT test variations for macOS
 for now, we're waiting for a dotnet/runtime fix.

---
 tests/xharness/Jenkins/TestVariationsFactory.cs | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/tests/xharness/Jenkins/TestVariationsFactory.cs b/tests/xharness/Jenkins/TestVariationsFactory.cs
index 56318ec238ad..5f7e97588743 100644
--- a/tests/xharness/Jenkins/TestVariationsFactory.cs
+++ b/tests/xharness/Jenkins/TestVariationsFactory.cs
@@ -162,8 +162,9 @@ IEnumerable<TestData> GetTestData (RunTestTask test)
 						if (test.Platform != TestPlatform.MacCatalyst) {
 							yield return new TestData { Variation = "Debug (static registrar)", Registrar = "static", Debug = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.Mac), };
 							yield return new TestData { Variation = "Debug (static registrar, ARM64)", Registrar = "static", Debug = true, Profiling = false, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.Mac) || !mac_supports_arm64, RuntimeIdentifier = arm64_runtime_identifier, };
-							yield return new TestData { Variation = "Release (NativeAOT)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.Mac), Defines = "NATIVEAOT", LinkMode = "Full" };
-							yield return new TestData { Variation = "Release (NativeAOT, ARM64)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.Mac) || !mac_supports_arm64, Defines = "NATIVEAOT", RuntimeIdentifier = arm64_runtime_identifier, LinkMode = "Full" };
+							// Pending: We need the NativeAOT's runtime bits to ship using runtime packs for macOS (https://github.com/dotnet/runtime/issues/87060) before we can enable this
+							// yield return new TestData { Variation = "Release (NativeAOT)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.Mac), Defines = "NATIVEAOT", LinkMode = "Full" };
+							// yield return new TestData { Variation = "Release (NativeAOT, ARM64)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.Mac) || !mac_supports_arm64, Defines = "NATIVEAOT", RuntimeIdentifier = arm64_runtime_identifier, LinkMode = "Full" };
 						}
 						if (test.Platform == TestPlatform.MacCatalyst) {
 							yield return new TestData { Variation = "Release (ARM64, LLVM)", Debug = false, UseLlvm = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst) || !mac_supports_arm64, RuntimeIdentifier = arm64_runtime_identifier };

From 94cdec2f53d295e517b1cc947d35b197c56f63e1 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:59 +0200
Subject: [PATCH 43/46] [xharness] Disable NativeAOT test variations for Mac
 Catalyst for now, we need a few upstream fixes.

---
 tests/xharness/Jenkins/TestVariationsFactory.cs | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/tests/xharness/Jenkins/TestVariationsFactory.cs b/tests/xharness/Jenkins/TestVariationsFactory.cs
index 5f7e97588743..3ef390bdf80f 100644
--- a/tests/xharness/Jenkins/TestVariationsFactory.cs
+++ b/tests/xharness/Jenkins/TestVariationsFactory.cs
@@ -169,7 +169,12 @@ IEnumerable<TestData> GetTestData (RunTestTask test)
 						if (test.Platform == TestPlatform.MacCatalyst) {
 							yield return new TestData { Variation = "Release (ARM64, LLVM)", Debug = false, UseLlvm = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst) || !mac_supports_arm64, RuntimeIdentifier = arm64_runtime_identifier };
 							yield return new TestData { Variation = "Release", Debug = false, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst) };
-							yield return new TestData { Variation = "Release (NativeAOT)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst), Defines = "NATIVEAOT", LinkMode = "Full" };
+							// Pending: We need to skip this consistency check to support universal apps:
+							// https://github.com/dotnet/sdk/blob/f90e558092ac61038ffa1017fe3a5aca1af5ae7e/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets#L224-L226
+							// because the outer build has PublishAot=true and no RuntimeIdentifier set.
+							// Filed as https://github.com/dotnet/sdk/issues/33414.
+							// yield return new TestData { Variation = "Release (NativeAOT)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst), Defines = "NATIVEAOT", LinkMode = "Full" };
+
 							yield return new TestData { Variation = "Release (NativeAOT, ARM64)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst) || !mac_supports_arm64, Defines = "NATIVEAOT", RuntimeIdentifier = arm64_runtime_identifier, LinkMode = "Full" };
 							yield return new TestData { Variation = "Release (NativeAOT, x64)", Debug = false, PublishAot = true, Ignored = !jenkins.TestSelection.IsEnabled (TestLabel.Monotouch) || !jenkins.TestSelection.IsEnabled (PlatformLabel.MacCatalyst), Defines = "NATIVEAOT", LinkMode = "Full", RuntimeIdentifier = "maccatalyst-x64" };
 						}

From 42d6121e12b22517f4be550013c665ab91aef798 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:59 +0200
Subject: [PATCH 44/46] [dotnet] Set a flag to avoid a bug with the NativeAOT
 compiler

---
 dotnet/targets/Xamarin.Shared.Sdk.props | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.props b/dotnet/targets/Xamarin.Shared.Sdk.props
index f823bae323c2..050a40c1736d 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.props
+++ b/dotnet/targets/Xamarin.Shared.Sdk.props
@@ -140,5 +140,8 @@
 
 		<!-- This turns off some NativeAOT logic we don't want nor need -->
 		<NativeCompilationDuringPublish>false</NativeCompilationDuringPublish>
+
+		<!-- This works around an issue in NativeAOT: https://github.com/dotnet/runtime/issues/86186 -->
+		<IlcKeepManagedDebuggerSupport>true</IlcKeepManagedDebuggerSupport>
 	</PropertyGroup>
 </Project>

From 3c912d7aea88e0a8ee57229fac95875c6c48420f Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:49:59 +0200
Subject: [PATCH 45/46] [dotnet] Treat the ICU data file as a resource instead
 of an assembly.

We can fix this better once this fix reaches us:

    https://github.com/dotnet/runtime/pull/87813

because then we can set the ICU data file at build time (to a relative path).
---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 7 ++++++-
 runtime/runtime.m                         | 2 ++
 2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index 469e14bdc97e..681b62cb3e1a 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -153,6 +153,11 @@
 	<!-- Default item includes (globs and implicit references) -->
 	<Import Project="Xamarin.Shared.Sdk.DefaultItems.targets" />
 
+	<PropertyGroup Condition="'$(_GlobalizationDataFileLocation)' == ''">
+		<_GlobalizationDataFileLocation Condition="'$(_UseNativeAot)' == 'true'">Resource</_GlobalizationDataFileLocation>
+		<_GlobalizationDataFileLocation Condition="'$(_UseNativeAot)' != 'true'">Assembly</_GlobalizationDataFileLocation>
+	</PropertyGroup>
+
 	<!-- dotnet publish -->
 	<Import Project="Xamarin.Shared.Sdk.Publish.targets" />
 
@@ -1650,7 +1655,7 @@
 				            '%(ResolvedFileToPublish.Filename)%(ResolvedFileToPublish.Extension)' == '$(_GlobalizationDataFile)' And
 				            '%(ResolvedFileToPublish.NuGetPackageId)' == '$(_MonoNugetPackageId)'
 				            "
-				PublishFolderType="Assembly"
+				PublishFolderType="$(_GlobalizationDataFileLocation)"
 			/>
 
 			<!-- Remove the libxamarin-*.dylib files we don't want -->
diff --git a/runtime/runtime.m b/runtime/runtime.m
index 1c0e08f544a4..dfb9123876d3 100644
--- a/runtime/runtime.m
+++ b/runtime/runtime.m
@@ -2589,12 +2589,14 @@ -(void) xamarinSetFlags: (enum XamarinGCHandleFlags) flags;
 	int subtractPropertyCount = 0;
 
 	if (xamarin_icu_dat_file_name != NULL && *xamarin_icu_dat_file_name != 0) {
+#if !defined (NATIVEAOT)
 		char path [1024];
 		if (!xamarin_locate_app_resource (xamarin_icu_dat_file_name, path, sizeof (path))) {
 			LOG (PRODUCT ": Could not locate the ICU data file '%s' in the app bundle.\n", xamarin_icu_dat_file_name);
 		} else {
 			icu_dat_file_path = strdup (path);
 		}
+#endif // !defined (NATIVEAOT)
 	} else {
 		subtractPropertyCount++;
 	}

From b4e3361a10ce6856d77d6ee9c9df7460489eefe6 Mon Sep 17 00:00:00 2001
From: Rolf Bjarne Kvinge <rolf@xamarin.com>
Date: Wed, 21 Jun 2023 20:50:00 +0200
Subject: [PATCH 46/46] [dotnet] Tell ILC about any satellite assemblies.

---
 dotnet/targets/Xamarin.Shared.Sdk.targets | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/dotnet/targets/Xamarin.Shared.Sdk.targets b/dotnet/targets/Xamarin.Shared.Sdk.targets
index 681b62cb3e1a..d62eb17660e3 100644
--- a/dotnet/targets/Xamarin.Shared.Sdk.targets
+++ b/dotnet/targets/Xamarin.Shared.Sdk.targets
@@ -1280,6 +1280,13 @@
 		<ItemGroup>
 			<_CustomLinkFlags Include="$(_LinkerArgsSplitBySemiColon.Split(';'))" />
 		</ItemGroup>
+
+		<ItemGroup>
+			<IlcSatelliteAssembly Include="@(ResourceCopyLocalItems)" Condition="'%(ResourceCopyLocalItems.Culture)' != '' And '%(ResourceCopyLocalItems.Culture)' != 'neutral'" />
+			<IlcSatelliteAssembly Include="@(IntermediateSatelliteAssembliesWithTargetPath)" Condition="'%(IntermediateSatelliteAssembliesWithTargetPath.Culture)' != '' And '%(IntermediateSatelliteAssembliesWithTargetPath.Culture)' != 'neutral'" />
+			<!-- Culture is not set on ReferenceSatellitePaths items, so use DestinationSubDirectory instead -->
+			<IlcSatelliteAssembly Include="@(ReferenceSatellitePaths)" Condition="'%(ReferenceSatellitePaths.DestinationSubDirectory)' != ''" />
+		</ItemGroup>
 	</Target>
 
 	<PropertyGroup>