From d605221dcf0f17564e62c6cdb34703a7cef9017c Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 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 #include #include +#include #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 +#include +#include +#include +#include + +#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 + +#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 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 @@ $(EnableDefaultItems) $(EnableDefaultItems) - true false + false + true 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 Condition="'$(BuildSessionId)' != ''">$(IntermediateOutputPath)linker-cache - <_XamarinRuntime Condition="'$(UseMonoRuntime)' == 'true'">MonoVM - <_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true'">CoreCLR - $(TrimMode) copy @@ -853,7 +850,11 @@ - <_PackageIdInfix Condition="'$(UseMonoRuntime)' == 'true'">Mono. + <_XamarinRuntime Condition="'$(UseMonoRuntime)' == 'true'">MonoVM + <_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(PublishAot)' != 'true'">CoreCLR + <_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(PublishAot)' == 'true'">NativeAOT + + <_PackageIdInfix Condition="'$(_XamarinRuntime)' == 'MonoVM'">Mono. <_MonoNugetPackageId>Microsoft.NETCore.App.Runtime.$(_PackageIdInfix)$(RuntimeIdentifier) <_XamarinNugetPackageId>Microsoft.$(_PlatformName).Runtime.$(RuntimeIdentifier) @@ -871,8 +872,9 @@ <_XamarinRefAssemblyDirectory>$(_XamarinRefPackageDirectory)/ref/net8.0/ <_XamarinRefAssemblyPath>$(_XamarinRefAssemblyDirectory)$(_PlatformAssemblyName).dll - <_LibPartialStaticRegistrar Condition="'$(UseMonoRuntime)' == 'true'">$(_XamarinNativeLibraryDirectory)/Microsoft.$(_PlatformName).registrar.a - <_LibPartialStaticRegistrar Condition="'$(UseMonoRuntime)' != 'true'">$(_XamarinNativeLibraryDirectory)/Microsoft.$(_PlatformName).registrar.coreclr.a + <_LibPartialStaticRegistrar Condition="'$(_XamarinRuntime)' == 'MonoVM'">$(_XamarinNativeLibraryDirectory)/Microsoft.$(_PlatformName).registrar.a + <_LibPartialStaticRegistrar Condition="'$(_XamarinRuntime)' == 'CoreCLR'">$(_XamarinNativeLibraryDirectory)/Microsoft.$(_PlatformName).registrar.coreclr.a + <_LibPartialStaticRegistrar Condition="'$(_XamarinRuntime)' == 'NativeAOT'">$(_XamarinNativeLibraryDirectory)/Microsoft.$(_PlatformName).registrar.nativeaot.a <_MonoRuntimePackPath>%(_MonoFrameworkReference.RuntimePackPath)/runtimes/$(RuntimeIdentifier)/ @@ -952,7 +954,9 @@ <_LibXamarinLinkMode Condition="'$(_LibXamarinLinkMode)' == ''">static <_LibXamarinExtension Condition="'$(_LibXamarinLinkMode)' == 'dylib'">dylib <_LibXamarinExtension Condition="'$(_LibXamarinLinkMode)' == 'static'">a - <_LibXamarinRuntime Condition="'$(UseMonoRuntime)' != 'true'">-coreclr + <_LibXamarinRuntime Condition="'$(_XamarinRuntime)' == 'MonoVM'"> + <_LibXamarinRuntime Condition="'$(_XamarinRuntime)' == 'CoreCLR'">-coreclr + <_LibXamarinRuntime Condition="'$(_XamarinRuntime)' == 'NativeAOT'">-nativeaot <_LibXamarinDebug Condition="'$(_BundlerDebug)' == 'true'">-debug <_LibXamarinName Condition="'$(_LibXamarinName)' == ''">libxamarin-dotnet$(_LibXamarinRuntime)$(_LibXamarinDebug).$(_LibXamarinExtension) @@ -1528,7 +1532,7 @@ <_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 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 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 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 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 CreateTestVariations (IEnumerable tests, Func CreateTestVariations (IEnumerable tests, Func 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 @@ + + + managed-static + + <_CustomLinkerOptionsFile>$([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)custom-linker-options.txt')) From 607cc785555ce88a0d8896f178b07a2c63fc1ecd Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 <_PackageIdInfix Condition="'$(_XamarinRuntime)' == 'MonoVM'">Mono. + <_PackageIdInfix Condition="'$(_XamarinRuntime)' == 'NativeAOT'">NativeAOT. <_MonoNugetPackageId>Microsoft.NETCore.App.Runtime.$(_PackageIdInfix)$(RuntimeIdentifier) <_XamarinNugetPackageId>Microsoft.$(_PlatformName).Runtime.$(RuntimeIdentifier) From ca6f2e4d2eda3aec3af205996f4719ba3266433a Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 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 @@ <_RunAotCompiler>false + + + <_RunAotCompiler Condition="'$(_SdkIsSimulator)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst'">true From a3b466b89e56bb79166f5ed4e07e8771bbb45077 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 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 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 { } } + /// + /// Looks up a localized string similar to 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.. + /// + public static string MX2016 { + get { + return ResourceManager.GetString("MX2016", resourceCulture); + } + } + /// /// 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 @@ + + 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. + + Could not process XML description: {0} From ab8f928e4a67a48c94e8185a568d9d1975983425 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 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 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 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 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 Condition="'$(Registrar)' != 'managed-static'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsManagedStaticRegistrar false + + <_ExtraTrimmerArgs Condition="'$(_XamarinRuntime)' == 'NativeAOT'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsNativeAOT true + <_ExtraTrimmerArgs Condition="'$(_XamarinRuntime)' != 'NativeAOT'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsNativeAOT false + <_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --enable-serialization-discovery 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 @@ - + + + + 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 @@ - + + + + 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 @@ + + 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 @@ - + + + + From e0e4b77a55b6e7733367ed7ab9cf8477c31846ef Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ <_ExportSymbolsExplicitly Condition="'$(_ExportSymbolsExplicitly)' == ''">true + + + + true 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 @@ true false true - true + <_AggressiveAttributeTrimming Condition="'$(_AggressiveAttributeTrimming)' == ''">true false false From 901be399257eba41320aa37a1e125a8182df9938 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 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 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 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 [] array, T item, string message) where T : IEquatable + { + 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 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; + + + + managed-static + + + true + + + + + <_IsSimulatorFeature Condition="('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS') And '$(_SdkIsSimulator)' == 'true'">true + <_IsSimulatorFeature Condition="'$(_IsSimulatorFeature)' == ''">false + + + <_IsManagedStaticRegistrarFeature Condition="'$(Registrar)' == 'managed-static'">true + <_IsManagedStaticRegistrarFeature Condition="'$(Registrar)' != 'managed-static'">false + + + <_IsNativeAOTFeature Condition="'$(_XamarinRuntime)' == 'NativeAOT'">true + <_IsNativeAOTFeature Condition="'$(_XamarinRuntime)' != 'NativeAOT'">false + + + <_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.Arch.IsSimulator $(_IsSimulatorFeature) + <_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsManagedStaticRegistrar $(_IsManagedStaticRegistrarFeature) + <_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsNativeAOT $(_IsNativeAOTFeature) + + + + + + + + + + @@ -444,9 +481,6 @@ - - managed-static - @@ -564,18 +598,6 @@ <_ExtraTrimmerArgs Condition="'$(_BundlerDebug)' != 'true' And '$(MtouchInterpreter)' == '' And '$(_RunAotCompiler)' == 'true' And '$(_PlatformName)' != 'macOS'">$(_ExtraTrimmerArgs) --enable-opt sealer - - <_ExtraTrimmerArgs Condition="('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS') And '$(_SdkIsSimulator)' == 'true'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.Arch.IsSimulator true - <_ExtraTrimmerArgs Condition="('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS') And '$(_SdkIsSimulator)' != 'true'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.Arch.IsSimulator false - - - <_ExtraTrimmerArgs Condition="'$(Registrar)' == 'managed-static'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsManagedStaticRegistrar true - <_ExtraTrimmerArgs Condition="'$(Registrar)' != 'managed-static'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsManagedStaticRegistrar false - - - <_ExtraTrimmerArgs Condition="'$(_XamarinRuntime)' == 'NativeAOT'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsNativeAOT true - <_ExtraTrimmerArgs Condition="'$(_XamarinRuntime)' != 'NativeAOT'">$(_ExtraTrimmerArgs) --feature ObjCRuntime.Runtime.IsNativeAOT false - <_ExtraTrimmerArgs>$(_ExtraTrimmerArgs) --enable-serialization-discovery From 595bcdb92f10d019c3882d9c656d1f55f5aecaeb Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 Condition="'$(PublishAot)' != 'true'"> + $(_ComputeLinkerArgumentsDependsOn); ComputeResolvedFilesToPublishList; + + <_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 Condition="'$(RuntimeIdentifiers)' == '' And '$(PublishAot)' != 'true'">$(_ComputeVariablesDependsOn);ComputeResolvedFilesToPublishList From 13fa76923fc0b84bcf9e9ea1ddab600c88cbbe3e Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ true + + + + + false + + + true + From b36db052750ad8dc48673047fe01fae573447516 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 Condition="'$(PublishAot)' == 'true'"> + $(_CompileNativeExecutableDependsOn); + IlcCompile; + 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 @@ + + Compile;_ComputeLinkerArguments;_ComputeManagedAssemblyToLink;SetupOSSpecificProps;PrepareForILLink;_XamarinComputeIlcCompileInputs + + @@ -1166,6 +1170,13 @@ + + + + static + + + <_GenerateBindingsDependsOn> _ComputeBindingVariables; From 8cfee8b599d204ae087088142d3fa26ab0cbf007 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ static + + + + + From 6bd8915d1aa49ce565ec13d5a28d2215dfa47713 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ + + + <_UpdatedManagedAssemblyToLink Include="@(ManagedAssemblyToLink->'$(IntermediateLinkDir)%(Filename)%(Extension)')" Condition="Exists('$(IntermediateLinkDir)%(Filename)%(Extension)')" /> + + + + + From 39774937bab4c367a69dd56e1da2c6f9df26a05d Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ + + + + From 79b76574c7f2440dd3474d84979a461950ce9ebc Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ + + + From c48d5830258905f6ad65836035a02a458149e620 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ + + + <_NativeExecutableObjectFiles Include="$(NativeObject)" /> From 2ee532690af0dd41ac22accaa4b6338e2cb4bac6 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ <_NativeExecutableObjectFiles Include="$(NativeObject)" /> + + + + <_LinkerArgsSplitBySemiColon>@(LinkerArg->Replace(' ',';')) + + + <_CustomLinkFlags Include="$(_LinkerArgsSplitBySemiColon.Split(';'))" /> + From 617f64e52d02ba6b1bc0a9afbdb066dbfc8c4cb8 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ + + + <_CustomLinkerOptionsFile>$([System.IO.Path]::GetFullPath('$(IntermediateOutputPath)custom-linker-options.txt')) @@ -1506,11 +1509,12 @@ <_DefaultLinkMode>TrimMode - <_DefaultLinkMode Condition="'$(_PlatformName)' == 'macOS'">None - <_DefaultLinkMode Condition="'$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' == 'Release'">SdkOnly - <_DefaultLinkMode Condition="'$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' != 'Release'">None - <_DefaultLinkMode Condition="'$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' == 'true'">None - <_DefaultLinkMode Condition="'$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' != 'true'">SdkOnly + <_DefaultLinkMode Condition="'$(PublishAot)' != 'true'">Full + <_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'macOS'">None + <_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' == 'Release'">SdkOnly + <_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' != 'Release'">None + <_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' == 'true'">None + <_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' != 'true'">SdkOnly From d601e516983fd3d6562abab6237fbfdb8211fdbf Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ true + + + true From 183c76af4046ca90cff356e02568df97611be396 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 ($""); writer.WriteLine ($""); @@ -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"); @@ -46,7 +57,8 @@ using (TextWriter writer = new StreamWriter (outputPath)) { writer.WriteLine ($"\t\t"); writer.WriteLine ("\t"); writer.WriteLine ("\t"); - writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion>{minSdkVersionString}"); + writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion Condition=\"'$(PublishAot)' != 'true'\">{minSdkVersionString}"); + writer.WriteLine ($"\t\t<{platform}MinSupportedOSPlatformVersion Condition=\"'$(PublishAot)' == 'true'\">{minNativeAotSdkVersionString}"); writer.WriteLine ("\t"); writer.WriteLine (""); } From e3228d04eaf79a128979b6e7c37de7ac838f3e19 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ true + + + false From a1d707c0134aa3a967db36fcdc25b16c34bb597b Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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)" /> + + + <_TrimmerRootAssemblyButOnlyIntermediateAssembly Include="@(TrimmerRootAssembly)" Condition="'@(TrimmerRootAssembly)' == '@(IntermediateAssembly)' And '%(Identity)' != ''" /> + + + + + <_UseNativeAot Condition="'$(PublishAot)' == 'true' And '$(_IsPublishing)' == 'true'">true + false - false + false true + 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 @@ - + false 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 Condition="'$(PublishAot)' != 'true'"> + <_ComputeLinkerArgumentsDependsOn Condition="'$(_UseNativeAot)' != 'true'"> $(_ComputeLinkerArgumentsDependsOn); ComputeResolvedFilesToPublishList; @@ -443,12 +443,12 @@ - + Compile;_ComputeLinkerArguments;_ComputeManagedAssemblyToLink;SetupOSSpecificProps;PrepareForILLink;_XamarinComputeIlcCompileInputs - + managed-static @@ -490,10 +490,10 @@ - + - - + + @@ -895,8 +895,8 @@ <_XamarinRuntime Condition="'$(UseMonoRuntime)' == 'true'">MonoVM - <_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(PublishAot)' != 'true'">CoreCLR - <_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(PublishAot)' == 'true'">NativeAOT + <_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(_UseNativeAot)' != 'true'">CoreCLR + <_XamarinRuntime Condition="'$(UseMonoRuntime)' != 'true' And '$(_UseNativeAot)' == 'true'">NativeAOT <_PackageIdInfix Condition="'$(_XamarinRuntime)' == 'MonoVM'">Mono. <_PackageIdInfix Condition="'$(_XamarinRuntime)' == 'NativeAOT'">NativeAOT. @@ -948,7 +948,7 @@ publish (except the merged app bundle, which we'll handle ourselves). --> - <_ComputeVariablesDependsOn Condition="'$(RuntimeIdentifiers)' == '' And '$(PublishAot)' != 'true'">$(_ComputeVariablesDependsOn);ComputeResolvedFilesToPublishList + <_ComputeVariablesDependsOn Condition="'$(RuntimeIdentifiers)' == '' And '$(_UseNativeAot)' != 'true'">$(_ComputeVariablesDependsOn);ComputeResolvedFilesToPublishList @@ -957,7 +957,7 @@ <_RunAotCompiler>false - + <_RunAotCompiler Condition="'$(_SdkIsSimulator)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst'">true @@ -1314,7 +1314,7 @@ _AOTCompile; - <_CompileNativeExecutableDependsOn Condition="'$(PublishAot)' == 'true'"> + <_CompileNativeExecutableDependsOn Condition="'$(_UseNativeAot)' == 'true'"> $(_CompileNativeExecutableDependsOn); IlcCompile; @@ -1531,12 +1531,12 @@ <_DefaultLinkMode>TrimMode - <_DefaultLinkMode Condition="'$(PublishAot)' != 'true'">Full - <_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'macOS'">None - <_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' == 'Release'">SdkOnly - <_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' != 'Release'">None - <_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' == 'true'">None - <_DefaultLinkMode Condition="'$(PublishAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' != 'true'">SdkOnly + <_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true'">Full + <_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true' And '$(_PlatformName)' == 'macOS'">None + <_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' == 'Release'">SdkOnly + <_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true' And '$(_PlatformName)' == 'MacCatalyst' And '$(Configuration)' != 'Release'">None + <_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' == 'true'">None + <_DefaultLinkMode Condition="'$(_UseNativeAot)' != 'true' And '$(_PlatformName)' != 'macOS' And '$(_PlatformName)' != 'MacCatalyst' And '$(_SdkIsSimulator)' != 'true'">SdkOnly 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 CreateTestVariations (IEnumerable tests, Func 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 @@ static + + + + + + + + From c49888bee16b81168c232d7f5e75248f7a9a1fa8 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 ("Xamarin rocks"), "content"); } } From 264be7055e0c83d14e9ff8509c28c151d05f070a Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ true + + + false + + false + + + true From 3c912d7aea88e0a8ee57229fac95875c6c48420f Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge 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 @@ + + <_GlobalizationDataFileLocation Condition="'$(_UseNativeAot)' == 'true'">Resource + <_GlobalizationDataFileLocation Condition="'$(_UseNativeAot)' != 'true'">Assembly + + @@ -1650,7 +1655,7 @@ '%(ResolvedFileToPublish.Filename)%(ResolvedFileToPublish.Extension)' == '$(_GlobalizationDataFile)' And '%(ResolvedFileToPublish.NuGetPackageId)' == '$(_MonoNugetPackageId)' " - PublishFolderType="Assembly" + PublishFolderType="$(_GlobalizationDataFileLocation)" /> 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 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 @@ <_CustomLinkFlags Include="$(_LinkerArgsSplitBySemiColon.Split(';'))" /> + + + + + + +