diff --git a/msbuild/Messaging/Xamarin.Messaging.Build/Xamarin.Messaging.Build.csproj b/msbuild/Messaging/Xamarin.Messaging.Build/Xamarin.Messaging.Build.csproj index 2595200674..a16e288a04 100644 --- a/msbuild/Messaging/Xamarin.Messaging.Build/Xamarin.Messaging.Build.csproj +++ b/msbuild/Messaging/Xamarin.Messaging.Build/Xamarin.Messaging.Build.csproj @@ -1,6 +1,6 @@ - net472 + netstandard2.0 Exe Build $(NoWarn);NU1603 diff --git a/msbuild/Xamarin.Localization.MSBuild/Xamarin.Localization.MSBuild.csproj b/msbuild/Xamarin.Localization.MSBuild/Xamarin.Localization.MSBuild.csproj index 45d524dfcb..6bc59827ff 100644 --- a/msbuild/Xamarin.Localization.MSBuild/Xamarin.Localization.MSBuild.csproj +++ b/msbuild/Xamarin.Localization.MSBuild/Xamarin.Localization.MSBuild.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.0 true ../../product.snk diff --git a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj index 911a1be76a..1b24d18957 100644 --- a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj +++ b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.0 false true ../../product.snk diff --git a/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj b/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj index c8867e79db..75d9892f16 100644 --- a/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj +++ b/msbuild/Xamarin.MacDev.Tasks/Xamarin.MacDev.Tasks.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.0 false true latest diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index cf02c72839..1c49e94d34 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -2685,6 +2685,9 @@ Copyright (C) 2018 Microsoft. All rights reserved. <_AppContainerDir Condition="'$(IsAppDistribution)' == 'true'">$(ArchivePath)\Products\Applications\ $(_AppContainerDir)$(_AppBundleName)$(AppBundleExtension) + + <_AppContainerDir>$([System.IO.Path]::GetDirectoryName($(AppBundleDir)))/ + <_AppBundlePath>$(AppBundleDir) diff --git a/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.Common.After.targets b/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.Common.After.targets index 576c6b4403..40e82e95b6 100644 --- a/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.Common.After.targets +++ b/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.Common.After.targets @@ -312,8 +312,8 @@ Copyright (C) 2011-2013 Xamarin. All rights reserved. Outputs="$(_LinkSemaphore)"> - - <_RemoteILLinkPath>$(ILLinkTasksAssembly.Replace('$(NetCoreRoot)', '$(_DotNetRootRemoteDirectory)').Replace('net472', 'net6.0').Replace('$([System.IO.Path]::GetFileName('$(ILLinkTasksAssembly)'))', 'illink.dll')) + + <_RemoteILLinkPath>$(ILLinkTasksAssembly.Replace('$(NetCoreRoot)', '$(_DotNetRootRemoteDirectory)').Replace('net472', 'net$(BundledNETCoreAppTargetFrameworkVersion)').Replace('$([System.IO.Path]::GetFileName('$(ILLinkTasksAssembly)'))', 'illink.dll')) diff --git a/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.Tasks.Windows.csproj b/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.Tasks.Windows.csproj index 46f2c6e519..f9995134ce 100644 --- a/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.Tasks.Windows.csproj +++ b/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.Tasks.Windows.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.0 false false compile diff --git a/msbuild/Xamarin.iOS.Tasks/Xamarin.iOS.Tasks.csproj b/msbuild/Xamarin.iOS.Tasks/Xamarin.iOS.Tasks.csproj index 8a74a6e21a..ee241e084c 100644 --- a/msbuild/Xamarin.iOS.Tasks/Xamarin.iOS.Tasks.csproj +++ b/msbuild/Xamarin.iOS.Tasks/Xamarin.iOS.Tasks.csproj @@ -1,7 +1,7 @@ - netstandard2.0 + netstandard2.0 false compile true diff --git a/runtime/xamarin/runtime.h b/runtime/xamarin/runtime.h index 481a0cc114..d7845c76f4 100644 --- a/runtime/xamarin/runtime.h +++ b/runtime/xamarin/runtime.h @@ -56,8 +56,8 @@ typedef struct { } MTProperty; // This structure completely describes everything required to resolve a metadata token -typedef struct MTFullTokenReference { - const char *assembly_name; /* the name of the assembly */ +typedef struct __attribute__((packed)) { + uint32_t assembly_index; /* index into the 'assemblies' array in the registration map */ uint32_t module_token; uint32_t token; } MTFullTokenReference; @@ -99,10 +99,15 @@ typedef struct __attribute__((packed)) { const __unsafe_unretained Protocol * const * protocols; // the corresponding native protocols } MTProtocolMap; +typedef struct __attribute__((packed)) { + const char *name; + const char *mvid; +} MTAssembly; + struct MTRegistrationMap; struct MTRegistrationMap { - const char **assembly; + const MTAssembly *assemblies; MTClassMap *map; const MTFullTokenReference *full_token_references; // There are some managed types that are not registered because their ObjC diff --git a/src/CoreFoundation/CFRunLoop.cs b/src/CoreFoundation/CFRunLoop.cs index d3b7e661cc..d38411a837 100644 --- a/src/CoreFoundation/CFRunLoop.cs +++ b/src/CoreFoundation/CFRunLoop.cs @@ -59,7 +59,11 @@ namespace CoreFoundation { // CFRunLoop.h [StructLayout (LayoutKind.Sequential)] +#if NET + internal unsafe struct CFRunLoopSourceContext { +#else internal struct CFRunLoopSourceContext { +#endif public CFIndex Version; public IntPtr Info; public IntPtr Retain; @@ -67,9 +71,15 @@ namespace CoreFoundation { public IntPtr CopyDescription; public IntPtr Equal; public IntPtr Hash; +#if NET + public delegate* unmanaged Schedule; + public delegate* unmanaged Cancel; + public delegate* unmanaged Perform; +#else public IntPtr Schedule; public IntPtr Cancel; public IntPtr Perform; +#endif } #if NET @@ -145,9 +155,11 @@ namespace CoreFoundation { [DllImport (Constants.CoreFoundationLibrary)] extern static /* CFRunLoopSourceRef */ IntPtr CFRunLoopSourceCreate (/* CFAllocatorRef */ IntPtr allocator, /* CFIndex */ nint order, /* CFRunLoopSourceContext* */ ref CFRunLoopSourceContext context); +#if !NET static ScheduleCallback ScheduleDelegate = (ScheduleCallback) Schedule; static CancelCallback CancelDelegate = (CancelCallback) Cancel; static PerformCallback PerformDelegate = (PerformCallback) Perform; +#endif protected CFRunLoopSourceCustom () : base (IntPtr.Zero, true) @@ -155,9 +167,17 @@ namespace CoreFoundation { gch = GCHandle.Alloc (this); var ctx = new CFRunLoopSourceContext (); ctx.Info = GCHandle.ToIntPtr (gch); +#if NET + unsafe { + ctx.Schedule = &Schedule; + ctx.Cancel = &Cancel; + ctx.Perform = &Perform; + } +#else ctx.Schedule = Marshal.GetFunctionPointerForDelegate (ScheduleDelegate); ctx.Cancel = Marshal.GetFunctionPointerForDelegate (CancelDelegate); ctx.Perform = Marshal.GetFunctionPointerForDelegate (PerformDelegate); +#endif var handle = CFRunLoopSourceCreate (IntPtr.Zero, 0, ref ctx); InitializeHandle (handle); @@ -165,7 +185,11 @@ namespace CoreFoundation { delegate void ScheduleCallback (IntPtr info, IntPtr runLoop, IntPtr mode); +#if NET + [UnmanagedCallersOnly] +#else [MonoPInvokeCallback (typeof(ScheduleCallback))] +#endif static void Schedule (IntPtr info, IntPtr runLoop, IntPtr mode) { var source = GCHandle.FromIntPtr (info).Target as CFRunLoopSourceCustom; @@ -182,7 +206,11 @@ namespace CoreFoundation { delegate void CancelCallback (IntPtr info, IntPtr runLoop, IntPtr mode); +#if NET + [UnmanagedCallersOnly] +#else [MonoPInvokeCallback (typeof(CancelCallback))] +#endif static void Cancel (IntPtr info, IntPtr runLoop, IntPtr mode) { var source = GCHandle.FromIntPtr (info).Target as CFRunLoopSourceCustom; @@ -199,7 +227,11 @@ namespace CoreFoundation { delegate void PerformCallback (IntPtr info); +#if NET + [UnmanagedCallersOnly] +#else [MonoPInvokeCallback (typeof(PerformCallback))] +#endif static void Perform (IntPtr info) { var source = GCHandle.FromIntPtr (info).Target as CFRunLoopSourceCustom; diff --git a/src/CoreVideo/CVDisplayLink.cs b/src/CoreVideo/CVDisplayLink.cs index b12be52cfd..42b7cdce5d 100644 --- a/src/CoreVideo/CVDisplayLink.cs +++ b/src/CoreVideo/CVDisplayLink.cs @@ -330,27 +330,50 @@ namespace CoreVideo { public delegate CVReturn DisplayLinkOutputCallback (CVDisplayLink displayLink, ref CVTimeStamp inNow, ref CVTimeStamp inOutputTime, CVOptionFlags flagsIn, ref CVOptionFlags flagsOut); delegate CVReturn CVDisplayLinkOutputCallback (IntPtr displayLink, ref CVTimeStamp inNow, ref CVTimeStamp inOutputTime, CVOptionFlags flagsIn, ref CVOptionFlags flagsOut, IntPtr displayLinkContext); +#if NET + [UnmanagedCallersOnly] + static unsafe CVReturn OutputCallback (IntPtr displayLink, CVTimeStamp* inNow, CVTimeStamp* inOutputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, IntPtr displayLinkContext) +#else static CVDisplayLinkOutputCallback static_OutputCallback = new CVDisplayLinkOutputCallback (OutputCallback); - #if !MONOMAC [MonoPInvokeCallback (typeof (CVDisplayLinkOutputCallback))] #endif static CVReturn OutputCallback (IntPtr displayLink, ref CVTimeStamp inNow, ref CVTimeStamp inOutputTime, CVOptionFlags flagsIn, ref CVOptionFlags flagsOut, IntPtr displayLinkContext) +#endif { GCHandle callbackHandle = GCHandle.FromIntPtr (displayLinkContext); DisplayLinkOutputCallback func = (DisplayLinkOutputCallback) callbackHandle.Target!; CVDisplayLink delegateDisplayLink = new CVDisplayLink(displayLink, false); +#if NET + return func (delegateDisplayLink, + ref System.Runtime.CompilerServices.Unsafe.AsRef (inNow), + ref System.Runtime.CompilerServices.Unsafe.AsRef (inOutputTime), + flagsIn, ref System.Runtime.CompilerServices.Unsafe.AsRef (flagsOut)); +#else return func (delegateDisplayLink, ref inNow, ref inOutputTime, flagsIn, ref flagsOut); +#endif } - + +#if NET + [DllImport (Constants.CoreVideoLibrary)] + extern static unsafe CVReturn CVDisplayLinkSetOutputCallback (IntPtr displayLink, delegate* unmanaged function, IntPtr userInfo); +#else [DllImport (Constants.CoreVideoLibrary)] extern static CVReturn CVDisplayLinkSetOutputCallback (IntPtr displayLink, CVDisplayLinkOutputCallback function, IntPtr userInfo); +#endif public CVReturn SetOutputCallback (DisplayLinkOutputCallback callback) { callbackHandle = GCHandle.Alloc (callback); +#if NET + unsafe { + CVReturn ret = CVDisplayLinkSetOutputCallback (this.Handle, &OutputCallback, GCHandle.ToIntPtr (callbackHandle)); + return ret; + } +#else CVReturn ret = CVDisplayLinkSetOutputCallback (this.Handle, static_OutputCallback, GCHandle.ToIntPtr (callbackHandle)); - return ret; +#endif + } #if NET diff --git a/src/CoreVideo/CVPixelBuffer.cs b/src/CoreVideo/CVPixelBuffer.cs index 00ab1ec9fb..90889a3b53 100644 --- a/src/CoreVideo/CVPixelBuffer.cs +++ b/src/CoreVideo/CVPixelBuffer.cs @@ -146,15 +146,35 @@ namespace CoreVideo { /* void * CV_NULLABLE */ IntPtr releaseRefCon, /* const void * CV_NULLABLE */ IntPtr baseAddress); +#if !NET static CVPixelBufferReleaseBytesCallback releaseBytesCallback = new CVPixelBufferReleaseBytesCallback (ReleaseBytesCallback); +#endif +#if NET + [UnmanagedCallersOnly] +#else [MonoPInvokeCallbackAttribute (typeof (CVPixelBufferReleaseBytesCallback))] +#endif static void ReleaseBytesCallback (IntPtr releaseRefCon, IntPtr baseAddress) { GCHandle handle = GCHandle.FromIntPtr (releaseRefCon); handle.Free (); } +#if NET + [DllImport (Constants.CoreVideoLibrary)] + static unsafe extern CVReturn CVPixelBufferCreateWithBytes ( + /* CFAllocatorRef CV_NULLABLE */ IntPtr allocator, + /* size_t */ nint width, + /* size_t */ nint height, + /* OSType */ CVPixelFormatType pixelFormatType, + /* void * CV_NONNULL */ IntPtr baseAddress, + /* size_t */ nint bytesPerRow, + delegate* unmanaged releaseCallback, + /* void * CV_NULLABLE */ IntPtr releaseRefCon, + /* CFDictionaryRef CV_NULLABLE */ IntPtr pixelBufferAttributes, + /* CV_RETURNS_RETAINED_PARAMETER CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ out IntPtr pixelBufferOut);// __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_4_0); +#else [DllImport (Constants.CoreVideoLibrary)] static extern CVReturn CVPixelBufferCreateWithBytes ( /* CFAllocatorRef CV_NULLABLE */ IntPtr allocator, @@ -167,7 +187,7 @@ namespace CoreVideo { /* void * CV_NULLABLE */ IntPtr releaseRefCon, /* CFDictionaryRef CV_NULLABLE */ IntPtr pixelBufferAttributes, /* CV_RETURNS_RETAINED_PARAMETER CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ out IntPtr pixelBufferOut);// __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_4_0); - +#endif public static CVPixelBuffer? Create (nint width, nint height, CVPixelFormatType pixelFormatType, byte[] data, nint bytesPerRow, CVPixelBufferAttributes pixelBufferAttributes) { CVReturn status; @@ -187,7 +207,13 @@ namespace CoreVideo { gchandle = GCHandle.Alloc (data, GCHandleType.Pinned); // This requires a pinned GCHandle, because unsafe code is scoped to the current block, and the address of the byte array will be used after this function returns. +#if NET + unsafe { + status = CVPixelBufferCreateWithBytes (IntPtr.Zero, width, height, pixelFormatType, gchandle.AddrOfPinnedObject (), bytesPerRow, &ReleaseBytesCallback, GCHandle.ToIntPtr (gchandle), DictionaryContainerHelper.GetHandle (pixelBufferAttributes), out handle); + } +#else status = CVPixelBufferCreateWithBytes (IntPtr.Zero, width, height, pixelFormatType, gchandle.AddrOfPinnedObject (), bytesPerRow, releaseBytesCallback, GCHandle.ToIntPtr (gchandle), DictionaryContainerHelper.GetHandle (pixelBufferAttributes), out handle); +#endif if (status != CVReturn.Success) { gchandle.Free (); @@ -210,11 +236,11 @@ namespace CoreVideo { /* size_t */ nint dataSize, /* size_t */ nint numberOfPlanes, /* const void* */IntPtr planeAddresses); - +#if !NET static CVPixelBufferReleasePlanarBytesCallback releasePlanarBytesCallback = new CVPixelBufferReleasePlanarBytesCallback (ReleasePlanarBytesCallback); +#endif - [MonoPInvokeCallbackAttribute (typeof (CVPixelBufferReleasePlanarBytesCallback))] - static void ReleasePlanarBytesCallback (IntPtr releaseRefCon, IntPtr dataPtr, nint dataSize, nint numberOfPlanes, IntPtr planeAddresses) + static void ReleasePlanarBytesCallbackImpl (IntPtr releaseRefCon, IntPtr dataPtr, nint dataSize, nint numberOfPlanes, IntPtr planeAddresses) { GCHandle handle = GCHandle.FromIntPtr (releaseRefCon); PlaneData data = (PlaneData) handle.Target!; @@ -222,7 +248,36 @@ namespace CoreVideo { data.dataHandles[i].Free (); handle.Free (); } +#if NET + [UnmanagedCallersOnly] +#else + [MonoPInvokeCallbackAttribute (typeof (CVPixelBufferReleasePlanarBytesCallback))] +#endif + static void ReleasePlanarBytesCallback (IntPtr releaseRefCon, IntPtr dataPtr, nint dataSize, nint numberOfPlanes, IntPtr planeAddresses) + { + ReleasePlanarBytesCallbackImpl (releaseRefCon, dataPtr, dataSize, numberOfPlanes, planeAddresses); + } +#if NET + [DllImport (Constants.CoreVideoLibrary)] + static unsafe extern CVReturn CVPixelBufferCreateWithPlanarBytes ( + /* CFAllocatorRef CV_NULLABLE */ IntPtr allocator, + /* size_t */ nint width, + /* size_t */ nint height, + /* OSType */ CVPixelFormatType pixelFormatType, + /* void * CV_NULLABLE */ IntPtr dataPtr, /* pass a pointer to a plane descriptor block, or NULL /* + /* size_t */ nint dataSize, /* pass size if planes are contiguous, NULL if not */ + /* size_t */ nint numberOfPlanes, + /* void *[] CV_NULLABLE */ IntPtr[] planeBaseAddress, + /* size_t[] */ nint [] planeWidth, + /* size_t[] */ nint [] planeHeight, + /* size_t[] */ nint [] planeBytesPerRow, + delegate* unmanaged/* CV_NULLABLE */ releaseCallback, + /* void * CV_NULLABLE */ IntPtr releaseRefCon, + /* CFDictionaryRef CV_NULLABLE */ IntPtr pixelBufferAttributes, + /* CV_RETURNS_RETAINED_PARAMETER CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ out IntPtr pixelBufferOut); // __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_4_0); + +#else [DllImport (Constants.CoreVideoLibrary)] static extern CVReturn CVPixelBufferCreateWithPlanarBytes ( /* CFAllocatorRef CV_NULLABLE */ IntPtr allocator, @@ -240,6 +295,7 @@ namespace CoreVideo { /* void * CV_NULLABLE */ IntPtr releaseRefCon, /* CFDictionaryRef CV_NULLABLE */ IntPtr pixelBufferAttributes, /* CV_RETURNS_RETAINED_PARAMETER CVPixelBufferRef CV_NULLABLE * CV_NONNULL */ out IntPtr pixelBufferOut); // __OSX_AVAILABLE_STARTING(__MAC_10_4,__IPHONE_4_0); +#endif public static CVPixelBuffer? Create (nint width, nint height, CVPixelFormatType pixelFormatType, byte[][] planes, nint[] planeWidths, nint[] planeHeights, nint[] planeBytesPerRow, CVPixelBufferAttributes pixelBufferAttributes) { @@ -287,14 +343,24 @@ namespace CoreVideo { data_handle = GCHandle.Alloc (data); IntPtr data_handle_ptr = GCHandle.ToIntPtr (data_handle); +#if NET + unsafe { + status = CVPixelBufferCreateWithPlanarBytes (IntPtr.Zero, + width, height, pixelFormatType, IntPtr.Zero, 0, + planeCount, addresses, planeWidths, planeHeights, planeBytesPerRow, + &ReleasePlanarBytesCallback, data_handle_ptr, + DictionaryContainerHelper.GetHandle (pixelBufferAttributes), out handle); + } +#else status = CVPixelBufferCreateWithPlanarBytes (IntPtr.Zero, width, height, pixelFormatType, IntPtr.Zero, 0, planeCount, addresses, planeWidths, planeHeights, planeBytesPerRow, releasePlanarBytesCallback, data_handle_ptr, DictionaryContainerHelper.GetHandle (pixelBufferAttributes), out handle); +#endif if (status != CVReturn.Success) { - ReleasePlanarBytesCallback (data_handle_ptr, IntPtr.Zero, 0, 0, IntPtr.Zero); + ReleasePlanarBytesCallbackImpl (data_handle_ptr, IntPtr.Zero, 0, 0, IntPtr.Zero); return null; } diff --git a/src/ObjCRuntime/Class.cs b/src/ObjCRuntime/Class.cs index 7f5890678c..437eb0b222 100644 --- a/src/ObjCRuntime/Class.cs +++ b/src/ObjCRuntime/Class.cs @@ -10,6 +10,7 @@ #nullable enable using System; +using System.Diagnostics.CodeAnalysis; using System.Reflection; using System.Collections.Generic; using System.Runtime.InteropServices; @@ -19,6 +20,10 @@ using Foundation; using Registrar; #endif +#if !COREBUILD +using Xamarin.Bundler; +#endif + #if !NET using NativeHandle = System.IntPtr; #endif @@ -56,8 +61,8 @@ namespace ObjCRuntime { for (int i = 0; i < map->assembly_count; i++) { - var ptr = Marshal.ReadIntPtr (map->assembly, i * IntPtr.Size); - Runtime.Registrar.SetAssemblyRegistered (Marshal.PtrToStringAuto (ptr)); + var assembly = map->assemblies [i]; + Runtime.Registrar.SetAssemblyRegistered (Marshal.PtrToStringAuto (assembly.name)); } } @@ -292,27 +297,27 @@ namespace ObjCRuntime { if ((token_reference & 0x1) == 0x1) { // full token reference var idx = (int) (token_reference >> 1); - var entry = map->full_token_references + (IntPtr.Size + 8) * idx; + var entry = map->full_token_references [idx]; // first compare what's most likely to fail (the type's metadata token) - var token = (uint) Marshal.ReadInt32 (entry + IntPtr.Size + 4); + var token = entry.token; type_token |= 0x02000000 /* TypeDef - the token type is explicit in the full token reference, but not present in the type_token argument, so we have to add it before comparing */; if (type_token != token) return false; // then the module token - var module_token = (uint) Marshal.ReadInt32 (entry + IntPtr.Size); + var module_token = entry.module_token; if (mod_token != module_token) return false; // leave the assembly name for the end, since it's the most expensive comparison (string comparison) - assembly_name = Marshal.ReadIntPtr (entry); + assembly_name = map->assemblies [entry.assembly_index].name; } else { // packed token reference if (token_reference >> 8 != type_token) return false; var assembly_index = (token_reference >> 1) & 0x7F; - assembly_name = Marshal.ReadIntPtr (map->assembly, (int) assembly_index * IntPtr.Size); + assembly_name = map->assemblies [(int) assembly_index].name; } return Runtime.StringEquals (assembly_name, asm_name); @@ -380,10 +385,11 @@ namespace ObjCRuntime { internal unsafe static MemberInfo? ResolveFullTokenReference (uint token_reference) { // sizeof (MTFullTokenReference) = IntPtr.Size + 4 + 4 - var entry = Runtime.options->RegistrationMap->full_token_references + (IntPtr.Size + 8) * (int) (token_reference >> 1); - var assembly_name = Marshal.ReadIntPtr (entry); - var module_token = (uint) Marshal.ReadInt32 (entry + IntPtr.Size); - var token = (uint) Marshal.ReadInt32 (entry + IntPtr.Size + 4); + var idx = (int) (token_reference >> 1); + var entry = Runtime.options->RegistrationMap->full_token_references [idx]; + var assembly_name = Runtime.options->RegistrationMap->assemblies [entry.assembly_index].name; + var module_token = entry.module_token; + var token = entry.token; #if LOG_TYPELOAD Console.WriteLine ($"ResolveFullTokenReference (0x{token_reference:X}) assembly name: {assembly_name} module token: 0x{module_token:X} token: 0x{token:X}."); @@ -430,7 +436,7 @@ namespace ObjCRuntime { Console.WriteLine ($"ResolveTokenReference (0x{token_reference:X}) assembly index: {assembly_index} token: 0x{token:X}."); #endif - var assembly_name = Marshal.ReadIntPtr (map->assembly, (int) assembly_index * IntPtr.Size); + var assembly_name = map->assemblies [(int) assembly_index].name; var assembly = ResolveAssembly (assembly_name); var module = ResolveModule (assembly, 0x1); @@ -474,7 +480,65 @@ namespace ObjCRuntime { throw ErrorHelper.CreateError (8020, $"Could not find the module with MetadataToken 0x{token:X} in the assembly {assembly}."); } +// Restrict this code to desktop for now, which is where most of the problems with outdated generated static registrar code occur. +#if __MACOS__ || __MACCATALYST__ + static bool? verify_static_registrar_code; + static object? verification_lock; + static Dictionary? verified_assemblies; // Use Dictionary instead of HashSet to avoid pulling in System.Core.dll. + unsafe static void VerifyStaticRegistrarCode (IntPtr assembly_name, Assembly assembly) + { + if (verify_static_registrar_code is null) { + verify_static_registrar_code = !string.IsNullOrEmpty (Environment.GetEnvironmentVariable ("XAMARIN_VALIDATE_STATIC_REGISTRAR_CODE")); + verification_lock = new object (); + } + if (verify_static_registrar_code != true) + return; + + lock (verification_lock!) { + if (verified_assemblies is null) { + verified_assemblies = new Dictionary (Runtime.IntPtrEqualityComparer); + } else if (verified_assemblies.ContainsKey (assembly_name)) { + return; + } + verified_assemblies [assembly_name] = null; + } + + var map = Runtime.options->RegistrationMap; + if (map is null) + return; + + for (var i = 0; i < map->assembly_count; i++) { + var entry = map->assemblies [i]; + var name = Marshal.PtrToStringAuto (entry.name)!; + if (!Runtime.StringEquals (assembly_name, name)) + continue; + try { + var mvid = Marshal.PtrToStringAuto (entry.mvid)!; + var runtime_mvid = assembly.ManifestModule.ModuleVersionId; + var registered_mvid = Guid.Parse (mvid); + if (registered_mvid == runtime_mvid) + continue; + throw ErrorHelper.CreateError (8044, Errors.MX8044 /* The assembly {0} has been modified since the app was built, invalidating the generated static registrar code. The MVID for the loaded assembly is {1}, while the MVID for the assembly the generated static registrar code corresponds to is {2}. */, name, runtime_mvid, registered_mvid); + } catch (Exception e) { + throw ErrorHelper.CreateError (8043, e, Errors.MX8043 /* An exception occurred while validating the static registrar code for {0}: {1} */, name, e.Message); + } + } + } +#endif // __MACOS__ || __MACCATALYST__ + static Assembly ResolveAssembly (IntPtr assembly_name) + { + if (TryResolveAssembly (assembly_name, out var asm)) { +#if __MACOS__ || __MACCATALYST__ + VerifyStaticRegistrarCode (assembly_name, asm); +#endif + return asm; + } + + throw ErrorHelper.CreateError (8019, $"Could not find the assembly {Marshal.PtrToStringAuto (assembly_name)} in the loaded assemblies."); + } + + static bool TryResolveAssembly (IntPtr assembly_name, [NotNullWhen (true)] out Assembly? assembly) { // Find the assembly. We've already loaded all the assemblies that contain registered types, so just look at those assemblies. foreach (var asm in AppDomain.CurrentDomain.GetAssemblies ()) { @@ -482,12 +546,14 @@ namespace ObjCRuntime { continue; #if LOG_TYPELOAD - Console.WriteLine ($"ResolveAssembly (0x{assembly_name:X}): {asm.FullName}."); + Console.WriteLine ($"TryResolveAssembly (0x{assembly_name:X}): {asm.FullName}."); #endif - return asm; + assembly = asm; + return true; } - throw ErrorHelper.CreateError (8019, $"Could not find the assembly {Marshal.PtrToStringAuto (assembly_name)} in the loaded assemblies."); + assembly = null; + return false; } internal unsafe static uint GetTokenReference (Type type, bool throw_exception = true) @@ -514,7 +580,7 @@ namespace ObjCRuntime { // Find the assembly index in our list of registered assemblies. int assembly_index = -1; for (int i = 0; i < map->assembly_count; i++) { - var name_ptr = Marshal.ReadIntPtr (map->assembly, (int) i * IntPtr.Size); + var name_ptr = map->assemblies [(int) i].name; if (Runtime.StringEquals (name_ptr, asm_name)) { assembly_index = i; break; @@ -542,15 +608,16 @@ namespace ObjCRuntime { { var map = Runtime.options->RegistrationMap; for (int i = 0; i < map->full_token_reference_count; i++) { - var ptr = map->full_token_references + (i * (IntPtr.Size + 8)); - var asm_ptr = Marshal.ReadIntPtr (ptr); - var token = Marshal.ReadInt32 (ptr + IntPtr.Size + 4); + var ftr = map->full_token_references [i]; + var token = ftr.token; if (token != metadata_token) continue; - var mod_token = Marshal.ReadInt32 (ptr + IntPtr.Size); + var mod_token = ftr.module_token; if (mod_token != module_token) continue; - if (!Runtime.StringEquals (asm_ptr, assembly_name)) + var assembly_index = ftr.assembly_index; + var assembly = map->assemblies [assembly_index]; + if (!Runtime.StringEquals (assembly.name, assembly_name)) continue; return ((uint) i << 1) + 1; diff --git a/src/ObjCRuntime/Runtime.CoreCLR.cs b/src/ObjCRuntime/Runtime.CoreCLR.cs index 54fa69b6a5..8d691b525f 100644 --- a/src/ObjCRuntime/Runtime.CoreCLR.cs +++ b/src/ObjCRuntime/Runtime.CoreCLR.cs @@ -419,6 +419,13 @@ namespace ObjCRuntime { if (obj == null) return; + var structType = obj.GetType (); + // Unwrap enums, Marshal.StructureToPtr complains they're not blittable (https://github.com/xamarin/xamarin-macios/issues/15744) + if (structType.IsEnum) { + structType = Enum.GetUnderlyingType (structType); + obj = Convert.ChangeType (obj, structType); + } + if (obj is bool b) { // Only write a single byte for bools Marshal.WriteByte (ptr, b ? (byte) 1 : (byte) 0); diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs index bd8ab8f907..3ffda5a757 100644 --- a/src/ObjCRuntime/Runtime.cs +++ b/src/ObjCRuntime/Runtime.cs @@ -55,9 +55,9 @@ namespace ObjCRuntime { #pragma warning disable 649 // Field 'X' is never assigned to, and will always have its default value internal unsafe struct MTRegistrationMap { - public IntPtr assembly; + public MTAssembly *assemblies; public MTClassMap *map; - public IntPtr full_token_references; /* array of MTFullTokenReference */ + public MTFullTokenReference *full_token_references; public MTManagedClassMap* skipped_map; public MTProtocolWrapperMap* protocol_wrapper_map; public MTProtocolMap protocol_map; @@ -78,6 +78,13 @@ namespace ObjCRuntime { UserType = 2, } + [StructLayout (LayoutKind.Sequential, Pack = 1)] + internal unsafe struct MTFullTokenReference { + public uint assembly_index; + public uint module_token; + public uint token; + } + [StructLayout (LayoutKind.Sequential, Pack = 1)] internal struct MTClassMap { public IntPtr handle; @@ -104,6 +111,12 @@ namespace ObjCRuntime { public IntPtr* protocols; } + [StructLayout (LayoutKind.Sequential, Pack = 1)] + internal unsafe struct MTAssembly { + public IntPtr name; + public IntPtr mvid; + } + /* Keep Delegates, Trampolines and InitializationOptions in sync with monotouch-glue.m */ #pragma warning disable 649 // Field 'X' is never assigned to, and will always have its default value internal struct Trampolines { diff --git a/src/UIKit/UIGestureRecognizer.cs b/src/UIKit/UIGestureRecognizer.cs index efa52b18d3..8d6d674c7e 100644 --- a/src/UIKit/UIGestureRecognizer.cs +++ b/src/UIKit/UIGestureRecognizer.cs @@ -11,11 +11,10 @@ #if !WATCH using System; -using System.Collections; using System.Collections.Generic; using Foundation; using ObjCRuntime; -using CoreGraphics; +#nullable enable namespace UIKit { @@ -41,9 +40,9 @@ namespace UIKit { { var copyOfRecognizers = recognizers; var savedHandle = Handle; - recognizers = null; + recognizers = new Dictionary (); - if (copyOfRecognizers == null) + if (copyOfRecognizers.Count == 0) return; DangerousRetain (savedHandle); @@ -80,12 +79,12 @@ namespace UIKit { [Register ("__UIGestureRecognizerGenericCB")] internal class Callback : Token where T: UIGestureRecognizer { Action action; - + internal Callback (Action action) { this.action = action; } - + [Export ("target:")] [Preserve (Conditional = true)] public void Activated (T sender) => action (sender); @@ -168,7 +167,10 @@ namespace UIKit { // public IEnumerable GetTargets () { - return (IEnumerable) recognizers?.Keys ?? Array.Empty (); + var keys = recognizers?.Keys; + if (keys is null) + return Array.Empty (); + return (IEnumerable) keys; } } diff --git a/tests/dotnet/MyRegistrarApp/AppDelegate.cs b/tests/dotnet/MyRegistrarApp/AppDelegate.cs new file mode 100644 index 0000000000..3f2469d496 --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/AppDelegate.cs @@ -0,0 +1,63 @@ +using System; +using System.Runtime.InteropServices; + +using Foundation; +using ObjCRuntime; + +namespace MySimpleApp +{ + public class Program + { + static int Main (string[] args) + { + Console.WriteLine (Environment.GetEnvironmentVariable ("MAGIC_WORD")); + +#if INCLUDED_ADDITIONAL_CODE + GC.KeepAlive (typeof (AdditionalClass)); +#endif + + return StaticRegistrarValidationTest (); + } + + static int StaticRegistrarValidationTest () + { + try { + using var obj = new SomeObj (); + obj.Whatever (); + xamarin_IntPtr_objc_msgSend_IntPtr_ref_IntPtr_exception (obj.Handle, Selector.GetHandle ("whatever"), IntPtr.Zero, IntPtr.Zero, out var gchandle); + Console.WriteLine ($"GCH: {gchandle}"); + if (gchandle != IntPtr.Zero) { + var gch = GCHandle.FromIntPtr (gchandle); + var exc = (Exception) gch.Target; + gch.Free (); + throw exc; + } + return 1; // We're not supposed to get here + } catch (Exception e) { + Console.WriteLine ($"E: {e}"); + if (e.Message.Contains ("The assembly MyRegistrarApp has been modified since the app was built, invalidating the generated static registrar code.")) + return 0; + return 2; + } + } + + [DllImport ("__Internal")] + static extern IntPtr xamarin_IntPtr_objc_msgSend_IntPtr_ref_IntPtr_exception (IntPtr handle, IntPtr selector, IntPtr p0, IntPtr p1, out IntPtr gchandle); + } + + public class SomeObj : NSObject + { + [Export ("whatever")] + public IntPtr Whatever () + { + return new IntPtr (0xdeadf00d); + } + } + + public class DeadClass {} // Some code for the linker to remove + +#if INCLUDED_ADDITIONAL_CODE + public class AdditionalClass { + } +#endif +} diff --git a/tests/dotnet/MyRegistrarApp/MacCatalyst/Makefile b/tests/dotnet/MyRegistrarApp/MacCatalyst/Makefile new file mode 100644 index 0000000000..110d078f45 --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/MacCatalyst/Makefile @@ -0,0 +1 @@ +include ../shared.mk diff --git a/tests/dotnet/MyRegistrarApp/MacCatalyst/MyRegistrarApp.csproj b/tests/dotnet/MyRegistrarApp/MacCatalyst/MyRegistrarApp.csproj new file mode 100644 index 0000000000..6b0e2c7731 --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/MacCatalyst/MyRegistrarApp.csproj @@ -0,0 +1,7 @@ + + + + net$(BundledNETCoreAppTargetFrameworkVersion)-maccatalyst + + + diff --git a/tests/dotnet/MyRegistrarApp/Makefile b/tests/dotnet/MyRegistrarApp/Makefile new file mode 100644 index 0000000000..6affa45ff1 --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/Makefile @@ -0,0 +1,2 @@ +TOP=../../.. +include $(TOP)/tests/common/shared-dotnet-test.mk diff --git a/tests/dotnet/MyRegistrarApp/iOS/Makefile b/tests/dotnet/MyRegistrarApp/iOS/Makefile new file mode 100644 index 0000000000..110d078f45 --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/iOS/Makefile @@ -0,0 +1 @@ +include ../shared.mk diff --git a/tests/dotnet/MyRegistrarApp/iOS/MyRegistrarApp.csproj b/tests/dotnet/MyRegistrarApp/iOS/MyRegistrarApp.csproj new file mode 100644 index 0000000000..86d408734a --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/iOS/MyRegistrarApp.csproj @@ -0,0 +1,7 @@ + + + + net$(BundledNETCoreAppTargetFrameworkVersion)-ios + + + diff --git a/tests/dotnet/MyRegistrarApp/macOS/Makefile b/tests/dotnet/MyRegistrarApp/macOS/Makefile new file mode 100644 index 0000000000..110d078f45 --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/macOS/Makefile @@ -0,0 +1 @@ +include ../shared.mk diff --git a/tests/dotnet/MyRegistrarApp/macOS/MyRegistrarApp.csproj b/tests/dotnet/MyRegistrarApp/macOS/MyRegistrarApp.csproj new file mode 100644 index 0000000000..a77287b9ba --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/macOS/MyRegistrarApp.csproj @@ -0,0 +1,7 @@ + + + + net$(BundledNETCoreAppTargetFrameworkVersion)-macos + + + diff --git a/tests/dotnet/MyRegistrarApp/shared.csproj b/tests/dotnet/MyRegistrarApp/shared.csproj new file mode 100644 index 0000000000..517a4462d6 --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/shared.csproj @@ -0,0 +1,20 @@ + + + + Exe + + MyRegistrarApp + com.xamarin.myregistrarapp + + true + true + + $(DefineConstants);$(AdditionalDefineConstants) + + + + + + + + diff --git a/tests/dotnet/MyRegistrarApp/shared.mk b/tests/dotnet/MyRegistrarApp/shared.mk new file mode 100644 index 0000000000..37f5df45b2 --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/shared.mk @@ -0,0 +1,3 @@ +TOP=../../../.. +TESTNAME=MyRegistrarApp +include $(TOP)/tests/common/shared-dotnet.mk diff --git a/tests/dotnet/MyRegistrarApp/tvOS/Makefile b/tests/dotnet/MyRegistrarApp/tvOS/Makefile new file mode 100644 index 0000000000..110d078f45 --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/tvOS/Makefile @@ -0,0 +1 @@ +include ../shared.mk diff --git a/tests/dotnet/MyRegistrarApp/tvOS/MyRegistrarApp.csproj b/tests/dotnet/MyRegistrarApp/tvOS/MyRegistrarApp.csproj new file mode 100644 index 0000000000..e9019db664 --- /dev/null +++ b/tests/dotnet/MyRegistrarApp/tvOS/MyRegistrarApp.csproj @@ -0,0 +1,7 @@ + + + + net$(BundledNETCoreAppTargetFrameworkVersion)-tvos + + + diff --git a/tests/dotnet/UnitTests/IncrementalBuildTest.cs b/tests/dotnet/UnitTests/IncrementalBuildTest.cs index c5b1ac816b..bff09b5ebb 100644 --- a/tests/dotnet/UnitTests/IncrementalBuildTest.cs +++ b/tests/dotnet/UnitTests/IncrementalBuildTest.cs @@ -34,7 +34,7 @@ class MainClass { // Capture the current time var timestamp = DateTime.UtcNow; - File.WriteAllText (mainFile, mainContents + "\n"); + File.WriteAllText (mainFile, mainContents); // Build again rv = DotNet.AssertBuild (project_path, properties); diff --git a/tests/dotnet/UnitTests/ProjectTest.cs b/tests/dotnet/UnitTests/ProjectTest.cs index 9c89268c7c..cafccb063c 100644 --- a/tests/dotnet/UnitTests/ProjectTest.cs +++ b/tests/dotnet/UnitTests/ProjectTest.cs @@ -982,5 +982,19 @@ namespace Xamarin.Tests { Assert.That (errors [0].Message, Does.Contain ("Error loading Entitlements.plist template 'Entitlements.plist'"), "Message"); } } + + [TestCase (ApplePlatform.MacOSX, "osx-arm64")] + public void CustomAppBundleDir (ApplePlatform platform, string runtimeIdentifiers) + { + var project = "MySimpleApp"; + Configuration.IgnoreIfIgnoredPlatform (platform); + + var project_path = GetProjectPath (project, runtimeIdentifiers: runtimeIdentifiers, platform: platform, out var appPath); + Clean (project_path); + var properties = GetDefaultProperties (runtimeIdentifiers); + var customAppBundleDir = Path.Combine (Cache.CreateTemporaryDirectory (), project + ".app"); + properties ["AppBundleDir"] = customAppBundleDir; + var result = DotNet.AssertBuild (project_path, properties); + } } } diff --git a/tests/dotnet/UnitTests/RegistrarTest.cs b/tests/dotnet/UnitTests/RegistrarTest.cs new file mode 100644 index 0000000000..5213b25905 --- /dev/null +++ b/tests/dotnet/UnitTests/RegistrarTest.cs @@ -0,0 +1,55 @@ +namespace Xamarin.Tests { + [TestFixture] + public class RegistrarTest : TestBaseClass + { + [TestCase (ApplePlatform.MacCatalyst, true)] + [TestCase (ApplePlatform.MacOSX, true)] + [TestCase (ApplePlatform.iOS, false)] + [TestCase (ApplePlatform.TVOS, false)] + public void InvalidStaticRegistrarValidation (ApplePlatform platform, bool validated) + { + var project = "MyRegistrarApp"; + var configuration = "Debug"; + var runtimeIdentifiers = GetDefaultRuntimeIdentifier (platform); + Configuration.IgnoreIfIgnoredPlatform (platform); + + var projectPath = GetProjectPath (project, platform: platform); + Clean (projectPath); + var properties = GetDefaultProperties (); + properties ["Registrar"] = "static"; + // enable the linker (so that the main assembly is modified) + properties ["LinkMode"] = "full"; + properties ["MtouchLink"] = "full"; + + DotNet.AssertBuild (projectPath, properties); + + var appDir = GetAppPath (projectPath, platform, runtimeIdentifiers, configuration); + var asmDir = Path.Combine (appDir, GetRelativeAssemblyDirectory (platform)); + + var appExecutable = Path.Combine (asmDir, project + ".dll"); + + // Save the first version of the main assembly in memory + var firstAssembly = File.ReadAllBytes (appExecutable); + + // Build again, including additional code + properties ["AdditionalDefineConstants"] = "INCLUDED_ADDITIONAL_CODE"; + DotNet.AssertBuild (projectPath, properties); + + // Revert to the original version of the main assembly + File.WriteAllBytes (appExecutable, firstAssembly); + + Environment.SetEnvironmentVariable ("XAMARIN_VALIDATE_STATIC_REGISTRAR_CODE", "1"); + try { + if (validated) { + ExecuteProjectWithMagicWordAndAssert (projectPath, platform, runtimeIdentifiers); + } else if (CanExecute (platform, runtimeIdentifiers)) { + var rv = base.Execute (GetNativeExecutable (platform, appDir), out var output, out _); + Assert.AreEqual (1, rv.ExitCode, "Expected no validation"); + } + } finally { + Environment.SetEnvironmentVariable ("XAMARIN_VALIDATE_STATIC_REGISTRAR_CODE", null); + } + } + } +} + diff --git a/tests/dotnet/UnitTests/TestBaseClass.cs b/tests/dotnet/UnitTests/TestBaseClass.cs index 9bfb20ae37..81d23e5b0f 100644 --- a/tests/dotnet/UnitTests/TestBaseClass.cs +++ b/tests/dotnet/UnitTests/TestBaseClass.cs @@ -40,9 +40,24 @@ namespace Xamarin.Tests { } protected string GetAppPath (string projectPath, ApplePlatform platform, string runtimeIdentifiers, string configuration = "Debug") + { + return Path.Combine (GetBinDir (projectPath, platform, runtimeIdentifiers, configuration), Path.GetFileNameWithoutExtension (projectPath) + ".app"); + } + + protected string GetBinDir (string projectPath, ApplePlatform platform, string runtimeIdentifiers, string configuration = "Debug") + { + return GetBinOrObjDir ("bin", projectPath, platform, runtimeIdentifiers, configuration); + } + + protected string GetObjDir (string projectPath, ApplePlatform platform, string runtimeIdentifiers, string configuration = "Debug") + { + return GetBinOrObjDir ("obj", projectPath, platform, runtimeIdentifiers, configuration); + } + + protected string GetBinOrObjDir (string binOrObj, string projectPath, ApplePlatform platform, string runtimeIdentifiers, string configuration = "Debug") { var appPathRuntimeIdentifier = runtimeIdentifiers.IndexOf (';') >= 0 ? "" : runtimeIdentifiers; - return Path.Combine (Path.GetDirectoryName (projectPath)!, "bin", configuration, platform.ToFramework (), appPathRuntimeIdentifier, Path.GetFileNameWithoutExtension (projectPath) + ".app"); + return Path.Combine (Path.GetDirectoryName (projectPath)!, binOrObj, configuration, platform.ToFramework (), appPathRuntimeIdentifier); } protected string GetOutputPath (string project, string? subdir, string runtimeIdentifiers, ApplePlatform platform, string configuration = "Debug") @@ -275,20 +290,25 @@ namespace Xamarin.Tests { } protected void ExecuteWithMagicWordAndAssert (string executable) + { + var rv = Execute (executable, out var output, out string magicWord); + Assert.That (output.ToString (), Does.Contain (magicWord), "Contains magic word"); + Assert.AreEqual (0, rv.ExitCode, "ExitCode"); + } + + protected Execution Execute (string executable, out StringBuilder output, out string magicWord) { if (!File.Exists (executable)) throw new FileNotFoundException ($"The executable '{executable}' does not exists."); - var magicWord = Guid.NewGuid ().ToString (); + magicWord = Guid.NewGuid ().ToString (); var env = new Dictionary { { "MAGIC_WORD", magicWord }, { "DYLD_FALLBACK_LIBRARY_PATH", null }, // VSMac might set this, which may cause tests to crash. }; - var output = new StringBuilder (); - var rv = Execution.RunWithStringBuildersAsync (executable, Array.Empty (), environment: env, standardOutput: output, standardError: output, timeout: TimeSpan.FromSeconds (15)).Result; - Assert.That (output.ToString (), Does.Contain (magicWord), "Contains magic word"); - Assert.AreEqual (0, rv.ExitCode, "ExitCode"); + output = new StringBuilder (); + return Execution.RunWithStringBuildersAsync (executable, Array.Empty (), environment: env, standardOutput: output, standardError: output, timeout: TimeSpan.FromSeconds (15)).Result; } public static StringBuilder AssertExecute (string executable, params string[] arguments) diff --git a/tests/monotouch-test/ObjCRuntime/Messaging.cs b/tests/monotouch-test/ObjCRuntime/Messaging.cs index 76f6010655..b4fb209e03 100644 --- a/tests/monotouch-test/ObjCRuntime/Messaging.cs +++ b/tests/monotouch-test/ObjCRuntime/Messaging.cs @@ -263,8 +263,23 @@ namespace ObjCRuntime [DllImport (LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")] public extern static void void_objc_msgSend_NSRange_out_NSRange_ref_NSRange (IntPtr receiver, IntPtr selector, _LongNSRange p1, out _LongNSRange p2, ref _LongNSRange p3); + + [DllImport (LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")] + public extern static void void_objc_msgSend_ref_byte_ref_sbyte_ref_short_ref_ushort_ref_int_ref_uint_ref_long_ref_ulong (IntPtr receiver, IntPtr selector, ref EnumB b, ref EnumSB sb, ref EnumS s, ref EnumUS us, ref EnumI i, ref EnumUI ui, ref EnumL l, ref EnumUL ul); + + [DllImport (LIBOBJC_DYLIB, EntryPoint = "objc_msgSend")] + public extern static void void_objc_msgSend_out_byte_out_sbyte_out_short_out_ushort_out_int_out_uint_out_long_out_ulong (IntPtr receiver, IntPtr selector, out EnumB b, out EnumSB sb, out EnumS s, out EnumUS us, out EnumI i, out EnumUI ui, out EnumL l, out EnumUL ul); } + public enum EnumB : byte { a, b = 10 }; + public enum EnumSB : sbyte { a, b = 11 }; + public enum EnumS : short { a, b = 12 }; + public enum EnumUS : ushort { a, b = 13 }; + public enum EnumI : int { a, b = 14 }; + public enum EnumUI : uint { a, b = 15 }; + public enum EnumL : long { a, b = 16 }; + public enum EnumUL : ulong { a, b = 17 }; + public struct _LongNSRange { public long Location; public long Length; diff --git a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs index c8a78e1b28..c35b6a0f83 100644 --- a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs +++ b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs @@ -1694,21 +1694,38 @@ namespace MonoTouchFixtures.ObjCRuntime { } [Register ("UnderlyingEnumValues")] - class UnderlyingEnumValues : NSObject + internal class UnderlyingEnumValues : NSObject { - enum B : byte { a }; - enum SB : sbyte { a }; - enum S : short { a }; - enum US : ushort { a }; - enum I : int { a }; - enum UI : uint { a }; - enum L : long { a }; - enum UL : ulong { a }; - [Export ("Foo:a:b:c:d:e:f:g:h")] - void Foo (B b, SB sb, S s, US us, I i, UI ui, L l, UL ul) + void Foo (EnumB b, EnumSB sb, EnumS s, EnumUS us, EnumI i, EnumUI ui, EnumL l, EnumUL ul) { } + + [Export ("ByRef:a:b:c:d:e:f:g:")] + void ByRef (ref EnumB b, ref EnumSB sb, ref EnumS s, ref EnumUS us, ref EnumI i, ref EnumUI ui, ref EnumL l, ref EnumUL ul) + { + b = EnumB.b; + sb = EnumSB.b; + s = EnumS.b; + us = EnumUS.b; + i = EnumI.b; + ui = EnumUI.b; + l = EnumL.b; + ul = EnumUL.b; + } + + [Export ("Out:a:b:c:d:e:f:g:")] + void Out (out EnumB b, out EnumSB sb, out EnumS s, out EnumUS us, out EnumI i, out EnumUI ui, out EnumL l, out EnumUL ul) + { + b = EnumB.b; + sb = EnumSB.b; + s = EnumS.b; + us = EnumUS.b; + i = EnumI.b; + ui = EnumUI.b; + l = EnumL.b; + ul = EnumUL.b; + } } // It should be possible to export two identically named nested types. @@ -5456,6 +5473,43 @@ namespace MonoTouchFixtures.ObjCRuntime { } } #endif // !__WATCHOS__ && !__TVOS__ + + [Test] + public void RefEnumValues () + { + EnumB b = 0; + EnumSB sb = 0; + EnumS s = 0; + EnumUS us = 0; + EnumI i = 0; + EnumUI ui = 0; + EnumL l = 0; + EnumUL ul = 0; + + using (var obj = new UnderlyingEnumValues ()) { + b = 0; sb = 0; s = 0; us = 0; i = 0; ui = 0; l = 0; ul = 0; + Messaging.void_objc_msgSend_ref_byte_ref_sbyte_ref_short_ref_ushort_ref_int_ref_uint_ref_long_ref_ulong (obj.Handle, Selector.GetHandle ("ByRef:a:b:c:d:e:f:g:"), ref b, ref sb, ref s, ref us, ref i, ref ui, ref l, ref ul); + Assert.AreEqual (EnumB.b, b, "ref: B"); + Assert.AreEqual (EnumSB.b, sb, "ref: SB"); + Assert.AreEqual (EnumS.b, s, "ref: S"); + Assert.AreEqual (EnumUS.b, us, "ref: US"); + Assert.AreEqual (EnumI.b, i, "ref: I"); + Assert.AreEqual (EnumUI.b, ui, "ref: UI"); + Assert.AreEqual (EnumL.b, l, "ref: L"); + Assert.AreEqual (EnumUL.b, ul, "ref: UL"); + + b = 0; sb = 0; s = 0; us = 0; i = 0; ui = 0; l = 0; ul = 0; + Messaging.void_objc_msgSend_out_byte_out_sbyte_out_short_out_ushort_out_int_out_uint_out_long_out_ulong (obj.Handle, Selector.GetHandle ("Out:a:b:c:d:e:f:g:"), out b, out sb, out s, out us, out i, out ui, out l, out ul); + Assert.AreEqual (EnumB.b, b, "out: B"); + Assert.AreEqual (EnumSB.b, sb, "out: SB"); + Assert.AreEqual (EnumS.b, s, "out: S"); + Assert.AreEqual (EnumUS.b, us, "out: US"); + Assert.AreEqual (EnumI.b, i, "out: I"); + Assert.AreEqual (EnumUI.b, ui, "out: UI"); + Assert.AreEqual (EnumL.b, l, "out: L"); + Assert.AreEqual (EnumUL.b, ul, "out: UL"); + } + } } #if !__WATCHOS__ diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index ded2f901dd..37a763de1f 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -2118,7 +2118,7 @@ namespace Registrar { AutoIndentStringBuilder full_token_references = new AutoIndentStringBuilder (); uint full_token_reference_count; - List registered_assemblies = new List (); + List<(AssemblyDefinition Assembly, string Name)> registered_assemblies = new List<(AssemblyDefinition Assembly, string Name)> (); bool IsPlatformType (TypeReference type) { @@ -2853,9 +2853,9 @@ namespace Registrar { if (string.IsNullOrEmpty (single_assembly)) { foreach (var assembly in GetAssemblies ()) - registered_assemblies.Add (GetAssemblyName (assembly)); + registered_assemblies.Add (new (assembly, GetAssemblyName (assembly))); } else { - registered_assemblies.Add (single_assembly); + registered_assemblies.Add (new (GetAssemblies ().Single (v => GetAssemblyName (v) == single_assembly), single_assembly)); } foreach (var @class in allTypes) { @@ -3154,22 +3154,24 @@ namespace Registrar { map.AppendLine (); } - map.AppendLine ("static const char *__xamarin_registration_assemblies []= {"); + map.AppendLine ("static const MTAssembly __xamarin_registration_assemblies [] = {"); int count = 0; foreach (var assembly in registered_assemblies) { count++; if (count > 1) map.AppendLine (", "); - map.Append ("\""); - map.Append (assembly); - map.Append ("\""); + map.Append ("{ \""); + map.Append (assembly.Name); + map.Append ("\", \""); + map.Append (assembly.Assembly.MainModule.Mvid.ToString ()); + map.Append ("\" }"); } map.AppendLine (); map.AppendLine ("};"); map.AppendLine (); if (full_token_reference_count > 0) { - map.AppendLine ("static const struct MTFullTokenReference __xamarin_token_references [] = {"); + map.AppendLine ("static const MTFullTokenReference __xamarin_token_references [] = {"); map.AppendLine (full_token_references); map.AppendLine ("};"); map.AppendLine (); @@ -4876,7 +4878,13 @@ namespace Registrar { default: throw ErrorHelper.CreateError (99, Errors.MX0099, $"unsupported tokentype ({member.MetadataToken.TokenType}) for {member.FullName}"); } - full_token_references.AppendFormat ("\t\t{{ /* #{3} = 0x{4:X} */ \"{0}\", 0x{1:X}, 0x{2:X} }},\n", GetAssemblyName (member.Module.Assembly), member.Module.MetadataToken.ToUInt32 (), member.MetadataToken.ToUInt32 (), full_token_reference_count, rv); + var assemblyIndex = registered_assemblies.FindIndex (v => v.Assembly == member.Module.Assembly); + var assemblyName = registered_assemblies [assemblyIndex].Name; + var moduleToken = member.Module.MetadataToken.ToUInt32 (); + var moduleName = member.Module.Name; + var memberToken = member.MetadataToken.ToUInt32 (); + var memberName = member.FullName; + full_token_references.Append ($"\t\t{{ /* #{full_token_reference_count} = 0x{rv:X} */ {assemblyIndex} /* {assemblyName} */, 0x{moduleToken:X} /* {moduleName} */, 0x{memberToken:X} /* {memberName} */ }},\n"); return rv; } @@ -4908,7 +4916,7 @@ namespace Registrar { /* The assembly must be a registered one, and only within the first 128 assemblies */ var assembly_name = GetAssemblyName (member.Module.Assembly); - var index = registered_assemblies.IndexOf (assembly_name); + var index = registered_assemblies.FindIndex (v => v.Name == assembly_name); if (index < 0 || index > 127) return CreateFullTokenReference (member); diff --git a/tools/devops/automation/scripts/TestResults.Tests.ps1 b/tools/devops/automation/scripts/TestResults.Tests.ps1 index bd80c7c3b8..84dafc9567 100644 --- a/tools/devops/automation/scripts/TestResults.Tests.ps1 +++ b/tools/devops/automation/scripts/TestResults.Tests.ps1 @@ -140,22 +140,27 @@ Describe "TestResults tests" { New-Item -Path "$testDirectory/TestSummary-prefixintrospection-2" -Name "TestSummary.md" -Value "SummaryE" -Force New-Item -Path "$testDirectory/TestSummary-prefixmtouch-3" -Name "TestSummary.md" -Value "SummaryF" -Force - $labels = "linker;introspection".Split(";") + $labels = @("linker", "introspection", "monotouch-test") $testResults = New-TestSummaryResults -Path "$testDirectory" -Labels $labels -TestPrefix "prefix" Remove-Item -Path $testDirectory -Recurse - $testResults.count | Should -Be 2 + $testResults.count | Should -Be $labels.count $testResults[0].Label | Should -Be "linker" $testResults[0].Context | Should -Be " - linker" - $testResults[0].ResultsPath | Should -Be "$Env:PWD/subdir/TestSummary-prefixlinker-200/TestSummary.md" + $testResults[0].ResultsPath | Should -Be "$(get-location)/subdir/TestSummary-prefixlinker-200/TestSummary.md" $testResults[0].TestsJobStatus | Should -Be "yay" $testResults[1].Label | Should -Be "introspection" $testResults[1].Context | Should -Be " - introspection" - $testResults[1].ResultsPath | Should -Be "$Env:PWD/subdir/TestSummary-prefixintrospection-2/TestSummary.md" + $testResults[1].ResultsPath | Should -Be "$(get-location)/subdir/TestSummary-prefixintrospection-2/TestSummary.md" $testResults[1].TestsJobStatus | Should -Be "nay" + + $testResults[2].Label | Should -Be "monotouch_test" + $testResults[2].Context | Should -Be " - monotouch_test" + $testResults[2].ResultsPath | Should -Be "./subdir/TestSummary-prefixmonotouch_test-1/TestSummary.md" + $testResults[2].TestsJobStatus | Should -Be "" } } diff --git a/tools/devops/automation/scripts/TestResults.psm1 b/tools/devops/automation/scripts/TestResults.psm1 index 78234bd8b1..0b1d9f6984 100644 --- a/tools/devops/automation/scripts/TestResults.psm1 +++ b/tools/devops/automation/scripts/TestResults.psm1 @@ -28,14 +28,14 @@ class TestResults { } [bool] IsSuccess() { - Write-Debug "\t$($this.Label) - IsSuccess()" + Write-Debug "`t$($this.Label) - IsSuccess()" if ($this.NotTestSummaryLabels.Contains($this.Label)) { - Write-Debug "\t\t$($this.Label) - Found special label $($this.Label), checking only status." + Write-Debug "`t`t$($this.Label) - Found special label $($this.Label), checking only status." return $this.TestsJobStatus -eq "Succeeded" } else { $hasResultsPath = Test-Path $this.ResultsPath -PathType Leaf - Write-Debug "\t\t$($this.Label) - Path $($this.ResultsPath) exits? $hasResultsPath" - Write-Debug "\t\t$($this.Label) - Test status: $($this.TestsJobStatus)" + Write-Debug "`t`t$($this.Label) - Path $($this.ResultsPath) exists? $hasResultsPath" + Write-Debug "`t`t$($this.Label) - Test status: $($this.TestsJobStatus)" return $hasResultsPath -and ($this.TestsJobStatus -eq "Succeeded") } } @@ -91,13 +91,13 @@ class TestResults { [object] GetPassedTests() { Write-Debug "$($this.Label) - GetPassedTests()" if ($this.Passed -eq -1 -or $this.Failed -eq -1) { - Write-Debug "\t$($this.Label) - Calculate results." + Write-Debug "`t$($this.Label) - Calculate results." # the result file is diff if the result was a success or not if ($this.IsSuccess()) { - Write-Debug "$($this.Label) - IsSuccess() => TRUE" + Write-Debug "`t$($this.Label) - IsSuccess() => TRUE" $this.Failed = 0 if ($this.NotTestSummaryLabels.Contains($this.Label)) { - Write-Debug "\t\t$($this.Label) - Found special label $($this.Label), adding a single pass." + Write-Debug "`t`t$($this.Label) - Found special label $($this.Label), adding a single pass." $this.Passed = 1 } else { # in this case, the file contains a single line with the number and the following @@ -106,27 +106,26 @@ class TestResults { $regexp = "(# :tada: All )(?[0-9]+)( tests passed :tada:)" $content = Get-Content $this.ResultsPath | Select -First 1 if ($content -eq "# No tests selected.") { - Write-Debug "\t\tNo tests selected" + Write-Debug "`t`tNo tests selected" $this.Passed = 0 } elseif ($content -match $regexp) { - Write-Debug "Did match regexp" $this.Passed = $matches.passed -as [int] - Write-Debug "Passed tests count: $($this.Passed)" + Write-Debug "`tPassed tests count: $($this.Passed)" } else { - throw "Unknown result pattern '$content'" + throw "Unable to understand the test result '$content' for test '$($this.Label)'" } } } else { - Write-Debug "IsSuccess() => FALSE" + Write-Debug "`t$($this.Label) - IsSuccess() => FALSE" $fileIsPresent = Test-Path $this.ResultsPath -PathType Leaf if ($this.TestsJobStatus -eq "" -or -not (Test-Path $this.ResultsPath -PathType Leaf)) { - Write-Debug "\t\tTests job status: $($this.TestsJobStatus)" - Write-Debug "\t\tNot Found results path: $fileIsPresent" + Write-Debug "`t`tTests job status: $($this.TestsJobStatus)" + Write-Debug "`t`tNot Found results path: $fileIsPresent" $this.Passed = -2 $this.Failed = -2 } else { if ($this.NotTestSummaryLabels.Contains($this.Label)) { - Write-Debug "\t\tFound special label $($this.Label), adding a single fail." + Write-Debug "`t`tFound special label $($this.Label), adding a single fail." $this.Passed = 0 $this.Failed = 1 } else { @@ -160,20 +159,24 @@ class TestResults { # 4 tests failed, 144 tests passed. $regexp = "(\)(?[0-9]+)( tests failed, )(?[0-9]+)( tests passed\.\)" if ($content -match $regexp) { - Write-Debug "\t\tMatched regexpt." + Write-Debug "`t`tMatched regexpt." $this.Passed = $matches.passed -as [int] $this.Failed = $matches.failed -as [int] - Write-Debug "\t\tPassed: $($this.Passed) Failed: $($this.Failed)" } else { - throw "Unknown result pattern '$content'" + Write-Debug "`t`tAdding a single fail because unexpected contents found: $($content)" + $this.Passed = 0 + $this.Failed = 1 } } else { - throw "Unknown result pattern of a failed test" + Write-Debug "`t`tNo found, adding a single fail" + $this.Passed = 0 + $this.Failed = 1 } } } } } + Write-Debug "`t$($this.Label) - Passed: $($this.Passed) Failed: $($this.Failed)" return [PSCustomObject]@{ Passed = $this.Passed Failed = $this.Failed @@ -241,7 +244,7 @@ class ParallelTestsResults { } # we return the patterns we already know - if ($failedTests -eq 0) { + if ($failedTests -eq 0 -and $crashedTests -eq 0) { return ":tada: All $passedTests tests passed :tada:" } else { return "$crashedTests tests crashed, $failedTests tests failed, $passedTests tests passed." @@ -307,8 +310,8 @@ class ParallelTestsResults { } else { # create a detail per test result with the name of the test and will contain the exact summary $stringBuilder.AppendLine("$($result.Failed) tests failed, $($result.Passed) tests passed.") + $stringBuilder.AppendLine("
") if (Test-Path -Path $r.ResultsPath -PathType Leaf) { - $stringBuilder.AppendLine("
") $stringBuilder.AppendLine("") $foundTests = $false foreach ($line in Get-Content -Path $r.ResultsPath) @@ -321,12 +324,8 @@ class ParallelTestsResults { } } } - $stringBuilder.AppendLine("
") - $stringBuilder.AppendLine("") } else { - $stringBuilder.AppendLine("
") $stringBuilder.AppendLine(" Test has no summary file.") - $stringBuilder.AppendLine("
") } $stringBuilder.AppendLine("
") $stringBuilder.AppendLine("") @@ -402,7 +401,7 @@ function New-TestSummaryResults { $environmentVariable = "TESTS_JOBSTATUS_$($label.ToUpper())" $status = [Environment]::GetEnvironmentVariable($environmentVariable) - Write-Host "Test results for $label is '$status'" + Write-Debug "Test results for $label is '$status'" $testSummaryDirectoryExpression = "$Env:SYSTEM_DEFAULTWORKINGDIRECTORY\Reports\TestSummary-$TestPrefix$label-*" @@ -411,7 +410,10 @@ function New-TestSummaryResults { $testSummaryDirectories = Get-ChildItem -Path $Path -Directory -Filter $directoryFilter if ($testSummaryDirectories.length -eq 0) { - Write-Host "WARNING: Found no directories matching $directoryFilter for label $label" + Write-Debug "WARNING: Found no directories matching $directoryFilter for label $label and prefix $TestPrefix" + $testSummaryPath = Join-Path $Path "TestSummary-$TestPrefix$label-1" "TestSummary.md" + $result = New-TestResults -Path $testSummaryPath -Status $status -Label $label -Context "$Env:CONTEXT - $label" -Attempt 1 + $testResults += $result continue } @@ -436,10 +438,10 @@ function New-TestSummaryResults { $testAttemptPath = $testSummaryDirectory.Name $testSummaryPath = Join-Path $testAttemptPath "TestSummary.md" - Write-Host "Found "$attemptDirectories.count" directories, selected $testSummaryDirectory and final path is $testSummaryPath" + Write-Debug "Found $($attemptDirectories.count) directories, selected $testSummaryDirectory and final path is $testSummaryPath" if (-not (Test-Path -Path $testSummaryPath -PathType Leaf)) { - Write-Host "WARNING: Path $testSummaryPath does not exist" + Write-Debug "WARNING: Path $testSummaryPath does not exist" } $result = New-TestResults -Path $testSummaryPath -Status $status -Label $label -Context "$Env:CONTEXT - $label" -Attempt $testAttempt diff --git a/tools/devops/automation/templates/build/api-diff-process-results.yml b/tools/devops/automation/templates/build/api-diff-process-results.yml index dd588045f5..2ae100692e 100644 --- a/tools/devops/automation/templates/build/api-diff-process-results.yml +++ b/tools/devops/automation/templates/build/api-diff-process-results.yml @@ -49,7 +49,7 @@ steps: inputs: dropServiceURI: 'https://devdiv.artifacts.visualstudio.com/DefaultCollection' dropMetadataContainerName: 'DropMetadata-ChangeDetection' - buildNumber: 'xamarin-macios/detected-changes/$(Build.BuildNumber)/$(Build.BuildId)' + buildNumber: 'xamarin-macios/detected-changes/$(Build.BuildNumber)/$(Build.BuildId)-$(System.JobAttempt)' sourcePath: '$(System.DefaultWorkingDirectory)/change-detection/results/' detailedLog: true usePat: true @@ -57,7 +57,7 @@ steps: # Process the github comment and publish it - pwsh: | Import-Module $Env:SYSTEM_DEFAULTWORKINGDIRECTORY\xamarin-macios\tools\devops\automation\scripts\MaciosCI.psd1 - $vsdropsChangeDetectionPrefix = "https://vsdrop.corp.microsoft.com/file/v1/xamarin-macios/detected-changes/$Env:BUILD_BUILDNUMBER/$Env:BUILD_BUILDID/;/" + $vsdropsChangeDetectionPrefix = "https://vsdrop.corp.microsoft.com/file/v1/xamarin-macios/detected-changes/$Env:BUILD_BUILDNUMBER/$Env:BUILD_BUILDID-$Env:SYSTEM_JOBATTEMPT/;/" $rootDirectory = Join-Path "$Env:SYSTEM_DEFAULTWORKINGDIRECTORY" "change-detection" "results" diff --git a/tools/devops/automation/templates/build/build-nugets.yml b/tools/devops/automation/templates/build/build-nugets.yml index 78d3e4c06d..706a292113 100644 --- a/tools/devops/automation/templates/build/build-nugets.yml +++ b/tools/devops/automation/templates/build/build-nugets.yml @@ -19,6 +19,6 @@ steps: displayName: 'Publish Artifact: build-binlogs' inputs: targetPath: $(Build.ArtifactStagingDirectory)/build-binlogs - artifactName: build-binlogs-$(Build.BuildId) + artifactName: build-binlogs-$(Build.BuildId)-$(System.JobAttempt) continueOnError: true condition: and(succeededOrFailed(), contains(variables['configuration.BuildNugets'], 'True')) diff --git a/tools/devops/automation/templates/tests/publish-html.yml b/tools/devops/automation/templates/tests/publish-html.yml index 9964b7f798..1121c1f181 100644 --- a/tools/devops/automation/templates/tests/publish-html.yml +++ b/tools/devops/automation/templates/tests/publish-html.yml @@ -49,24 +49,28 @@ steps: # build a message with all the content of all tests, to do so, we get the labels and to pass them to pwsh we do a join with ; # as the separator - pwsh: | - $vsdropsIndex="$Env:VSDROPSPREFIX/$Env:BUILD_BUILDNUMBER/$Env:BUILD_BUILDID/" - Import-Module $Env:SYSTEM_DEFAULTWORKINGDIRECTORY\xamarin-macios\tools\devops\automation\scripts\MaciosCI.psd1 - $DebugPreference = "Continue" # enable debug messages + try { + $vsdropsIndex="$Env:VSDROPSPREFIX/$Env:BUILD_BUILDNUMBER/$Env:BUILD_BUILDID-$Env:SYSTEM_JOBATTEMPT/" + Import-Module $Env:SYSTEM_DEFAULTWORKINGDIRECTORY\xamarin-macios\tools\devops\automation\scripts\MaciosCI.psd1 + $DebugPreference = "Continue" # enable debug messages - $labels = "$Env:LABELS".Split(";") + $labels = "$Env:LABELS".Split(";") - $testResults = New-TestSummaryResults -Path "$Env:SYSTEM_DEFAULTWORKINGDIRECTORY\Reports" -Labels $labels -TestPrefix "${{ parameters.testPrefix }}" + $testResults = New-TestSummaryResults -Path "$Env:SYSTEM_DEFAULTWORKINGDIRECTORY\Reports" -Labels $labels -TestPrefix "${{ parameters.testPrefix }}" - $parallelResults = New-ParallelTestsResults -Results $testResults -Context "$Env:CONTEXT" -TestPrefix "${{ parameters.testPrefix }}" -VSDropsIndex $vsdropsIndex - $success = $parallelResults.IsSuccess() - $emoji = ":rocket:" - if (-not $success) { - Set-PipelineResult -Status partiallySucceeded - $emoji = ":fire:" - } + $parallelResults = New-ParallelTestsResults -Results $testResults -Context "$Env:CONTEXT" -TestPrefix "${{ parameters.testPrefix }}" -VSDropsIndex $vsdropsIndex + $success = $parallelResults.IsSuccess() + $emoji = ":rocket:" + if (-not $success) { + Set-PipelineResult -Status partiallySucceeded + $emoji = ":fire:" + } - $gihubComments = New-GitHubCommentsObject -Org "xamarin" -Repo "xamarin-macios" -Token $Env:GITHUB_TOKEN -Hash $Env:GIT_HASH -Debug - $result = $gihubComments.NewCommentFromObject("Test results", $emoji, $parallelResults) + $gihubComments = New-GitHubCommentsObject -Org "xamarin" -Repo "xamarin-macios" -Token $Env:GITHUB_TOKEN -Hash $Env:GIT_HASH -Debug + $result = $gihubComments.NewCommentFromObject("Test results", $emoji, $parallelResults) + } catch { + New-GitHubComment -Header "Failed to compute test summaries on $Env:CONTEXT" -Emoji ":fire:" -Description "Failed to compute test summaries: $_." + } env: LABELS: ${{ join(';', parameters.simTestsConfigurations) }} BUILD_REVISION: $(Build.SourceVersion) diff --git a/tools/devops/automation/templates/tests/run-tests.yml b/tools/devops/automation/templates/tests/run-tests.yml index f153369b63..547588265e 100644 --- a/tools/devops/automation/templates/tests/run-tests.yml +++ b/tools/devops/automation/templates/tests/run-tests.yml @@ -175,7 +175,7 @@ steps: echo "##vso[task.setvariable variable=TESTS_BOT;isOutput=true]$AGENT_NAME" # uri used to create the vsdrops index using full uri - export VSDROPS_URI="$VSDROPSPREFIX/$BUILD_BUILDNUMBER/$BUILD_BUILDID/$PARAMETERS_TESTPREFIX;/tests/" + export VSDROPS_URI="$VSDROPSPREFIX/$BUILD_BUILDNUMBER/$BUILD_BUILDID-$SYSTEM_JOBATTEMPT/$PARAMETERS_TESTPREFIX;/tests/" # assume something is going to fail echo "##vso[task.setvariable variable=TESTS_JOBSTATUS;isOutput=true]Failed" @@ -218,7 +218,7 @@ steps: displayName: 'Publish Artifact: Simulator diagnostic info' inputs: targetPath: $(System.DefaultWorkingDirectory)/diagnostic-sim-output - artifactName: diagnostic-simulator-info-$(Build.BuildId)-${{ parameters.label }} + artifactName: diagnostic-simulator-info-$(Build.BuildId)-$(System.JobAttempt)-${{ parameters.label }} condition: and(eq(variables['system.debug'], true), succeededOrFailed()) continueOnError: true diff --git a/tools/mtouch/Errors.designer.cs b/tools/mtouch/Errors.designer.cs index 9981c4001b..295403782a 100644 --- a/tools/mtouch/Errors.designer.cs +++ b/tools/mtouch/Errors.designer.cs @@ -4113,5 +4113,23 @@ namespace Xamarin.Bundler { return ResourceManager.GetString("MX8042", resourceCulture); } } + + /// + /// Looks up a localized string similar to An exception occurred while validating the static registrar code for {0}: {1}. + /// + public static string MX8043 { + get { + return ResourceManager.GetString("MX8043", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to The assembly {0} has been modified since the app was built, invalidating the generated static registrar code. The MVID for the loaded assembly is {1}, while the MVID for the assembly the generated static registrar code corresponds to is {2}.. + /// + public static string MX8044 { + get { + return ResourceManager.GetString("MX8044", resourceCulture); + } + } } } diff --git a/tools/mtouch/Errors.resx b/tools/mtouch/Errors.resx index 2c1cadaed8..73fee07470 100644 --- a/tools/mtouch/Errors.resx +++ b/tools/mtouch/Errors.resx @@ -2171,4 +2171,16 @@ 1: exception info + + + An exception occurred while validating the static registrar code for {0}: {1} + + 0: name of an assembly + 1: exception info + + + + + The assembly {0} has been modified since the app was built, invalidating the generated static registrar code. The MVID for the loaded assembly is {1}, while the MVID for the assembly the generated static registrar code corresponds to is {2}. +