From ab46841563645e4c415191d113dd72c1248fe220 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 30 May 2022 11:30:50 +0200 Subject: [PATCH 01/15] [xharness] Redirect stdout/stderr for watch apps. (#15140) I don't remember why I excluded watch apps, and it seems to work locally, so let's see how it goes. Hopefully we'll get better diagnostics when something goes wrong. --- tests/xharness/AppRunner.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/xharness/AppRunner.cs b/tests/xharness/AppRunner.cs index 2b0dce9ca68a..03213f28a7aa 100644 --- a/tests/xharness/AppRunner.cs +++ b/tests/xharness/AppRunner.cs @@ -324,12 +324,10 @@ public async Task RunAsync () if (!await FindSimulatorAsync ()) return 1; - if (runMode != RunMode.WatchOS) { - var stdout_log = Logs.CreateFile ($"stdout-{Harness.Helpers.Timestamp}.log", "Standard output"); - var stderr_log = Logs.CreateFile ($"stderr-{Harness.Helpers.Timestamp}.log", "Standard error"); - args.Add (new SetStdoutArgument (stdout_log)); - args.Add (new SetStderrArgument (stderr_log)); - } + var stdout_log = Logs.CreateFile ($"stdout-{Harness.Helpers.Timestamp}.log", "Standard output"); + var stderr_log = Logs.CreateFile ($"stderr-{Harness.Helpers.Timestamp}.log", "Standard error"); + args.Add (new SetStdoutArgument (stdout_log)); + args.Add (new SetStderrArgument (stderr_log)); var simulators = new [] { simulator, companionSimulator }.Where (s => s != null); var systemLogs = new List (); From ab7f0784ef8be9a4fd43134c327d8a82cd5f9404 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 30 May 2022 11:32:09 +0200 Subject: [PATCH 02/15] Bump maccore. (#15141) --- mk/xamarin.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/xamarin.mk b/mk/xamarin.mk index 118927da2a28..5554b4536526 100644 --- a/mk/xamarin.mk +++ b/mk/xamarin.mk @@ -7,7 +7,7 @@ MONO_BRANCH := $(shell cd $(MONO_PATH) 2> /dev/null && git symbolic-ref --sho endif ifdef ENABLE_XAMARIN -NEEDED_MACCORE_VERSION := 0f0ca14cf22de341b0e1e8d6109e8b8753ada903 +NEEDED_MACCORE_VERSION := 29e384e9e3eada3066d9b70c03c48803876a9ea6 NEEDED_MACCORE_BRANCH := main MACCORE_DIRECTORY := maccore From 6ecc102b5b259e435699972c1a9f3265c66bff7d Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 30 May 2022 11:33:11 +0200 Subject: [PATCH 03/15] [msbuild] Use the full path to the symbols list file. Fixes #15046. (#15105) Give the full path to the symbols list file in the extension project to the main project, so that strip can find it. When building a solution remotely from Windows, we can't compute a relative path between projects, because they're laid out differently on disk. This means that we have to use full paths when passing paths between projects (such as the path to the symbol list file). Fixes https://github.com/xamarin/xamarin-macios/issues/15046. --- msbuild/Xamarin.Shared/Xamarin.Shared.targets | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index 76c143cfc870..92dff17e2ef7 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -2389,6 +2389,17 @@ Copyright (C) 2018 Microsoft. All rights reserved. + + + + + <_PostProcessingItem Include="@(_ResolvedNativeReference->'$(_AppBundleName)$(AppBundleExtension/$(_AppFrameworksRelativePath)%(Filename).framework/%(Filename)')" Condition="'%(_ResolvedNativeReference.Kind' == 'Framework'"> @@ -2409,7 +2420,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. %(_ResolvedNativeReference.Filename)%(_ResolvedNativeReference.Extension).dSYM <_PostProcessingItem Include="$([System.IO.Path]::GetFileName('$(AppBundleDir)'))/$(_NativeExecutableRelativePath)" Condition="'$(IsWatchApp)' != 'true'"> - $(_MtouchSymbolsList) + $(_SymbolsListFullPath) $(_AppBundleName)$(AppBundleExtension).dSYM @@ -2425,10 +2436,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. - - <_PostProcessingItem Include="@(_AppExtensionPostProcessingItems -> '$(_AppBundleName)$(AppBundleExtension)\$(_AppPlugInsRelativePath)%(Identity)')" Condition="@(_AppExtensionPostProcessingItems->Count()) > 0"> - $([MSBuild]::MakeRelative('$(MSBuildProjectDirectory)','%(_AppExtensionPostProcessingItems.SourceProjectPath)/%(_AppExtensionPostProcessingItems.SymbolFile)')) - + <_PostProcessingItem Include="@(_AppExtensionPostProcessingItems -> '$(_AppBundleName)$(AppBundleExtension)\$(_AppPlugInsRelativePath)%(Identity)')" Condition="@(_AppExtensionPostProcessingItems->Count()) > 0" /> From 96116c400d5779fb20f21d910083a2eb21ee8c72 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 30 May 2022 11:34:08 +0200 Subject: [PATCH 04/15] [appkit] Remove leftover code made obsolete by newrefcount. (#15103) Remove code that we needed at some point due to memory related issues. These issues were fixed several years ago (newrefcount), so we no longer need this code (in fact it causes problems, see #15089). --- src/appkit.cs | 76 +++++++++++++++++++-------------------------------- 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/src/appkit.cs b/src/appkit.cs index 3d8395449e7a..e39e19a7bedd 100644 --- a/src/appkit.cs +++ b/src/appkit.cs @@ -4896,23 +4896,18 @@ partial interface NSComboBox { void Add (NSObject object1); [Export ("addItemsWithObjectValues:")] - [PostGet ("Values")] void Add (NSObject [] items); [Export ("insertItemWithObjectValue:atIndex:")] - [PostGet ("Values")] void Insert (NSObject object1, nint index); [Export ("removeItemWithObjectValue:")] - [PostGet ("Values")] void Remove (NSObject object1); [Export ("removeItemAtIndex:")] - [PostGet ("Values")] void RemoveAt (nint index); [Export ("removeAllItems")] - [PostGet ("Values")] void RemoveAll (); [Export ("selectItemWithObjectValue:")] @@ -5020,23 +5015,18 @@ partial interface NSComboBoxCell { void Add (NSObject object1); [Export ("addItemsWithObjectValues:")] - [PostGet ("Values")] void Add (NSObject [] items); [Export ("insertItemWithObjectValue:atIndex:")] - [PostGet ("Values")] void Insert (NSObject object1, nint index); [Export ("removeItemWithObjectValue:")] - [PostGet ("Values")] void Remove (NSObject object1); [Export ("removeItemAtIndex:")] - [PostGet ("Values")] void RemoveAt (nint index); [Export ("removeAllItems")] - [PostGet ("Values")] void RemoveAll (); [Export ("selectItemWithObjectValue:")] @@ -5920,11 +5910,9 @@ partial interface NSDocument : NSUserActivityRestoring { void SetWindow ([NullAllowed] NSWindow window); [Export ("addWindowController:")] - [PostGet ("WindowControllers")] void AddWindowController (NSWindowController windowController); [Export ("removeWindowController:")] - [PostGet ("WindowControllers")] void RemoveWindowController (NSWindowController windowController); [Export ("showWindows")] @@ -6155,11 +6143,9 @@ partial interface NSDocumentController : NSWindowRestoration, NSCoding { NSDocument DocumentForWindow (NSWindow window); [Export ("addDocument:")] - [PostGet ("Documents")] void AddDocument (NSDocument document); [Export ("removeDocument:")] - [PostGet ("Documents")] void RemoveDocument (NSDocument document); [Export ("newDocument:")] @@ -13213,11 +13199,9 @@ partial interface NSRulerView { nfloat RequiredThickness { get; } [Export ("addMarker:")] - [PostGet ("Markers")] void AddMarker (NSRulerMarker marker); [Export ("removeMarker:")] - [PostGet ("Markers")] void RemoveMarker (NSRulerMarker marker); [Export ("trackMarker:withMouseEvent:")] @@ -14944,16 +14928,16 @@ interface NSSplitViewController : NSSplitViewDelegate, NSUserInterfaceValidation [Export ("splitViewItems", ArgumentSemantic.Copy)] NSSplitViewItem [] SplitViewItems { get; set; } - [Export ("addSplitViewItem:")][PostGet ("SplitViewItems")] + [Export ("addSplitViewItem:")] void AddSplitViewItem (NSSplitViewItem splitViewItem); - [Export ("insertSplitViewItem:atIndex:")][PostGet ("SplitViewItems")] + [Export ("insertSplitViewItem:atIndex:")] void InsertSplitViewItem (NSSplitViewItem splitViewItem, nint index); - [Export ("removeSplitViewItem:")][PostGet ("SplitViewItems")] + [Export ("removeSplitViewItem:")] void RemoveSplitViewItem (NSSplitViewItem splitViewItem); - [Export ("splitViewItemForViewController:")][PostGet ("SplitViewItems")] + [Export ("splitViewItemForViewController:")] NSSplitViewItem GetSplitViewItem (NSViewController viewController); [Mac (10,11)] @@ -15193,19 +15177,19 @@ interface NSStackView { [Static, Export ("stackViewWithViews:")] NSStackView FromViews (NSView [] views); - [Export ("addView:inGravity:")][PostGet ("Views")] + [Export ("addView:inGravity:")] void AddView (NSView aView, NSStackViewGravity gravity); - [Export ("insertView:atIndex:inGravity:")][PostGet ("Views")] + [Export ("insertView:atIndex:inGravity:")] void InsertView (NSView aView, nuint index, NSStackViewGravity gravity); - [Export ("removeView:")][PostGet ("Views")] + [Export ("removeView:")] void RemoveView (NSView aView); [Export ("viewsInGravity:")] NSView [] ViewsInGravity (NSStackViewGravity gravity); - [Export ("setViews:inGravity:")][PostGet ("Views")] + [Export ("setViews:inGravity:")] void SetViews (NSView [] views, NSStackViewGravity gravity); [Export ("setVisibilityPriority:forView:")] @@ -15904,10 +15888,10 @@ partial interface NSView : NSDraggingDestination, NSAnimatablePropertyContainer, [Export ("viewDidUnhide")] void ViewDidUnhide (); - [Export ("addSubview:")][PostGet ("Subviews")] + [Export ("addSubview:")] void AddSubview (NSView aView); - [Export ("addSubview:positioned:relativeTo:")][PostGet ("Subviews")] + [Export ("addSubview:positioned:relativeTo:")] void AddSubview (NSView aView, NSWindowOrderingMode place, [NullAllowed] NSView otherView); [Export ("viewWillMoveToWindow:")] @@ -15929,16 +15913,12 @@ partial interface NSView : NSDraggingDestination, NSAnimatablePropertyContainer, void WillRemoveSubview ([NullAllowed] NSView subview); [Export ("removeFromSuperview")] - [PreSnippet ("var mySuper = Superview;", Optimizable = true)] - [PostSnippet ("if (mySuper != null) {\n\t#pragma warning disable 168\n\tvar flush = mySuper.Subviews;\n#pragma warning restore 168\n\t}", Optimizable = true)] void RemoveFromSuperview (); - [Export ("replaceSubview:with:")][PostGet ("Subviews")] + [Export ("replaceSubview:with:")] void ReplaceSubviewWith (NSView oldView, NSView newView); [Export ("removeFromSuperviewWithoutNeedingDisplay")] - [PreSnippet ("var mySuper = Superview;", Optimizable = true)] - [PostSnippet ("if (mySuper != null) {\n\t#pragma warning disable 168\n\tvar flush = mySuper.Subviews;\n#pragma warning restore 168\n\t}", Optimizable = true)] void RemoveFromSuperviewWithoutNeedingDisplay (); [Export ("resizeSubviewsWithOldSize:")] @@ -16398,16 +16378,16 @@ partial interface NSView : NSDraggingDestination, NSAnimatablePropertyContainer, [Export ("constraints")] NSLayoutConstraint [] Constraints { get; } - [Export ("addConstraint:")][PostGet ("Constraints")] + [Export ("addConstraint:")] void AddConstraint (NSLayoutConstraint constraint); - [Export ("addConstraints:")][PostGet ("Constraints")] + [Export ("addConstraints:")] void AddConstraints (NSLayoutConstraint [] constraints); - [Export ("removeConstraint:")][PostGet ("Constraints")] + [Export ("removeConstraint:")] void RemoveConstraint (NSLayoutConstraint constraint); - [Export ("removeConstraints:")][PostGet ("Constraints")] + [Export ("removeConstraints:")] void RemoveConstraints (NSLayoutConstraint [] constraints); [Export ("layoutSubtreeIfNeeded")] @@ -16639,11 +16619,11 @@ partial interface NSView : NSDraggingDestination, NSAnimatablePropertyContainer, NSGestureRecognizer [] GestureRecognizers { get; set; } [Mac (10,10)] - [Export ("addGestureRecognizer:")][PostGet("GestureRecognizers")] + [Export ("addGestureRecognizer:")] void AddGestureRecognizer (NSGestureRecognizer gestureRecognizer); [Mac (10,10)] - [Export ("removeGestureRecognizer:")][PostGet("GestureRecognizers")] + [Export ("removeGestureRecognizer:")] void RemoveGestureRecognizer (NSGestureRecognizer gestureRecognizer); [Export ("prepareForReuse")] @@ -16966,7 +16946,7 @@ interface NSViewController : NSResponder, NSUserInterfaceItemIdentification, NSE NSViewController [] ChildViewControllers { get; set; } [Mac (10,10)] - [Export ("addChildViewController:")][PostGet("ChildViewControllers")] + [Export ("addChildViewController:")] void AddChildViewController (NSViewController childViewController); [Mac (10,10)] @@ -16974,11 +16954,11 @@ interface NSViewController : NSResponder, NSUserInterfaceItemIdentification, NSE void RemoveFromParentViewController (); [Mac (10,10)] - [Export ("insertChildViewController:atIndex:")][PostGet("ChildViewControllers")] + [Export ("insertChildViewController:atIndex:")] void InsertChildViewController (NSViewController childViewController, nint index); [Mac (10,10)] - [Export ("removeChildViewControllerAtIndex:")][PostGet("ChildViewControllers")] + [Export ("removeChildViewControllerAtIndex:")] void RemoveChildViewController (nint index); [Mac (10,10)] @@ -18095,13 +18075,13 @@ partial interface NSTabView { [Export ("controlSize")] NSControlSize ControlSize { get; set; } - [Export ("addTabViewItem:")][PostGet ("Items")] + [Export ("addTabViewItem:")] void Add (NSTabViewItem tabViewItem); - [Export ("insertTabViewItem:atIndex:")][PostGet ("Items")] + [Export ("insertTabViewItem:atIndex:")] void Insert (NSTabViewItem tabViewItem, nint index); - [Export ("removeTabViewItem:")][PostGet ("Items")] + [Export ("removeTabViewItem:")] void Remove (NSTabViewItem tabViewItem); [Export ("delegate", ArgumentSemantic.Assign), NullAllowed] @@ -18170,13 +18150,13 @@ interface NSTabViewController : NSTabViewDelegate, NSToolbarDelegate { [Export ("selectedTabViewItemIndex")] nint SelectedTabViewItemIndex { get; set; } - [Export ("addTabViewItem:")][PostGet("TabViewItems")] + [Export ("addTabViewItem:")] void AddTabViewItem (NSTabViewItem tabViewItem); - [Export ("insertTabViewItem:atIndex:")][PostGet("TabViewItems")] + [Export ("insertTabViewItem:atIndex:")] void InsertTabViewItem (NSTabViewItem tabViewItem, nint index); - [Export ("removeTabViewItem:")][PostGet("TabViewItems")] + [Export ("removeTabViewItem:")] void RemoveTabViewItem (NSTabViewItem tabViewItem); [Export ("tabViewItemForViewController:")] @@ -21303,10 +21283,10 @@ bool IsVisible { [Export ("standardWindowButton:")] NSButton StandardWindowButton (NSWindowButton b); - [Export ("addChildWindow:ordered:")][PostGet ("ChildWindows")] + [Export ("addChildWindow:ordered:")] void AddChildWindow (NSWindow childWin, NSWindowOrderingMode place); - [Export ("removeChildWindow:")][PostGet ("ChildWindows")] + [Export ("removeChildWindow:")] void RemoveChildWindow (NSWindow childWin); [Export ("childWindows")] From cf7c6b5980aef449e1fa036015c041030555352d Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 30 May 2022 11:34:45 +0200 Subject: [PATCH 05/15] [msbuild] Improve logic to clean up app bundle for unwanted files. (#15080) The current directory at launch is the root directory of the app bundle. This means that any files written to the current directory when an app is executed, will be placed there. This becomes a problem when the app is rebuilt (and resigned), because a valid macOS app bundle doesn't have any files in the root directory of the app bundle, so signing fails. We have logic to automatically crash crash reports from the app bundle, but it turns out this is a more common problem with other types of files (and folders), so improve the logic a bit: * Add support for setting a property to automatically clean up everything from an app bundle we don't think should be there (which is anything not in a Contents/ subdirectory). * Use the same property to add support for disabling any cleaning (we already clean mono's crash reports by default). * Improve detection of unwanted files to include directories inside the app bundle, not only files. Ref: https://github.com/dotnet/maui/issues/7353 --- msbuild/Xamarin.Shared/Xamarin.Shared.targets | 35 ++++++++++++++++--- tests/dotnet/UnitTests/ProjectTest.cs | 22 ++++++++---- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets index 92dff17e2ef7..80e4291d5295 100644 --- a/msbuild/Xamarin.Shared/Xamarin.Shared.targets +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -300,6 +300,7 @@ Copyright (C) 2018 Microsoft. All rights reserved. + + - + + + + <_FilesInAppBundleRootDirectoryToRemove Include="@(_FilesInAppBundleRootDirectory)" Condition="$([MSBuild]::ValueOrDefault('%(Identity)', '').StartsWith('$(AppBundleDir)/Contents/'))" /> + <_FilesInAppBundleRootDirectory Remove="@(_FilesInAppBundleRootDirectoryToRemove);$(AppBundleDir)/Contents" /> + + + + + + <_DirectoriesInAppBundleRootDirectory Include="@(_FilesInAppBundleRootDirectory)" Condition="$([MSBuild]::ValueOrDefault('%(Identity)', '').Length) > 1" /> + + + diff --git a/tests/dotnet/UnitTests/ProjectTest.cs b/tests/dotnet/UnitTests/ProjectTest.cs index 6468d3f37a93..208777c9ec57 100644 --- a/tests/dotnet/UnitTests/ProjectTest.cs +++ b/tests/dotnet/UnitTests/ProjectTest.cs @@ -526,19 +526,27 @@ public void FilesInAppBundle (ApplePlatform platform, string runtimeIdentifiers) // Create a file that isn't a crash report. File.WriteAllText (Path.Combine (appPath, "otherfile.txt"), "A file"); + var otherFileInDir = Path.Combine (appPath, "otherdir", "otherfile.log"); + Directory.CreateDirectory (Path.GetDirectoryName (otherFileInDir)!); + File.WriteAllText (otherFileInDir, "A log"); // Build again - this time it'll fail var rv = DotNet.Build (project_path, properties); var warnings = BinLog.GetBuildLogWarnings (rv.BinLogPath).ToArray (); Assert.AreNotEqual (0, rv.ExitCode, "Unexpected success"); Assert.AreEqual (1, warnings.Length, "Warning Count"); - Assert.AreEqual ($"Found files in the root directory of the app bundle. This will likely cause codesign to fail. Files:\nbin/Debug/{Configuration.DotNetTfm}-maccatalyst/maccatalyst-x64/MySimpleApp.app/otherfile.txt", warnings [0].Message, "Warning"); - - // Remove the offending file - File.Delete (Path.Combine (appPath, "otherfile.txt")); - - // Build yet again - DotNet.AssertBuild (project_path, properties); + Assert.AreEqual ($"Found files in the root directory of the app bundle. This will likely cause codesign to fail. Files:\nbin/Debug/{Configuration.DotNetTfm}-maccatalyst/maccatalyst-x64/MySimpleApp.app/otherfile.txt\nbin/Debug/{Configuration.DotNetTfm}-maccatalyst/maccatalyst-x64/MySimpleApp.app/otherdir\nbin/Debug/{Configuration.DotNetTfm}-maccatalyst/maccatalyst-x64/MySimpleApp.app/otherdir/otherfile.log", warnings [0].Message, "Warning"); + + // Build again, asking for automatic removal of the extraneous files. + var enableAutomaticCleanupProperties = new Dictionary (properties); + enableAutomaticCleanupProperties ["EnableAutomaticAppBundleRootDirectoryCleanup"] = "true"; + rv = DotNet.AssertBuild (project_path, enableAutomaticCleanupProperties); + warnings = BinLog.GetBuildLogWarnings (rv.BinLogPath).ToArray (); + Assert.AreEqual (0, warnings.Length, "Warning Count"); + + // Verify that the files were in fact removed. + Assert.That (Path.Combine (appPath, "otherfile.txt"), Does.Not.Exist, "otherfile"); + Assert.That (Path.GetDirectoryName (otherFileInDir), Does.Not.Exist, "otherdir"); } [Test] From f5ed7e80b8ae94d538bf8fd0b1d8f3c8416df78a Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Mon, 30 May 2022 11:56:47 +0200 Subject: [PATCH 06/15] [main] Update dependencies from dotnet/installer (#15148) Microsoft.Dotnet.Sdk.Internal From Version 6.0.301-rtm.22274.16 -> To Version 6.0.301-rtm.22277.2 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a02d2b790dba..ef563ee2c0b0 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/installer - 2cd1eed21f146e37527ff93e547ad89214c5e759 + 6ff814b7069ae99877b3cee8277cfe762f6e6201 https://github.com/dotnet/linker diff --git a/eng/Versions.props b/eng/Versions.props index 850ef60a96c1..7242e693793c 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,7 +1,7 @@ - 6.0.301-rtm.22274.16 + 6.0.301-rtm.22277.2 6.0.200-1.22219.3 6.0.0-beta.21212.6 6.0.0-rc.2.21468.3 From f45c20505d027aa5e452e57ce96d3270aba2ac19 Mon Sep 17 00:00:00 2001 From: Mauro Agnoletti Date: Mon, 30 May 2022 06:29:14 -0400 Subject: [PATCH 07/15] Updated Hot Restart Client version to 1.0.93 (#15137) Bring changes in logging verbosity --- msbuild/Directory.Build.props | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msbuild/Directory.Build.props b/msbuild/Directory.Build.props index f9a2d790e074..6ea13fb15abc 100644 --- a/msbuild/Directory.Build.props +++ b/msbuild/Directory.Build.props @@ -1,6 +1,6 @@ 1.6.24 - 1.0.92 + 1.0.93 From 7ad9f88939ea1951e9e0fda5a4f44eb2cb4d23a1 Mon Sep 17 00:00:00 2001 From: Emanuel Fernandez Dell'Oca Date: Mon, 30 May 2022 06:34:20 -0400 Subject: [PATCH 08/15] [msbuild] Fixes Hot Restart compiled Entitlements output path (#15125) The compiled entitlements should be placed in the intermediate Hot Restart app bundle so those can be picked up by the HotRestart Codesign task. Prior to this change, entitlements set in the project wouldn't be included in the app, making things like Keychain Access fail, even though it was configured. Fixes https://developercommunity.visualstudio.com/t/Unable-to-use-MSAL-with-locally-connecte/1573064 --- .../Xamarin.iOS.Tasks.Windows/Xamarin.iOS.HotRestart.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.HotRestart.targets b/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.HotRestart.targets index 1053939e1a11..ff0528f6d325 100644 --- a/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.HotRestart.targets +++ b/msbuild/Xamarin.iOS.Tasks.Windows/Xamarin.iOS.HotRestart.targets @@ -195,7 +195,7 @@ AppIdentifier="$(_AppIdentifier)" BundleIdentifier="$(_BundleIdentifier)" Entitlements="$(_HotRestartEntitlementsFile)" - CompiledEntitlements="$(DeviceSpecificIntermediateOutputPath)Entitlements.xcent" + CompiledEntitlements="$(HotRestartAppBundlePath)\Entitlements.plist" IsAppExtension="$(IsAppExtension)" ProvisioningProfile="$(_ProvisioningProfileId)" SdkIsSimulator="False" From d869a6868a0a1fb33a1bbec34a5b1542c227b9b8 Mon Sep 17 00:00:00 2001 From: Sebastien Pouliot Date: Mon, 30 May 2022 06:38:27 -0400 Subject: [PATCH 09/15] [corefoundation] Cache `kCFNull` to avoid native calls (#15146) --- src/CoreFoundation/CFArray.cs | 3 +++ src/corefoundation.cs | 2 +- tests/perftest/NativeArrayPerf.cs | 12 ++++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/CoreFoundation/CFArray.cs b/src/CoreFoundation/CFArray.cs index c597ec4e0fe8..15f4ec6a5a51 100644 --- a/src/CoreFoundation/CFArray.cs +++ b/src/CoreFoundation/CFArray.cs @@ -53,6 +53,9 @@ namespace CoreFoundation { // interesting bits: https://github.com/opensource-apple/CF/blob/master/CFArray.c public partial class CFArray : NativeObject { + // this cache the handle instead of issuing a native call + internal static NativeHandle CFNullHandle = _CFNullHandle; + #if !NET internal CFArray (NativeHandle handle) : base (handle, false) diff --git a/src/corefoundation.cs b/src/corefoundation.cs index c454a2ea6a60..1f1d063157b1 100644 --- a/src/corefoundation.cs +++ b/src/corefoundation.cs @@ -33,7 +33,7 @@ interface CFAllocator { interface CFArray { [Internal][Field ("kCFNull")] - IntPtr /* CFNullRef */ CFNullHandle { get; } + IntPtr /* CFNullRef */ _CFNullHandle { get; } } [Partial] diff --git a/tests/perftest/NativeArrayPerf.cs b/tests/perftest/NativeArrayPerf.cs index 1432a3f9e542..7ba8c67418b5 100644 --- a/tests/perftest/NativeArrayPerf.cs +++ b/tests/perftest/NativeArrayPerf.cs @@ -32,5 +32,17 @@ public void Create () var native = CFArray.Create (array); CFString.ReleaseNative (native); // that's a `CFObject.CFRelease` with a null-check } + + int error; + + [Benchmark] + public void ArrayFromHandleFunc () + { + var native = CFArray.Create (array); + var managed = CFArray.ArrayFromHandle (native); + if (managed.Length != array.Length) + error++; + CFString.ReleaseNative (native); // that's a `CFObject.CFRelease` with a null-check + } } } From da2b1071896ec8d3e15ccbda49947daf532ba60d Mon Sep 17 00:00:00 2001 From: "dotnet-maestro[bot]" <42748379+dotnet-maestro[bot]@users.noreply.github.com> Date: Tue, 31 May 2022 09:06:34 +0200 Subject: [PATCH 10/15] [main] Update dependencies from dotnet/installer (#15153) Microsoft.Dotnet.Sdk.Internal From Version 6.0.301-rtm.22277.2 -> To Version 6.0.301-rtm.22280.1 Co-authored-by: dotnet-maestro[bot] --- eng/Version.Details.xml | 4 ++-- eng/Versions.props | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index ef563ee2c0b0..a1532a9f596f 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,8 +1,8 @@ - + https://github.com/dotnet/installer - 6ff814b7069ae99877b3cee8277cfe762f6e6201 + 283e9cfd1967d94e7d6dbc53b166c58e847b31e3 https://github.com/dotnet/linker diff --git a/eng/Versions.props b/eng/Versions.props index 7242e693793c..f2bfc48526fd 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,7 +1,7 @@ - 6.0.301-rtm.22277.2 + 6.0.301-rtm.22280.1 6.0.200-1.22219.3 6.0.0-beta.21212.6 6.0.0-rc.2.21468.3 From 86fe13e17fb6004077ba060f2b9aaf4b4b5aa00c Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Date: Tue, 31 May 2022 09:24:51 -0400 Subject: [PATCH 11/15] [CI] Split the pipeline in two, one for CI and a second one for PRs. (#15110) --- tools/devops/automation/build-pipeline.yml | 262 ++---------------- .../devops/automation/build-pull-request.yml | 221 +++++++++++++++ .../automation/templates/main-stage.yml | 248 +++++++++++++++++ .../templates/sign-and-notarized/setup.yml | 55 ++-- .../sign-and-notarized/sign-and-notarized.yml | 2 + .../devops/automation/templates/variables.yml | 42 ++- .../automation/templates/vsts-variables.yml | 4 + 7 files changed, 563 insertions(+), 271 deletions(-) create mode 100644 tools/devops/automation/build-pull-request.yml create mode 100644 tools/devops/automation/templates/main-stage.yml create mode 100644 tools/devops/automation/templates/vsts-variables.yml diff --git a/tools/devops/automation/build-pipeline.yml b/tools/devops/automation/build-pipeline.yml index cd85f19d686e..a8b5c245aa90 100644 --- a/tools/devops/automation/build-pipeline.yml +++ b/tools/devops/automation/build-pipeline.yml @@ -193,43 +193,8 @@ resources: variables: - ${{ if contains(variables['Build.DefinitionName'], 'private') }}: - - template: templates/variables.yml -- template: templates/common/vs-release-vars.yml@sdk-insertions # used for the insertion steps -- group: xamops-azdev-secrets -- group: Xamarin-Secrets -- group: Xamarin Signing -- group: Xamarin Release -- group: Xamarin Notarization -- group: XamarinCompatLab # provisionator-uri setting -- group: VSEng DTL secrets -- name: GitHub.Token # Override the GitHub.Token setting defined in the Xamarin Release group - value: $(github--pat--vs-mobiletools-engineering-service2) # Use a token dedicated to critical production workflows and help avoid GitHub throttling -- name: AzDoBuildAccess.Token - value: $(pat--xamarinc--build-access) -- name: system.debug - value: true -- name: SigningKeychain - value: "builder.keychain" -- name: VSDropsPrefix - value: 'https://vsdrop.corp.microsoft.com/file/v1/xamarin-macios/device-tests' -- name: USE_TCP_TUNNEL # Needed to ensure that devices uses the usb cable to communicate with the devices to run the tests. - value: true -- name: TeamName - value: 'xamarin-macios' -- name: PROVISIONATOR_CHANNEL - value: ${{ parameters.provisionatorChannel }} -- name: PRBuildPool - value: 'VSEng-Xamarin-RedmondMacBuildPool-iOS-Untrusted' -- name: PRBuildPoolUrl - value: 'https://devdiv.visualstudio.com/_settings/agentpools?poolId=366&view=agents' -- name: CIBuildPool - value: 'VSEng-Xamarin-RedmondMacBuildPool-iOS-Trusted' -- name: CIBuildPoolUrl - value: 'https://devdiv.visualstudio.com/_settings/agentpools?poolId=367&view=agents' -- name: IsPRBuild - value: ${{ or(eq(variables['Build.Reason'], 'PullRequest'), and(eq(variables['Build.SourceBranchName'], 'merge'), or(eq(variables['Build.Reason'], 'Manual'), eq(variables['Build.Reason'], 'IndividualCI')))) }} -- name: CIBuild - value: true + - template: templates/vsts-variables.yml +- template: templates/variables.yml trigger: branches: @@ -251,28 +216,6 @@ trigger: - tools/mtouch/README.md - msbuild/Xamarin.Localization.MSBuild/README.md -pr: - autoCancel: true - branches: - include: - - main - - d16-* - - xcode* - - release/* - paths: - exclude: - - .github - - docs - - CODEOWNERS - - ISSUE_TEMPLATE.md - - LICENSE - - NOTICE.txt - - SECURITY.MD - - README.md - - src/README.md - - tools/mtouch/README.md - - msbuild/Xamarin.Localization.MSBuild/README.md - schedules: # the translations team wants a green build, we can do that on sundays even if @@ -285,187 +228,20 @@ schedules: always: true stages: - -- ${{ if eq(parameters.runGovernanceTests, true) }}: - - stage: governance_checks - displayName: 'Governance Checks' - dependsOn: [] - jobs: - - job: governance - displayName: 'Governance Checks' - pool: - vmImage: windows-latest - steps: - - template: templates/governance-checks.yml - - - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: - - job: translations - displayName: 'Loc translations' - pool: - vmImage: windows-latest - steps: - - template: templates/loc-translations.yml - - -- ${{ if eq(variables['Build.Reason'], 'PullRequest') }}: - - stage: clean - displayName: 'Clean up' - dependsOn: [] - jobs: - - job: - displayName: 'Clean comments' - pool: - vmImage: windows-latest - steps: - - template: templates/common/clean.yml - - -- stage: build_packages - displayName: 'Build' - dependsOn: [] - jobs: - - template: templates/build/build-stage.yml - parameters: - vsdropsPrefix: ${{ variables.vsdropsPrefix }} - runTests: ${{ and(parameters.runTests, ne(variables['Build.Reason'], 'Schedule'))}} - runDeviceTests: ${{ and(parameters.runDeviceTests, ne(variables['Build.Reason'], 'Schedule')) }} - keyringPass: $(pass--lab--mac--builder--keychain) - gitHubToken: ${{ variables['GitHub.Token'] }} - xqaCertPass: $(xqa--certificates--password) - enableDotnet: ${{ parameters.enableDotnet }} - skipESRP: ${{ parameters.skipESRP }} - pool: ${{ parameters.pool }} - -- stage: prepare_packages - displayName: 'Prepare packages' - dependsOn: - - build_packages - jobs: - - template: templates/sign-and-notarized/prepare-pkg-stage.yml - parameters: - keyringPass: $(pass--lab--mac--builder--keychain) - enableDotnet: ${{ parameters.enableDotnet }} - skipESRP: ${{ parameters.skipESRP }} - -- ${{ if eq(parameters.enableAPIDiff, true) }}: - - stage: generate_api_diff - displayName: 'API diff' - dependsOn: [] - jobs: - - template: templates/build/api-diff-stage.yml - parameters: - vsdropsPrefix: ${{ variables.vsdropsPrefix }} - keyringPass: $(pass--lab--mac--builder--keychain) - gitHubToken: ${{ variables['GitHub.Token'] }} - xqaCertPass: $(xqa--certificates--password) - enableDotnet: ${{ parameters.enableDotnet }} - pool: ${{ parameters.pool }} - -# .NET Release Prep and VS Insertion Stages, only execute them when the build comes from an official branch and is not a schedule build from OneLoc -- ${{ if and(ne(variables['Build.Reason'], 'Schedule'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), eq(variables['Build.SourceBranch'], 'refs/heads/net7.0'), eq(parameters.forceInsertion, true))) }}: - - template: templates/release/vs-insertion-prep.yml - -# Test stages - -# always run simulator tests -- ${{ each config in parameters.simTestsConfigurations }}: - - template: templates/tests/stage.yml - parameters: - testPrefix: ${{ config.testPrefix }} - stageName: ${{ config.stageName }} - displayName: ${{ config.displayName }} - testPool: '' # use the default - useXamarinStorage: ${{ config.useXamarinStorage }} - testsLabels: ${{ config.testsLabels }} - statusContext: ${{ config.statusContext }} - ${{ if and(ne(variables['Build.Reason'], 'Schedule'), or(eq(variables['Build.Reason'], 'IndividualCI'), eq(variables['Build.Reason'], 'Manual'))) }}: - makeTarget: 'wrench-jenkins' # override when we are running on CI or manually to run all tests - ${{ else }}: - makeTarget: ${{ config.makeTarget }} - vsdropsPrefix: ${{ variables.vsdropsPrefix }} - keyringPass: $(pass--lab--mac--builder--keychain) - gitHubToken: ${{ variables['GitHub.Token'] }} - xqaCertPass: $(xqa--certificates--password) - enableDotnet: ${{ parameters.enableDotnet }} - condition: ${{ parameters.runTests }} - -# devices are optional and will only be ran when we set them OR in CI -- ${{ if eq(parameters.runDeviceTests, true) }}: - - ${{ if and(ne(variables['Build.Reason'], 'Schedule'), or(eq(variables['Build.Reason'], 'IndividualCI'), eq(variables['Build.Reason'], 'Manual'))) }}: - - ${{ each config in parameters.deviceTestsConfigurations }}: - - template: templates/tests/stage.yml - parameters: - testPrefix: ${{ config.testPrefix }} - stageName: ${{ config.stageName }} - displayName: ${{ config.displayName }} - testPool: ${{ config.testPool }} - useXamarinStorage: ${{ config.useXamarinStorage }} - testsLabels: ${{ config.testsLabels }} - statusContext: ${{ config.statusContext }} - extraBotDemands: ${{ config.extraBotDemands }} - makeTarget: ${{ config.makeTarget }} - vsdropsPrefix: ${{ variables.vsdropsPrefix }} - keyringPass: $(pass-XamarinQA-bot-login) - gitHubToken: ${{ variables['GitHub.Token'] }} - xqaCertPass: $(xqa--certificates--password) - enableDotnet: ${{ parameters.enableDotnet }} - condition: ${{ parameters.runDeviceTests }} - parseLabels: false - -- ${{ if eq(parameters.runOldMacOSTests, true) }}: - - ${{ each config in parameters.macTestsConfigurations }}: - - template: templates/mac/stage.yml - parameters: - stageName: ${{ config.stageName }} - displayName: ${{ config.displayName }} - macPool: ${{ config.macPool }} - useImage: ${{ config.useImage }} - statusContext: ${{ config.statusContext }} - keyringPass: $(pass--lab--mac--builder--keychain) - enableDotnet: ${{ parameters.enableDotnet }} - demands: ${{ config.demands }} - -- ${{ if eq(parameters.runWindowsIntegration, true) }}: - - template: templates/windows/stage.yml - parameters: - stageName: windows_integration - displayName: 'Windows Integration Tests' - pool: 'VSEng-Xamarin-Mac-Devices' # currently ignored until the VS team provides a real one - statusContext: 'Windows Integration Tests' - -# iOS 32b tests are slow and do not have many machines, for that reason we are going just to run them in the Schedule builds. -# This means we are going to get the translations AND the iOS 32b on those builds. -# -- ${{ if eq(variables['Build.Reason'], 'Schedule') }}: - - template: templates/tests/stage.yml - parameters: - testPrefix: 'iOS32b' - stageName: 'ios32b_device' - displayName: 'iOS32b Device Tests' - testPool: 'VSEng-Xamarin-QA' - useXamarinStorage: False - testsLabels: '--label=run-ios-32-tests,run-non-monotouch-tests,run-monotouch-tests,run-mscorlib-tests' - statusContext: 'VSTS: device tests iOS32b' - extraBotDemands: ['xismoke-32'] - vsdropsPrefix: ${{ variables.vsdropsPrefix }} - keyringPass: $(pass--lab--mac--builder--keychain) - gitHubToken: ${{ variables['GitHub.Token'] }} - xqaCertPass: $(xqa--certificates--password) - enableDotnet: ${{ parameters.enableDotnet }} - -- ${{ if eq(parameters.runSamples, true) }}: - # TODO: Not the real step - - stage: sample_testing - displayName: 'Sample testing' - dependsOn: - - build_packages - condition: and(succeeded(), contains (stageDependencies.build_packages.build.outputs['configuration.RunSampleTests'], 'True')) - jobs: - - job: sample_testing - pool: - vmImage: ubuntu-latest - steps: - # TODO: do parse labels - - bash: | - echo "Samples!" - displayName: 'Sample testing' +- template: templates/main-stage.yml + parameters: + provisionatorChannel: ${{ parameters.provisionatorChannel }} + pool: ${{ parameters.pool }} + runTests: ${{ parameters.runTests }} + runDeviceTests: ${{ parameters.runDeviceTests }} + runOldMacOSTests: ${{ parameters.runOldMacOSTests }} + runWindowsIntegration: ${{ parameters.runWindowsIntegration }} + runGovernanceTests: ${{ parameters.runGovernanceTests }} + runSamples: ${{ parameters.runSamples }} + enableDotnet: ${{ parameters.enableDotnet }} + enableAPIDiff: ${{ parameters.enableAPIDiff }} + forceInsertion: ${{ parameters.forceInsertion }} + skipESRP: ${{ parameters.skipESRP }} + simTestsConfigurations: ${{ parameters.simTestsConfigurations }} + deviceTestsConfigurations: ${{ parameters.deviceTestsConfigurations }} + macTestsConfigurations: ${{ parameters.macTestsConfigurations }} diff --git a/tools/devops/automation/build-pull-request.yml b/tools/devops/automation/build-pull-request.yml new file mode 100644 index 000000000000..e86f3bbda3f8 --- /dev/null +++ b/tools/devops/automation/build-pull-request.yml @@ -0,0 +1,221 @@ +# YAML pipeline build definition +# https://devdiv.visualstudio.com/DevDiv/_apps/hub/ms.vss-ciworkflow.build-ci-hub?_a=edit-build-definition&id=13947&view=Tab_Tasks +# +# YAML build pipeline based on the Jenkins multi-stage (main branch) build workflow +# https://jenkins.internalx.com/view/Xamarin.MaciOS/job/macios/job/main/ +# https://jenkins.internalx.com/view/Xamarin.MaciOS/job/macios/configure +# +parameters: + +- name: provisionatorChannel + displayName: Provisionator channel to use + type: string + default: 'latest' + +- name: pool + type: string + displayName: Bot pool to use + default: automatic + values: + - pr + - ci + - automatic + +- name: runTests + displayName: Run Simulator Tests + type: boolean + default: true + +- name: runOldMacOSTests + displayName: Run Tests on older macOS versions + type: boolean + default: true + +- name: runWindowsIntegration + displayName: Run Windows integration tests + type: boolean + default: true + +- name: runGovernanceTests + displayName: Run Governance Checks + type: boolean + default: true + +- name: runSamples + displayName: Run Samples + type: boolean + default: false + +- name: enableDotnet + displayName: Build Dotnet + type: boolean + default: true + +- name: enableAPIDiff + displayName: Enable API diff generation + type: boolean + default: true + +# We are doing some black magic. We have several templates that +# are executed with different parameters. +# +# The problem with that is that templates cannot be used with the +# matrix strategy, so we are doing a little trick based on the following: +# +# 1. We can create a template that expands. +# 2. We can use the each keyword, which allow a loop +# 3. yaml is a super set of json, therefore, it was json dictionaries +# +# the following parameters, define an array of dictionaries with the +# data required by the templates. Do you want a new stage with +# device tests, no more copy paste, just add the new config. +# +- name: simTestsConfigurations + displayName: Simulator test configurations to run + type: object + default: [ + { + testPrefix: 'simulator', + stageName: 'simulator', + displayName: 'Simulator Tests', + useXamarinStorage: False, + testsLabels: '--label=run-all-tests,skip-device-tests', # TODO same as calling jenkins, we need to use diff one in ci an + statusContext: 'VSTS: simulator tests iOS', + makeTarget: 'jenkins', + } + ] + +- name: deviceTestsConfigurations + displayName: Device test configurations to run + type: object + default: [ + { + testPrefix: 'iOS64', + stageName: 'ios64b_device', + displayName: 'iOS64 Device Tests', + testPool: 'VSEng-Xamarin-Mac-Devices', + useXamarinStorage: False, + testsLabels: '--label=run-ios-64-tests,run-non-monotouch-tests,run-monotouch-tests,run-mscorlib-tests', + statusContext: 'VSTS: device tests iOS', + makeTarget: 'vsts-device-tests', + extraBotDemands: [ + 'ios', + ] + }, + { + testPrefix: 'tvos', + stageName: 'tvos_device', + displayName: 'tvOS Device Tests', + testPool: 'VSEng-Xamarin-Mac-Devices', + useXamarinStorage: False, + testsLabels: '--label=run-tvos-tests,run-non-monotouch-tests,run-monotouch-tests,run-mscorlib-tests', + statusContext: 'VSTS: device tests tvOS', + makeTarget: 'vsts-device-tests', + extraBotDemands: [ + 'tvos', + ] + }] + +- name: macTestsConfigurations + displayName: macOS test configurations to run + type: object + default: [ + { + stageName: 'mac_10_15', + displayName: 'Mac Catalina (10.15)', + macPool: 'macOS-10.15', + useImage: true, + statusContext: 'Mac Catalina (10.15)', + demands: [ + "Agent.OS -equals Darwin", + "Agent.OSVersion -equals '10.15'" + ] + }, + { + stageName: 'mac_11_5_m1', + displayName: 'M1 - Mac Big Sur (11.5)', + macPool: 'VSEng-VSMac-Xamarin-Shared', + useImage: false, + statusContext: 'M1 - Mac Big Sur (11.5)', + demands: [ + "Agent.OS -equals Darwin", + "macOS.Name -equals BigSur", + "macOS.Architecture -equals arm64", + "Agent.HasDevices -equals False", + "Agent.IsPaired -equals False" + ] + }] + +resources: + repositories: + - repository: self + checkoutOptions: + submodules: true + + - repository: templates + type: github + name: xamarin/yaml-templates + ref: refs/heads/main + endpoint: xamarin + + - repository: sdk-insertions + type: github + name: xamarin/sdk-insertions + ref: refs/heads/main + endpoint: xamarin + + - repository: maccore + type: github + name: xamarin/maccore + ref: refs/heads/main + endpoint: xamarin + + - repository: release-scripts + type: github + name: xamarin/release-scripts + ref: refs/heads/only_codesign + endpoint: xamarin + +variables: +- template: templates/variables.yml + +pr: + autoCancel: true + branches: + include: + - main + - d16-* + - xcode* + - release/* + paths: + exclude: + - .github + - docs + - CODEOWNERS + - ISSUE_TEMPLATE.md + - LICENSE + - NOTICE.txt + - SECURITY.MD + - README.md + - src/README.md + - tools/mtouch/README.md + - msbuild/Xamarin.Localization.MSBuild/README.md + +stages: +- template: templates/main-stage.yml + parameters: + provisionatorChannel: ${{ parameters.provisionatorChannel }} + pool: ${{ parameters.pool }} + runTests: ${{ parameters.runTests }} + runDeviceTests: false + runOldMacOSTests: ${{ parameters.runOldMacOSTests }} + runWindowsIntegration: ${{ parameters.runWindowsIntegration }} + runGovernanceTests: ${{ parameters.runGovernanceTests }} + runSamples: ${{ parameters.runSamples }} + enableDotnet: ${{ parameters.enableDotnet }} + enableAPIDiff: ${{ parameters.enableAPIDiff }} + forceInsertion: false + skipESRP: true + simTestsConfigurations: ${{ parameters.simTestsConfigurations }} + deviceTestsConfigurations: ${{ parameters.deviceTestsConfigurations }} + macTestsConfigurations: ${{ parameters.macTestsConfigurations }} diff --git a/tools/devops/automation/templates/main-stage.yml b/tools/devops/automation/templates/main-stage.yml new file mode 100644 index 000000000000..5ebb900db5f1 --- /dev/null +++ b/tools/devops/automation/templates/main-stage.yml @@ -0,0 +1,248 @@ +parameters: + +- name: provisionatorChannel + type: string + default: 'latest' + +- name: pool + type: string + default: automatic + values: + - pr + - ci + - automatic + +- name: runTests + type: boolean + default: true + +- name: runDeviceTests + type: boolean + default: false + +- name: runOldMacOSTests + type: boolean + default: true + +- name: runWindowsIntegration + type: boolean + default: true + +- name: runGovernanceTests + type: boolean + default: true + +- name: runSamples + type: boolean + default: false + +- name: enableDotnet + type: boolean + default: true + +- name: enableAPIDiff + type: boolean + default: true + +- name: forceInsertion + type: boolean + default: false + +- name: skipESRP + type: boolean + default: false # only to be used when testing the CI and we do not need a signed pkg + +- name: simTestsConfigurations + type: object + +- name: deviceTestsConfigurations + type: object + +- name: macTestsConfigurations + type: object + +stages: + +- ${{ if eq(parameters.runGovernanceTests, true) }}: + - stage: governance_checks + displayName: 'Governance Checks' + dependsOn: [] + jobs: + - job: governance + displayName: 'Governance Checks' + pool: + vmImage: windows-latest + steps: + - template: governance-checks.yml + + - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: + - job: translations + displayName: 'Loc translations' + pool: + vmImage: windows-latest + steps: + - template: loc-translations.yml + + +- ${{ if eq(variables['Build.Reason'], 'PullRequest') }}: + - stage: clean + displayName: 'Clean up' + dependsOn: [] + jobs: + - job: + displayName: 'Clean comments' + pool: + vmImage: windows-latest + steps: + - template: ./common/clean.yml + + +- stage: build_packages + displayName: 'Build' + dependsOn: [] + jobs: + - template: ./build/build-stage.yml + parameters: + vsdropsPrefix: ${{ variables.vsdropsPrefix }} + runTests: ${{ and(parameters.runTests, ne(variables['Build.Reason'], 'Schedule'))}} + runDeviceTests: ${{ and(parameters.runDeviceTests, ne(variables['Build.Reason'], 'Schedule')) }} + keyringPass: $(pass--lab--mac--builder--keychain) + gitHubToken: ${{ variables['GitHub.Token'] }} + xqaCertPass: $(xqa--certificates--password) + enableDotnet: ${{ parameters.enableDotnet }} + skipESRP: ${{ parameters.skipESRP }} + pool: ${{ parameters.pool }} + +- stage: prepare_packages + displayName: 'Prepare packages' + dependsOn: + - build_packages + jobs: + - template: ./sign-and-notarized/prepare-pkg-stage.yml + parameters: + keyringPass: $(pass--lab--mac--builder--keychain) + enableDotnet: ${{ parameters.enableDotnet }} + skipESRP: ${{ parameters.skipESRP }} + +- ${{ if eq(parameters.enableAPIDiff, true) }}: + - stage: generate_api_diff + displayName: 'API diff' + dependsOn: [] + jobs: + - template: ./build/api-diff-stage.yml + parameters: + vsdropsPrefix: ${{ variables.vsdropsPrefix }} + keyringPass: $(pass--lab--mac--builder--keychain) + gitHubToken: ${{ variables['GitHub.Token'] }} + xqaCertPass: $(xqa--certificates--password) + enableDotnet: ${{ parameters.enableDotnet }} + pool: ${{ parameters.pool }} + +# .NET Release Prep and VS Insertion Stages, only execute them when the build comes from an official branch and is not a schedule build from OneLoc +- ${{ if and(ne(variables['Build.Reason'], 'Schedule'), or(eq(variables['Build.SourceBranch'], 'refs/heads/main'), startsWith(variables['Build.SourceBranch'], 'refs/heads/release/'), eq(variables['Build.SourceBranch'], 'refs/heads/net7.0'), eq(parameters.forceInsertion, true))) }}: + - template: ./release/vs-insertion-prep.yml + +# Test stages + +# always run simulator tests +- ${{ each config in parameters.simTestsConfigurations }}: + - template: ./tests/stage.yml + parameters: + testPrefix: ${{ config.testPrefix }} + stageName: ${{ config.stageName }} + displayName: ${{ config.displayName }} + testPool: '' # use the default + useXamarinStorage: ${{ config.useXamarinStorage }} + testsLabels: ${{ config.testsLabels }} + statusContext: ${{ config.statusContext }} + ${{ if and(ne(variables['Build.Reason'], 'Schedule'), or(eq(variables['Build.Reason'], 'IndividualCI'), eq(variables['Build.Reason'], 'Manual'))) }}: + makeTarget: 'wrench-jenkins' # override when we are running on CI or manually to run all tests + ${{ else }}: + makeTarget: ${{ config.makeTarget }} + vsdropsPrefix: ${{ variables.vsdropsPrefix }} + keyringPass: $(pass--lab--mac--builder--keychain) + gitHubToken: ${{ variables['GitHub.Token'] }} + xqaCertPass: $(xqa--certificates--password) + enableDotnet: ${{ parameters.enableDotnet }} + condition: ${{ parameters.runTests }} + +# devices are optional and will only be ran when we set them OR in CI +- ${{ if eq(parameters.runDeviceTests, true) }}: + - ${{ if and(ne(variables['Build.Reason'], 'Schedule'), or(eq(variables['Build.Reason'], 'IndividualCI'), eq(variables['Build.Reason'], 'Manual'))) }}: + - ${{ each config in parameters.deviceTestsConfigurations }}: + - template: ./tests/stage.yml + parameters: + testPrefix: ${{ config.testPrefix }} + stageName: ${{ config.stageName }} + displayName: ${{ config.displayName }} + testPool: ${{ config.testPool }} + useXamarinStorage: ${{ config.useXamarinStorage }} + testsLabels: ${{ config.testsLabels }} + statusContext: ${{ config.statusContext }} + extraBotDemands: ${{ config.extraBotDemands }} + makeTarget: ${{ config.makeTarget }} + vsdropsPrefix: ${{ variables.vsdropsPrefix }} + keyringPass: $(pass-XamarinQA-bot-login) + gitHubToken: ${{ variables['GitHub.Token'] }} + xqaCertPass: $(xqa--certificates--password) + enableDotnet: ${{ parameters.enableDotnet }} + condition: ${{ parameters.runDeviceTests }} + parseLabels: false + +- ${{ if eq(parameters.runOldMacOSTests, true) }}: + - ${{ each config in parameters.macTestsConfigurations }}: + - template: ./mac/stage.yml + parameters: + stageName: ${{ config.stageName }} + displayName: ${{ config.displayName }} + macPool: ${{ config.macPool }} + useImage: ${{ config.useImage }} + statusContext: ${{ config.statusContext }} + keyringPass: $(pass--lab--mac--builder--keychain) + enableDotnet: ${{ parameters.enableDotnet }} + demands: ${{ config.demands }} + +- ${{ if eq(parameters.runWindowsIntegration, true) }}: + - template: ./windows/stage.yml + parameters: + stageName: windows_integration + displayName: 'Windows Integration Tests' + pool: 'VSEng-Xamarin-Mac-Devices' # currently ignored until the VS team provides a real one + statusContext: 'Windows Integration Tests' + +# iOS 32b tests are slow and do not have many machines, for that reason we are going just to run them in the Schedule builds. +# This means we are going to get the translations AND the iOS 32b on those builds. +# +- ${{ if eq(variables['Build.Reason'], 'Schedule') }}: + - template: ./tests/stage.yml + parameters: + testPrefix: 'iOS32b' + stageName: 'ios32b_device' + displayName: 'iOS32b Device Tests' + testPool: 'VSEng-Xamarin-QA' + useXamarinStorage: False + testsLabels: '--label=run-ios-32-tests,run-non-monotouch-tests,run-monotouch-tests,run-mscorlib-tests' + statusContext: 'VSTS: device tests iOS32b' + extraBotDemands: ['xismoke-32'] + vsdropsPrefix: ${{ variables.vsdropsPrefix }} + keyringPass: $(pass--lab--mac--builder--keychain) + gitHubToken: ${{ variables['GitHub.Token'] }} + xqaCertPass: $(xqa--certificates--password) + enableDotnet: ${{ parameters.enableDotnet }} + +- ${{ if eq(parameters.runSamples, true) }}: + # TODO: Not the real step + - stage: sample_testing + displayName: 'Sample testing' + dependsOn: + - build_packages + condition: and(succeeded(), contains (stageDependencies.build_packages.build.outputs['configuration.RunSampleTests'], 'True')) + jobs: + - job: sample_testing + pool: + vmImage: ubuntu-latest + steps: + # TODO: do parse labels + - bash: | + echo "Samples!" + displayName: 'Sample testing' diff --git a/tools/devops/automation/templates/sign-and-notarized/setup.yml b/tools/devops/automation/templates/sign-and-notarized/setup.yml index 2c093593ab64..3545603571a9 100644 --- a/tools/devops/automation/templates/sign-and-notarized/setup.yml +++ b/tools/devops/automation/templates/sign-and-notarized/setup.yml @@ -8,6 +8,10 @@ parameters: - name: condition default: and(succeeded(), eq(variables['IsPRBuild'], 'False')) +- name: skipESRP + type: boolean + default: false # only to be used when testing the CI and we do not need a signed pkg + steps: # DO NOT USE THE checkout.yml template. The reason is that the template changes the hash which results in a problem with the artifacts scripts @@ -26,29 +30,30 @@ steps: - checkout: release-scripts clean: true -# the ddsign plugin needs this version or it will crash and will make the sign step fail -- task: UseDotNet@2 - inputs: - packageType: sdk - version: 3.x - displayName: 'Install .NET Core SDK 3.x needed for ESRP' - -- task: MicroBuildSigningPlugin@3 - displayName: 'Install Signing Plugin' - inputs: - signType: '${{ parameters.signatureType }}' - azureSubscription: 'MicroBuild Signing Task (DevDiv)' - zipSources: false # we do not use the feature and makes the installation to last 10/12 mins instead of < 1 min - env: - SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: ${{ parameters.condition }} - -- task: ms-vseng.MicroBuildTasks.30666190-6959-11e5-9f96-f56098202fef.MicroBuildSigningPlugin@3 - displayName: 'Install Notarizing Plugin' - inputs: - signType: 'Real' # test is not present for mac.. - azureSubscription: 'MicroBuild Signing Task (DevDiv)' - zipSources: false # we do not use the feature and makes the installation to last 10/12 mins instead of < 1 min - env: +- ${{ if eq(parameters.skipESRP, true) }}: # do not install if not needd. + # the ddsign plugin needs this version or it will crash and will make the sign step fail + - task: UseDotNet@2 + inputs: + packageType: sdk + version: 3.x + displayName: 'Install .NET Core SDK 3.x needed for ESRP' + + - task: MicroBuildSigningPlugin@3 + displayName: 'Install Signing Plugin' + inputs: + signType: '${{ parameters.signatureType }}' + azureSubscription: 'MicroBuild Signing Task (DevDiv)' + zipSources: false # we do not use the feature and makes the installation to last 10/12 mins instead of < 1 min + env: SYSTEM_ACCESSTOKEN: $(System.AccessToken) - condition: ${{ parameters.condition }} + condition: ${{ parameters.condition }} + + - task: ms-vseng.MicroBuildTasks.30666190-6959-11e5-9f96-f56098202fef.MicroBuildSigningPlugin@3 + displayName: 'Install Notarizing Plugin' + inputs: + signType: 'Real' # test is not present for mac.. + azureSubscription: 'MicroBuild Signing Task (DevDiv)' + zipSources: false # we do not use the feature and makes the installation to last 10/12 mins instead of < 1 min + env: + SYSTEM_ACCESSTOKEN: $(System.AccessToken) + condition: ${{ parameters.condition }} diff --git a/tools/devops/automation/templates/sign-and-notarized/sign-and-notarized.yml b/tools/devops/automation/templates/sign-and-notarized/sign-and-notarized.yml index 1eeac343d0a6..a361a42ee5d8 100644 --- a/tools/devops/automation/templates/sign-and-notarized/sign-and-notarized.yml +++ b/tools/devops/automation/templates/sign-and-notarized/sign-and-notarized.yml @@ -24,6 +24,8 @@ parameters: steps: - template: setup.yml + parameters: + skipESRP: ${{ parameters.skipESRP }} - task: DownloadPipelineArtifact@2 displayName: Download not notarized build diff --git a/tools/devops/automation/templates/variables.yml b/tools/devops/automation/templates/variables.yml index d7ba27e5753b..e1596af6f1b5 100644 --- a/tools/devops/automation/templates/variables.yml +++ b/tools/devops/automation/templates/variables.yml @@ -1,4 +1,40 @@ - variables: - - group: AzureDevOps-Artifact-Feeds-Pats - - group: DotNet-MSRC-Storage +variables: +- ${{ if contains(variables['Build.DefinitionName'], 'private') }}: + - template: templates/vsts-variables.yml +- template: templates/common/vs-release-vars.yml@sdk-insertions # used for the insertion steps +- group: xamops-azdev-secrets +- group: Xamarin-Secrets +- group: Xamarin Signing +- group: Xamarin Release +- group: Xamarin Notarization +- group: XamarinCompatLab # provisionator-uri setting +- group: VSEng DTL secrets +- name: GitHub.Token # Override the GitHub.Token setting defined in the Xamarin Release group + value: $(github--pat--vs-mobiletools-engineering-service2) # Use a token dedicated to critical production workflows and help avoid GitHub throttling +- name: AzDoBuildAccess.Token + value: $(pat--xamarinc--build-access) +- name: system.debug + value: true +- name: SigningKeychain + value: "builder.keychain" +- name: VSDropsPrefix + value: 'https://vsdrop.corp.microsoft.com/file/v1/xamarin-macios/device-tests' +- name: USE_TCP_TUNNEL # Needed to ensure that devices uses the usb cable to communicate with the devices to run the tests. + value: true +- name: TeamName + value: 'xamarin-macios' +- name: PROVISIONATOR_CHANNEL + value: ${{ parameters.provisionatorChannel }} +- name: PRBuildPool + value: 'VSEng-Xamarin-RedmondMacBuildPool-iOS-Untrusted' +- name: PRBuildPoolUrl + value: 'https://devdiv.visualstudio.com/_settings/agentpools?poolId=366&view=agents' +- name: CIBuildPool + value: 'VSEng-Xamarin-RedmondMacBuildPool-iOS-Trusted' +- name: CIBuildPoolUrl + value: 'https://devdiv.visualstudio.com/_settings/agentpools?poolId=367&view=agents' +- name: IsPRBuild + value: ${{ or(eq(variables['Build.Reason'], 'PullRequest'), and(eq(variables['Build.SourceBranchName'], 'merge'), or(eq(variables['Build.Reason'], 'Manual'), eq(variables['Build.Reason'], 'IndividualCI')))) }} +- name: CIBuild + value: true diff --git a/tools/devops/automation/templates/vsts-variables.yml b/tools/devops/automation/templates/vsts-variables.yml new file mode 100644 index 000000000000..d7ba27e5753b --- /dev/null +++ b/tools/devops/automation/templates/vsts-variables.yml @@ -0,0 +1,4 @@ + variables: + - group: AzureDevOps-Artifact-Feeds-Pats + - group: DotNet-MSRC-Storage + From c17fd255832fcad92cb88816115c431176172a40 Mon Sep 17 00:00:00 2001 From: Chris Hamons Date: Tue, 31 May 2022 07:40:56 -0700 Subject: [PATCH 12/15] [nnyeah] Map NSObject ctors with IntPtr to NativeHandle (#15134) * [nnyeah] Remove NNYEAH_IN_PROCESS on IntegrationExamples.cs as it was cursed due to global caching in nuget tool install * [nnyeah] Simplify test API * [nnyeah] Map NSObject ctors with IntPtr to NativeHandle - Fixes https://github.com/xamarin/xamarin-macios/issues/15120 This required a significant amount of refactoring: - To resolve the base type of objects, we need to invoke cecil's Resolve - Resolve requires all assemblies to be loaded in memory, whcih requires a custom resolver to find them all - Note: This requires customer assemblies to include all non-platform dependencies to be next to the input - This extra state prompted a refactor of Program.cs to create a tool 'AssemblyConverter' with instance variables to reduce param passing - The ctor mapping logic is isolated to ConstructorTransforms to reduce the growth of Reworker.cs and make limited unit testing possible - Turns out the flat removal of the platform assembly from the import list was wrong, as it caused all platform references, such as NSObject to be resolved from System.Runtime, which is wrong. So replace in place with the new platform assembly instead. --- .../nnyeah/integration/API/IntegrationAPI.cs | 11 ++ tools/nnyeah/integration/Consumer/Consumer.cs | 8 + .../AssemblyComparator/ComparingVisitor.cs | 8 +- .../AssemblyComparator/ModuleElements.cs | 2 +- tools/nnyeah/nnyeah/AssemblyConverter.cs | 163 +++++++++++++++++ tools/nnyeah/nnyeah/AssemblyResolver.cs | 19 ++ tools/nnyeah/nnyeah/ConstructorTransforms.cs | 75 ++++++++ tools/nnyeah/nnyeah/Errors.Designer.cs | 6 + tools/nnyeah/nnyeah/Errors.resx | 3 + tools/nnyeah/nnyeah/Program.cs | 165 +----------------- tools/nnyeah/nnyeah/Reworker.cs | 21 ++- .../tests/integration/IntegrationExamples.cs | 32 +--- tools/nnyeah/tests/unit/CompileALibrary.cs | 11 +- .../tests/unit/ConstructorTransformTests.cs | 141 +++++++++++++++ .../tests/unit/DependencyRemovedTests.cs | 4 +- .../tests/unit/XamarinDependencyTests.cs | 4 +- tools/nnyeah/tests/unit/utils/TestRunning.cs | 15 +- 17 files changed, 476 insertions(+), 212 deletions(-) create mode 100644 tools/nnyeah/nnyeah/AssemblyConverter.cs create mode 100644 tools/nnyeah/nnyeah/AssemblyResolver.cs create mode 100644 tools/nnyeah/nnyeah/ConstructorTransforms.cs create mode 100644 tools/nnyeah/tests/unit/ConstructorTransformTests.cs diff --git a/tools/nnyeah/integration/API/IntegrationAPI.cs b/tools/nnyeah/integration/API/IntegrationAPI.cs index 85de7cfd0f98..581fbf5d6613 100644 --- a/tools/nnyeah/integration/API/IntegrationAPI.cs +++ b/tools/nnyeah/integration/API/IntegrationAPI.cs @@ -1,4 +1,5 @@ using System; +using Foundation; namespace IntegrationAPI { @@ -112,4 +113,14 @@ public NFloatAPI () public nfloat ToNFloat (ulong a) => a; public nfloat ToNFloat (float a) => a; } + + public class NSObjectDerived : NSObject { + public NSObjectDerived (IntPtr p) : base (p) { } + public NSObjectDerived (IntPtr p, bool b) : base (p, b) { } + + } + public class NSObjectDerivedSubclass : NSObjectDerived { + public NSObjectDerivedSubclass (IntPtr p) : base (p) { } + public NSObjectDerivedSubclass (IntPtr p, bool b) : base (p, b) { } + } } diff --git a/tools/nnyeah/integration/Consumer/Consumer.cs b/tools/nnyeah/integration/Consumer/Consumer.cs index 647cd0f9d946..a233292927db 100644 --- a/tools/nnyeah/integration/Consumer/Consumer.cs +++ b/tools/nnyeah/integration/Consumer/Consumer.cs @@ -2,6 +2,7 @@ using IntegrationAPI; using System.Runtime.InteropServices; +using ObjCRuntime; namespace ConsumerTests { @@ -13,6 +14,7 @@ public static string Test () NIntTest (output); NUIntTest (output); NFloatTest (output); + NSObjectCtor (output); if (output.Length == 0) { return "Test Successful"; @@ -251,5 +253,11 @@ static void NFloatTest (StringBuilder output) output.AppendLine ("nfloat implicit failure (float)"); } } + + static void NSObjectCtor (StringBuilder output) + { + var n = new NSObjectDerived (NativeHandle.Zero); + var n2 = new NSObjectDerived (NativeHandle.Zero, true); + } } } diff --git a/tools/nnyeah/nnyeah/AssemblyComparator/ComparingVisitor.cs b/tools/nnyeah/nnyeah/AssemblyComparator/ComparingVisitor.cs index df74ee49651c..038fbde38a6d 100644 --- a/tools/nnyeah/nnyeah/AssemblyComparator/ComparingVisitor.cs +++ b/tools/nnyeah/nnyeah/AssemblyComparator/ComparingVisitor.cs @@ -8,20 +8,22 @@ namespace Microsoft.MaciOS.Nnyeah.AssemblyComparator { public class ComparingVisitor { ModuleDefinition EarlierModule, LaterModule; bool PublicOnly; + NNyeahAssemblyResolver Resolver; - public ComparingVisitor (ModuleDefinition earlierModule, ModuleDefinition laterModule, bool publicOnly) + public ComparingVisitor (ModuleDefinition earlierModule, ModuleDefinition laterModule, NNyeahAssemblyResolver resolver, bool publicOnly) { EarlierModule = earlierModule; LaterModule = laterModule; PublicOnly = publicOnly; + Resolver = resolver; } public void Visit () { - var earlierElements = ModuleElements.Import (EarlierModule, PublicOnly); + var earlierElements = ModuleElements.Import (EarlierModule, Resolver, PublicOnly); if (earlierElements is null) throw new Exception (Errors.E0007); - var laterElements = ModuleElements.Import (LaterModule, PublicOnly); + var laterElements = ModuleElements.Import (LaterModule, Resolver, PublicOnly); if (laterElements is null) throw new Exception (Errors.E0007); var reworker = new TypeReworker (EarlierModule); diff --git a/tools/nnyeah/nnyeah/AssemblyComparator/ModuleElements.cs b/tools/nnyeah/nnyeah/AssemblyComparator/ModuleElements.cs index 0e73e4f1bb62..83566c72198d 100644 --- a/tools/nnyeah/nnyeah/AssemblyComparator/ModuleElements.cs +++ b/tools/nnyeah/nnyeah/AssemblyComparator/ModuleElements.cs @@ -12,7 +12,7 @@ public class ModuleElements { { } - public static ModuleElements Import (ModuleDefinition module, bool publicOnly) + public static ModuleElements Import (ModuleDefinition module, NNyeahAssemblyResolver resolver, bool publicOnly) { var moduleElements = new ModuleElements (); var typeStack = new Stack (); diff --git a/tools/nnyeah/nnyeah/AssemblyConverter.cs b/tools/nnyeah/nnyeah/AssemblyConverter.cs new file mode 100644 index 000000000000..d166c19ad06d --- /dev/null +++ b/tools/nnyeah/nnyeah/AssemblyConverter.cs @@ -0,0 +1,163 @@ +using System; +using System.IO; +using Mono.Options; +using System.Collections.Generic; +using Microsoft.MaciOS.Nnyeah.AssemblyComparator; +using Mono.Cecil; +using System.Diagnostics.CodeAnalysis; + +namespace Microsoft.MaciOS.Nnyeah { + // The standard entry point for assembly conversion + public class AssemblyConverter + { + string XamarinAssembly; + string MicrosoftAssembly; + string Infile; + string Outfile; + bool Verbose; + bool ForceOverwrite; + bool SuppressWarnings; + NNyeahAssemblyResolver Resolver; + + public static void Convert (string xamarinAssembly, string microsoftAssembly, string infile, string outfile, bool verbose, bool forceOverwrite, bool suppressWarnings) + { + var converter = new AssemblyConverter (xamarinAssembly, microsoftAssembly, infile, outfile, verbose, forceOverwrite, suppressWarnings); + converter.Convert (); + } + + AssemblyConverter (string xamarinAssembly, string microsoftAssembly, string infile, string outfile, bool verbose, bool forceOverwrite, bool suppressWarnings) + { + XamarinAssembly = xamarinAssembly; + MicrosoftAssembly = microsoftAssembly; + Infile = infile; + Outfile = outfile; + Verbose = verbose; + ForceOverwrite = forceOverwrite; + SuppressWarnings = suppressWarnings; + + Resolver = new NNyeahAssemblyResolver (Infile, XamarinAssembly); + } + + void Convert () + { + try { + var map = new TypeAndModuleMap (XamarinAssembly, MicrosoftAssembly, Resolver); + ReworkFile (map); + } + catch (Exception e) { + Console.Error.WriteLine (Errors.E0011, e.Message); + } + } + + void ReworkFile (TypeAndModuleMap map) + { + var warnings = new List (); + var transforms = new List (); + + if (!File.Exists (Infile)) { + throw new ConversionException (Errors.E0001, Infile); + } + + if (File.Exists (Outfile) && !ForceOverwrite) { + throw new ConversionException (Errors.E0002, Outfile); + } + + if (CreateReworker (map) is Reworker reworker) { + reworker.WarningIssued += (_, e) => warnings.Add (e.HelpfulMessage ()); + reworker.Transformed += (_, e) => warnings.Add (e.HelpfulMessage ()); + + try { + using var ostm = new FileStream (Outfile, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); + reworker.Rework (ostm); + if (Verbose) { + transforms.ForEach (Console.WriteLine); + } + if (!SuppressWarnings) { + warnings.ForEach (Console.WriteLine); + } + } catch (TypeNotFoundException e) { + throw new ConversionException (Errors.E0012, e.TypeName); + } catch (MemberNotFoundException e) { + throw new ConversionException (Errors.E0013, e.MemberName); + } catch (Exception e) { + throw new ConversionException (Errors.E0004, e.Message); + } + } else { + Console.WriteLine (Errors.N0003); + } + } + + Reworker? CreateReworker (TypeAndModuleMap map) + { + try { + var stm = new FileStream (Infile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); + var module = ModuleDefinition.ReadModule (stm, new ReaderParameters { AssemblyResolver = Resolver }); + var moduleContainer = new ModuleContainer (module, map.XamarinModule, map.MicrosoftModule); + + return Reworker.CreateReworker (stm, moduleContainer, map.TypeMap); + } catch (Exception e) { + throw new ConversionException (Errors.E0003, Infile, e.Message); + } + } + } + + class TypeAndModuleMap { + public TypeAndMemberMap TypeMap; + public ModuleDefinition XamarinModule; + public ModuleDefinition MicrosoftModule; + + public TypeAndModuleMap (string infile, string outfile, NNyeahAssemblyResolver resolver) + { + using var inFileStream = TryOpenRead (infile); + using var outFileStream = TryOpenRead (outfile); + + XamarinModule = ModuleDefinition.ReadModule (inFileStream, new ReaderParameters { AssemblyResolver = resolver }); + MicrosoftModule = ModuleDefinition.ReadModule (outFileStream, new ReaderParameters { AssemblyResolver = resolver }); + + var comparingVisitor = new ComparingVisitor (XamarinModule, MicrosoftModule, resolver, true); + TypeMap = new TypeAndMemberMap (); + + comparingVisitor.TypeEvents.NotFound += (_, e) => { + switch (e.Original.ToString()) { + case "System.nint": + case "System.nuint": + case "System.nfloat": + break; + case null: + throw new InvalidOperationException ("Null NotFound type event"); + default: + TypeMap.TypesNotPresent.Add (e.Original); + break; + } + }; + comparingVisitor.TypeEvents.Found += (s, e) => { TypeMap.TypeMap.Add (e.Original, e.Mapped); }; + + comparingVisitor.MethodEvents.NotFound += (s, e) => { TypeMap.MethodsNotPresent.Add (e.Original); }; + comparingVisitor.MethodEvents.Found += (s, e) => { TypeMap.MethodMap.Add (e.Original, e.Mapped); }; + + comparingVisitor.FieldEvents.NotFound += (s, e) => { TypeMap.FieldsNotPresent.Add (e.Original); }; + comparingVisitor.FieldEvents.Found += (s, e) => { TypeMap.FieldMap.Add (e.Original, e.Mapped); }; + + comparingVisitor.EventEvents.NotFound += (s, e) => { TypeMap.EventsNotPresent.Add (e.Original); }; + comparingVisitor.EventEvents.Found += (s, e) => { TypeMap.EventMap.Add (e.Original, e.Mapped); }; + + comparingVisitor.PropertyEvents.NotFound += (s, e) => { TypeMap.PropertiesNotPresent.Add (e.Original); }; + comparingVisitor.PropertyEvents.Found += (s, e) => { TypeMap.PropertyMap.Add (e.Original, e.Mapped); }; + + comparingVisitor.Visit (); + } + + static Stream TryOpenRead (string path) + { + try { + var stm = new FileStream (path, FileMode.Open, FileAccess.Read); + if (stm is null) { + throw new ConversionException (Errors.E0006, path, ""); + } + return stm; + } catch (Exception e) { + throw new ConversionException (Errors.E0006, path, e.Message); + } + } + } +} diff --git a/tools/nnyeah/nnyeah/AssemblyResolver.cs b/tools/nnyeah/nnyeah/AssemblyResolver.cs new file mode 100644 index 000000000000..98812db3d17d --- /dev/null +++ b/tools/nnyeah/nnyeah/AssemblyResolver.cs @@ -0,0 +1,19 @@ +using System.IO; +using Mono.Cecil; + + +namespace Microsoft.MaciOS.Nnyeah { + public class NNyeahAssemblyResolver : DefaultAssemblyResolver { + public NNyeahAssemblyResolver (string infile, string xamarinAssembly) : base () + { + // When resolving assemblies, look next to the platform assembly AND + // next to the input file. + // This must be done in a custom resolver to resolve type information + // such as the base type from types we are processing + // so we can answer questions like "Does this type derive from NSObject" + // from any number of inheritance levels + this.AddSearchDirectory (Path.GetDirectoryName (infile)); + this.AddSearchDirectory (Path.GetDirectoryName (xamarinAssembly)); + } + } +} diff --git a/tools/nnyeah/nnyeah/ConstructorTransforms.cs b/tools/nnyeah/nnyeah/ConstructorTransforms.cs new file mode 100644 index 000000000000..ad7fadaf76e1 --- /dev/null +++ b/tools/nnyeah/nnyeah/ConstructorTransforms.cs @@ -0,0 +1,75 @@ +using Mono.Cecil; +using Mono.Cecil.Rocks; +using System.Linq; + +using Microsoft.MaciOS.Nnyeah.AssemblyComparator; + +namespace Microsoft.MaciOS.Nnyeah { + // Converting constructors from Legacy to NET6 have some special concerns: + // - The arguments to NSObject's base class (IntPtr) and (IntPtr, bool) must be moved to NativeHandle, but _only_ if we're derived from NSObject + // - There are some absurd cases where people store off that IntPtr that we can't convert safely, so bail on non-trivial ctors + // - Invocations to said constructors need to be converted, but those should hopefully rare.... + public class ConstructorTransforms { + TypeReference NewNativeHandleTypeDefinition; + MethodDefinition IntPtrCtor; + MethodDefinition IntPtrCtorWithBool; + + public ConstructorTransforms (TypeReference newNativeHandleTypeDefinition, MethodDefinition intPtrCtor, MethodDefinition intPtrCtorWithBool) + { + NewNativeHandleTypeDefinition = newNativeHandleTypeDefinition; + IntPtrCtor = intPtrCtor; + IntPtrCtorWithBool = intPtrCtorWithBool; + } + + public void AddTransforms (TypeAndMemberMap moduleMap) + { + // Remove "NSObject (IntPtr)" from missing list and add "NSObject (NativeHandle)" + const string IntPtrCtorSignature = "System.Void Foundation.NSObject::.ctor(System.IntPtr)"; + moduleMap.MethodsNotPresent.Remove (IntPtrCtorSignature); + IntPtrCtor.Parameters[0].ParameterType = NewNativeHandleTypeDefinition; + moduleMap.MethodMap.Add (IntPtrCtorSignature, IntPtrCtor); + + // Remove "NSObject (IntPtr, bool)" from missing list and add "NSObject (NativeHandle,System.Boolean)" + const string IntPtrBoolCtorSignature = "System.Void Foundation.NSObject::.ctor(System.IntPtr,System.Boolean)"; + moduleMap.MethodsNotPresent.Remove (IntPtrBoolCtorSignature); + IntPtrCtorWithBool.Parameters[0].ParameterType = NewNativeHandleTypeDefinition; + moduleMap.MethodMap.Add (IntPtrBoolCtorSignature, IntPtrCtorWithBool); + } + + static bool IsIntPtrCtor (MethodDefinition d) + { + bool isSingle = d.Parameters.Count == 1 && + d.Parameters.First ().ParameterType.FullName == "System.IntPtr"; + bool isDouble = d.Parameters.Count == 2 && + d.Parameters.First ().ParameterType.FullName == "System.IntPtr" || + d.Parameters.Last ().ParameterType.FullName == "System.Boolean"; + return isSingle || isDouble; + } + + public bool IsNSObjectDerived (TypeReference? typeReference) + { + if (typeReference is null) { + return false; + } + if (typeReference.FullName == "Foundation.NSObject") { + return true; + } + return IsNSObjectDerived (typeReference.Resolve ().BaseType); + } + + public void ReworkAsNeeded (TypeDefinition definition) + { + if (IsNSObjectDerived (definition.BaseType)) { + if (definition.GetConstructors ().FirstOrDefault (IsIntPtrCtor) is MethodDefinition ctor) { + // How many instructions it takes to invoke a 1 or 2 param base ctor + // We can not safely process things that might store off the IntPtr + // or other such insanity, so just fail fast + if (ctor.Body.Instructions.Count > 7) { + throw new ConversionException (Errors.E0016); + } + ctor.Parameters[0].ParameterType = NewNativeHandleTypeDefinition; + } + } + } + } +} diff --git a/tools/nnyeah/nnyeah/Errors.Designer.cs b/tools/nnyeah/nnyeah/Errors.Designer.cs index 5db0e05f2cfd..b0e6d893deb2 100644 --- a/tools/nnyeah/nnyeah/Errors.Designer.cs +++ b/tools/nnyeah/nnyeah/Errors.Designer.cs @@ -184,5 +184,11 @@ internal static string E0015 { return ResourceManager.GetString("E0015", resourceCulture); } } + + internal static string E0016 { + get { + return ResourceManager.GetString("E0016", resourceCulture); + } + } } } diff --git a/tools/nnyeah/nnyeah/Errors.resx b/tools/nnyeah/nnyeah/Errors.resx index 661b9efb3b9e..d2e65869d2a9 100644 --- a/tools/nnyeah/nnyeah/Errors.resx +++ b/tools/nnyeah/nnyeah/Errors.resx @@ -94,5 +94,8 @@ Support legacy and NET assemblies --xamarin-assembly and --microsoft-assembly are currently required options. + + Error while processing constructor on type {0} in the old assembly. Constructors that do non-trivial work are not supported. + diff --git a/tools/nnyeah/nnyeah/Program.cs b/tools/nnyeah/nnyeah/Program.cs index f7c9c1380ebe..2d8545e0e19b 100644 --- a/tools/nnyeah/nnyeah/Program.cs +++ b/tools/nnyeah/nnyeah/Program.cs @@ -1,22 +1,7 @@ using System; -using System.IO; using Mono.Options; -using System.Collections.Generic; -using Microsoft.MaciOS.Nnyeah.AssemblyComparator; -using Mono.Cecil; -using System.Diagnostics.CodeAnalysis; namespace Microsoft.MaciOS.Nnyeah { - public class ConversionException : Exception { - public ConversionException (string message) : base (message) - { - } - - public ConversionException (string message, params object? [] args) : base (string.Format(message, args)) - { - } - } - public class Program { static int Main (string [] args) { @@ -70,158 +55,22 @@ static void Main2 (string [] args) } if (doHelp) { - PrintOptions (options, Console.Out); + options.WriteOptionDescriptions (Console.Out); + Console.Out.WriteLine (Errors.N0007); } else { - ProcessAssembly (xamarinAssembly!, microsoftAssembly!, infile!, outfile!, verbose, forceOverwrite, suppressWarnings); - } - } - - public static void ProcessAssembly (string xamarinAssembly, - string microsoftAssembly, string infile, string outfile, bool verbose, - bool forceOverwrite, bool suppressWarnings) - { - if (!TryLoadTypeAndModuleMap (xamarinAssembly!, microsoftAssembly!, publicOnly: true, - out var typeAndModuleMap, out var failureReason, out var xamarinModule, - out var microsoftModule)) { - Console.Error.WriteLine (Errors.E0011, failureReason); - } - ReworkFile (infile!, outfile!, verbose, forceOverwrite, suppressWarnings, typeAndModuleMap!, - xamarinModule!, microsoftModule!); - } - - static bool TryLoadTypeAndModuleMap (string earlier, string later, bool publicOnly, - [NotNullWhen (returnValue: true)] out TypeAndMemberMap? result, - [NotNullWhen (returnValue: false)] out string? reason, - [NotNullWhen (returnValue: true)] out ModuleDefinition? xamarinModule, - [NotNullWhen (returnValue: true)] out ModuleDefinition? microsoftModule) - { - try { - using var ealierFile = TryOpenRead (earlier); - using var laterFile = TryOpenRead (later); - - var earlierModule = ModuleDefinition.ReadModule (ealierFile); - var laterModule = ModuleDefinition.ReadModule (laterFile); - - var comparingVisitor = new ComparingVisitor (earlierModule, laterModule, publicOnly); - var map = new TypeAndMemberMap (); - - comparingVisitor.TypeEvents.NotFound += (_, e) => { - switch (e.Original.ToString()) { - case "System.nint": - case "System.nuint": - case "System.nfloat": - break; - case null: - throw new InvalidOperationException ("Null NotFound type event"); - default: - map.TypesNotPresent.Add (e.Original); - break; - } - }; - comparingVisitor.TypeEvents.Found += (s, e) => { map.TypeMap.Add (e.Original, e.Mapped); }; - - comparingVisitor.MethodEvents.NotFound += (s, e) => { map.MethodsNotPresent.Add (e.Original); }; - comparingVisitor.MethodEvents.Found += (s, e) => { map.MethodMap.Add (e.Original, e.Mapped); }; - - comparingVisitor.FieldEvents.NotFound += (s, e) => { map.FieldsNotPresent.Add (e.Original); }; - comparingVisitor.FieldEvents.Found += (s, e) => { map.FieldMap.Add (e.Original, e.Mapped); }; - - comparingVisitor.EventEvents.NotFound += (s, e) => { map.EventsNotPresent.Add (e.Original); }; - comparingVisitor.EventEvents.Found += (s, e) => { map.EventMap.Add (e.Original, e.Mapped); }; - - comparingVisitor.PropertyEvents.NotFound += (s, e) => { map.PropertiesNotPresent.Add (e.Original); }; - comparingVisitor.PropertyEvents.Found += (s, e) => { map.PropertyMap.Add (e.Original, e.Mapped); }; - - comparingVisitor.Visit (); - result = map; - reason = null; - xamarinModule = earlierModule; - microsoftModule = laterModule; - return true; - } catch (Exception e) { - result = null; - reason = e.Message; - xamarinModule = null; - microsoftModule = null; - return false; - } - } - - static Reworker? CreateReworker (string infile, TypeAndMemberMap typeMap, - ModuleDefinition xamarinModule, ModuleDefinition microsoftModule) - { - try { - var stm = new FileStream (infile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite); - var module = ModuleDefinition.ReadModule (stm); - var moduleContainer = new ModuleContainer (module, xamarinModule, microsoftModule); - - return Reworker.CreateReworker (stm, moduleContainer, typeMap); - } catch (Exception e) { - throw new ConversionException (Errors.E0003, infile, e.Message); - } - } - - - static void ReworkFile (string infile, string outfile, bool verbose, bool forceOverwrite, - bool suppressWarnings, TypeAndMemberMap typeMap, ModuleDefinition xamarinModule, - ModuleDefinition microsoftModule) - { - var warnings = new List (); - var transforms = new List (); - - if (!File.Exists (infile)) { - throw new ConversionException (Errors.E0001, infile); - } - - if (File.Exists (outfile) && !forceOverwrite) { - throw new ConversionException (Errors.E0002, outfile); - } - - if (CreateReworker (infile, typeMap, xamarinModule, microsoftModule) is Reworker reworker) { - reworker.WarningIssued += (_, e) => warnings.Add (e.HelpfulMessage ()); - reworker.Transformed += (_, e) => warnings.Add (e.HelpfulMessage ()); - - try { - using var ostm = new FileStream (outfile, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite); - reworker.Rework (ostm); - if (verbose) { - transforms.ForEach (Console.WriteLine); - } - if (!suppressWarnings) { - warnings.ForEach (Console.WriteLine); - } - } catch (TypeNotFoundException e) { - throw new ConversionException (Errors.E0012, e.TypeName); - } catch (MemberNotFoundException e) { - throw new ConversionException (Errors.E0013, e.MemberName); - } catch (Exception e) { - throw new ConversionException (Errors.E0004, e.Message); - } - } else { - if (verbose) { - Console.WriteLine (Errors.N0003); - } + AssemblyConverter.Convert (xamarinAssembly!, microsoftAssembly!, infile!, outfile!, verbose, forceOverwrite, suppressWarnings); } } + } - static Stream TryOpenRead (string path) + public class ConversionException : Exception { + public ConversionException (string message) : base (message) { - try { - var stm = new FileStream (path, FileMode.Open, FileAccess.Read); - if (stm is null) { - throw new ConversionException (Errors.E0006, path, ""); - } - return stm; - } catch (Exception e) { - throw new ConversionException (Errors.E0006, path, e.Message); - } } - static void PrintOptions (OptionSet options, TextWriter writer) + public ConversionException (string message, params object? [] args) : base (string.Format (message, args)) { - options.WriteOptionDescriptions (writer); - writer.WriteLine (Errors.N0007); } } } diff --git a/tools/nnyeah/nnyeah/Reworker.cs b/tools/nnyeah/nnyeah/Reworker.cs index dddbe2186f63..465bf09b3792 100644 --- a/tools/nnyeah/nnyeah/Reworker.cs +++ b/tools/nnyeah/nnyeah/Reworker.cs @@ -41,6 +41,7 @@ public class Reworker { Dictionary MethodSubs; Dictionary FieldSubs; + ConstructorTransforms ConstructorTransforms; public event EventHandler? WarningIssued; public event EventHandler? Transformed; @@ -49,15 +50,14 @@ public static bool NeedsReworking (ModuleDefinition module) { // simple predicate for seeing if there any references // to types we need to care about. - // IntPtr is for future handling of types that - // descend from NObject and need to have the constructor - // changed to NHandle + // Foundation.NSObject is for handling of types that + // descend from NObject and need to have the constructor changed return module.GetTypeReferences ().Any ( tr => tr.FullName == "System.nint" || tr.FullName == "System.nuint" || tr.FullName == "System.nfloat" || - tr.FullName == "System.IntPtr" + tr.FullName == "Foundation.NSObject" ); } @@ -123,6 +123,11 @@ public static bool NeedsReworking (ModuleDefinition module) NewNativeHandleTypeDefinition = modules.MicrosoftModule.Types.First (t => t.FullName == "ObjCRuntime.NativeHandle"); // These must be called last as they depend on Module and NativeIntegerAttributeTypeRef to be setup + var intPtrCtor = modules.XamarinModule.Types.First (t => t.FullName == "Foundation.NSObject").Methods.First (m => m.FullName == "System.Void Foundation.NSObject::.ctor(System.IntPtr)"); + var intPtrCtorWithBool = modules.XamarinModule.Types.First (t => t.FullName == "Foundation.NSObject").Methods.First (m => m.FullName == "System.Void Foundation.NSObject::.ctor(System.IntPtr,System.Boolean)"); + ConstructorTransforms = new ConstructorTransforms (ModuleToEdit.ImportReference (NewNativeHandleTypeDefinition), intPtrCtor, intPtrCtorWithBool); + ConstructorTransforms.AddTransforms (ModuleMap); + MethodSubs = LoadMethodSubs (); FieldSubs = LoadFieldSubs (); } @@ -279,11 +284,11 @@ Dictionary LoadFieldSubs () public void Rework (Stream stm) { + ReplacePlatformAssemblyReference (); foreach (var type in ModuleToEdit.Types) { ReworkType (type); } ChangeTargetFramework (); - RemoveXamarinReferences (); ModuleToEdit.Write (stm); stm.Flush (); } @@ -309,11 +314,11 @@ bool TryGetTargetFrameworkAttribute ([NotNullWhen (returnValue: true)] out Custo return false; } - void RemoveXamarinReferences () + void ReplacePlatformAssemblyReference () { for (int i = ModuleToEdit.AssemblyReferences.Count - 1; i >= 0; i--) { if (IsXamarinReference (ModuleToEdit.AssemblyReferences [i])) { - ModuleToEdit.AssemblyReferences.RemoveAt (i); + ModuleToEdit.AssemblyReferences[i] = new AssemblyNameReference (Modules.MicrosoftModule.Assembly.Name.Name, Modules.MicrosoftModule.Assembly.Name.Version); } } } @@ -332,6 +337,8 @@ static bool IsXamarinReference (AssemblyNameReference reference) void ReworkType (TypeDefinition definition) { + ConstructorTransforms.ReworkAsNeeded (definition); + foreach (var field in definition.Fields) { ReworkField (field); } diff --git a/tools/nnyeah/tests/integration/IntegrationExamples.cs b/tools/nnyeah/tests/integration/IntegrationExamples.cs index 6876dfaf1000..6c8d51995bc8 100644 --- a/tools/nnyeah/tests/integration/IntegrationExamples.cs +++ b/tools/nnyeah/tests/integration/IntegrationExamples.cs @@ -1,5 +1,3 @@ -#define NNYEAH_IN_PROCESS - using System; using System.Collections.Generic; using System.IO; @@ -57,29 +55,9 @@ async Task AssertLegacyBuild (string project, ApplePlatform platform) Assert.Zero (execution.ExitCode, $"Build Output: {output}"); } - async Task ExecuteNnyeah (string tmpDir, string inputPath, string convertedPath, ApplePlatform platform) + void ExecuteNnyeah (string tmpDir, string inputPath, string convertedPath, ApplePlatform platform) { -#if NNYEAH_IN_PROCESS - Program.ProcessAssembly (GetLegacyPlatform(platform), GetNetPlatform(platform), inputPath, convertedPath, true, true, false); -#else - var args = new List { "nnyeah", $"--input={inputPath}", $"--output={convertedPath}", $"--xamarin-assembly={GetLegacyPlatform(platform)}", - $"--microsoft-assembly={GetNetPlatform(platform)}", "--force-overwrite"}; - Execution execution = await Execution.RunAsync (DotNet.Executable, args, null, mergeOutput: true, workingDirectory: tmpDir); - Assert.Zero (execution.ExitCode, $"Nnyeah Output: {execution.StandardOutput}"); -#endif - } - - async Task InstallNnyeah (string dir) - { -#if !NNYEAH_IN_PROCESS - var args = new List { "new", "tool-manifest" }; - Execution execution = await Execution.RunAsync (DotNet.Executable, args, null, mergeOutput: true, workingDirectory: dir); - Assert.Zero (execution.ExitCode, execution.StandardOutput!.ToString()); - - args = new List { "tool", "install", "nnyeah", "--local", "--add-source", NnyeahNupkg }; - execution = await Execution.RunAsync (DotNet.Executable, args, null, mergeOutput: true, workingDirectory: dir); - Assert.Zero (execution.ExitCode, execution.StandardOutput!.ToString()); -#endif + AssemblyConverter.Convert (GetLegacyPlatform (platform), GetNetPlatform (platform), inputPath, convertedPath, true, true, false); } [Test] @@ -97,8 +75,7 @@ public async Task BuildAndRunSynthetic (string libraryProject, string libraryPat var tmpDir = Cache.CreateTemporaryDirectory ("BuildAndRunSynthetic"); - await InstallNnyeah (tmpDir); - await ExecuteNnyeah (tmpDir, inputPath, convertedPath, platform); + ExecuteNnyeah (tmpDir, inputPath, convertedPath, platform); DotNet.AssertBuild (Path.Combine (IntegrationRoot, consumerProject)); } @@ -297,8 +274,7 @@ public async Task NugetExamples (string downloadUrl, string libraryPath, ApplePl string convertedPath = Path.Combine (convertedDir, Path.GetFileName (libraryPath)); - await InstallNnyeah (tmpDir); - await ExecuteNnyeah (tmpDir, nugetPath, convertedPath, platform); + ExecuteNnyeah (tmpDir, nugetPath, convertedPath, platform); } } } diff --git a/tools/nnyeah/tests/unit/CompileALibrary.cs b/tools/nnyeah/tests/unit/CompileALibrary.cs index a62ba7ca2675..e37fbed52314 100644 --- a/tools/nnyeah/tests/unit/CompileALibrary.cs +++ b/tools/nnyeah/tests/unit/CompileALibrary.cs @@ -11,16 +11,11 @@ public class CompileALibrary { [Test] public async Task BasicLibrary () { - var dir = Cache.CreateTemporaryDirectory ("BasicLibrary"); - var code = @" + await TestRunning.BuildTemporaryLibrary (@" using System; public class Foo { public nint Ident (nint e) => e; -} -"; - var output = await TestRunning.BuildLibrary (code, "NoName", dir); - var expectedOutputFile = Path.Combine (dir, "NoName.dll"); - Assert.IsTrue (File.Exists (expectedOutputFile)); +}"); } [Test] @@ -47,7 +42,7 @@ public class Foo { Assert.IsTrue (File.Exists (libraryFile)); var convertedFile = Path.Combine (dir, "NoName-Converted.dll"); - Program.ProcessAssembly (Compiler.XamarinPlatformLibraryPath (PlatformName.macOS), Compiler.MicrosoftPlatformLibraryPath (PlatformName.macOS), libraryFile, convertedFile, true, true, false); + AssemblyConverter.Convert (Compiler.XamarinPlatformLibraryPath (PlatformName.macOS), Compiler.MicrosoftPlatformLibraryPath (PlatformName.macOS), libraryFile, convertedFile, true, true, false); } [Test] diff --git a/tools/nnyeah/tests/unit/ConstructorTransformTests.cs b/tools/nnyeah/tests/unit/ConstructorTransformTests.cs new file mode 100644 index 000000000000..2ca61c54475d --- /dev/null +++ b/tools/nnyeah/tests/unit/ConstructorTransformTests.cs @@ -0,0 +1,141 @@ +using System.Threading.Tasks; +using NUnit.Framework; +using Mono.Cecil; +using Mono.Cecil.Rocks; +using System.Linq; + +namespace Microsoft.MaciOS.Nnyeah.Tests { + + [TestFixture] + public class ConstructorTransformTests { + static ReaderParameters ReaderParameters { + get { + var legacyPlatform = Compiler.XamarinPlatformLibraryPath (PlatformName.macOS); + var netPlatform = Compiler.MicrosoftPlatformLibraryPath (PlatformName.macOS); + + // We must use a resolver here as the types will be Resolved()'ed later + return new ReaderParameters { AssemblyResolver = new NNyeahAssemblyResolver (legacyPlatform, netPlatform) }; + } + } + + static async Task CompileTypeForTest (string code) + { + string lib = await TestRunning.BuildTemporaryLibrary (code); + var module = ModuleDefinition.ReadModule (lib, ReaderParameters); + return module.GetType ("Foo"); + } + + static ConstructorTransforms CreateTestTransform (TypeDefinition type) + { + var legacyPlatform = Compiler.XamarinPlatformLibraryPath (PlatformName.macOS); + var netPlatform = Compiler.MicrosoftPlatformLibraryPath (PlatformName.macOS); + + var legacyAssembly = ModuleDefinition.ReadModule (legacyPlatform, ReaderParameters); + var netAssembly = ModuleDefinition.ReadModule (netPlatform, ReaderParameters); + + var legacyNSObject = legacyAssembly.Types.First (t => t.FullName == "Foundation.NSObject"); + + return new ConstructorTransforms ( + netAssembly.GetType("ObjCRuntime.NativeHandle"), + legacyNSObject.Methods.First (m => m.FullName == "System.Void Foundation.NSObject::.ctor(System.IntPtr)"), + legacyNSObject.Methods.First (m => m.FullName == "System.Void Foundation.NSObject::.ctor(System.IntPtr,System.Boolean)") + ); + } + + [Test] + public async Task DerivedFromNSObject () + { + var type = await CompileTypeForTest (@" +using System; +using Foundation; +public class Foo : NSObject { + public Foo (IntPtr p) : base (p) { } +}"); + CreateTestTransform (type).ReworkAsNeeded (type); + + var ctor = type.GetConstructors ().First (); + Assert.AreEqual ("ObjCRuntime.NativeHandle", ctor.Parameters[0].ParameterType.FullName); + Assert.AreEqual (ctor.FullName, "System.Void Foo::.ctor(ObjCRuntime.NativeHandle)"); + } + + [Test] + public async Task DerivedFromNSObjectWithBool () + { + var type = await CompileTypeForTest (@" +using System; +using Foundation; +public class Foo : NSObject { + public Foo (IntPtr p, bool b) : base (p, b) { } +}"); + CreateTestTransform (type).ReworkAsNeeded (type); + + var ctor = type.GetConstructors ().First (); + Assert.AreEqual ("ObjCRuntime.NativeHandle", ctor.Parameters[0].ParameterType.FullName); + Assert.AreEqual ("System.Boolean", ctor.Parameters[1].ParameterType.FullName); + } + + // [Test] - https://github.com/xamarin/xamarin-macios/issues/15133 + public async Task InvokeCtor () + { + var type = await CompileTypeForTest (@" +using System; +using Foundation; +public class Foo : NSObject { + public Foo (IntPtr p) : base (p) { } + public Foo Create () => new Foo (IntPtr.Zero); +}"); + CreateTestTransform (type).ReworkAsNeeded (type); + + var ctor = type.GetConstructors ().First (); + Assert.AreEqual ("ObjCRuntime.NativeHandle", ctor.Parameters[0].ParameterType.FullName); + } + + [Test] + public async Task RefuseToProcessCtorWithBehavior () + { + var type = await CompileTypeForTest (@" +using System; +using Foundation; +public class Foo : NSObject { + public Foo (IntPtr p) : base (p) { Console.Error.WriteLine (typeof(int)); } +}"); + Assert.Throws (() => CreateTestTransform (type).ReworkAsNeeded (type)); + } + + [Test] + public async Task DerivedFromNSObjectDerived () + { + var type = await CompileTypeForTest (@" +using System; +using Foundation; +public class BaseFoo : NSObject { + public BaseFoo (IntPtr p) : base (p) { } +} +public class Foo : BaseFoo { + public Foo (IntPtr p) : base (p) { } +} +"); + CreateTestTransform (type).ReworkAsNeeded (type); + + var ctor = type.GetConstructors().First(); + Assert.AreEqual ("ObjCRuntime.NativeHandle", ctor.Parameters[0].ParameterType.FullName); + } + + [Test] + public async Task NotNSObjectJustIntPtr () + { + var type = await CompileTypeForTest (@" +using System; +using Foundation; +public class Foo { + public Foo (IntPtr p) { } +}"); + + CreateTestTransform (type).ReworkAsNeeded (type); + + var ctor = type.GetConstructors ().First (); + Assert.AreEqual ("System.IntPtr", ctor.Parameters[0].ParameterType.FullName); + } + + } +} diff --git a/tools/nnyeah/tests/unit/DependencyRemovedTests.cs b/tools/nnyeah/tests/unit/DependencyRemovedTests.cs index 48976864cef7..dbd2f12a8545 100644 --- a/tools/nnyeah/tests/unit/DependencyRemovedTests.cs +++ b/tools/nnyeah/tests/unit/DependencyRemovedTests.cs @@ -22,12 +22,12 @@ public class Foo {{ public {type} Ident ({type} e) => e; }} "; - var output = await TestRunning.BuildLibrary (code, "NoName", dir); + await TestRunning.BuildLibrary (code, "NoName", dir); var expectedOutputFile = Path.Combine (dir, "NoName.dll"); var targetRewrite = Path.Combine (dir, "NoNameRemoved.dll"); Assert.DoesNotThrow (() => { - Program.ProcessAssembly (Compiler.XamarinPlatformLibraryPath (PlatformName.macOS), + AssemblyConverter.Convert (Compiler.XamarinPlatformLibraryPath (PlatformName.macOS), Compiler.MicrosoftPlatformLibraryPath (PlatformName.macOS), expectedOutputFile, targetRewrite, verbose: false, forceOverwrite: true, suppressWarnings: true); }, $"Failed to process assembly for type {type}"); diff --git a/tools/nnyeah/tests/unit/XamarinDependencyTests.cs b/tools/nnyeah/tests/unit/XamarinDependencyTests.cs index 7792869286c9..e04a9a882e3a 100644 --- a/tools/nnyeah/tests/unit/XamarinDependencyTests.cs +++ b/tools/nnyeah/tests/unit/XamarinDependencyTests.cs @@ -18,7 +18,7 @@ public class Foo { public nint Ident (nint e) => e; } "; - var output = await TestRunning.BuildLibrary (code, "NoName", dir); + await TestRunning.BuildLibrary (code, "NoName", dir); var expectedOutputFile = Path.Combine (dir, "NoName.dll"); var module = ModuleDefinition.ReadModule (expectedOutputFile); @@ -36,7 +36,7 @@ public class Foo { public char Ident (char e) => e; } "; - var output = await TestRunning.BuildLibrary (code, "NoName", dir); + await TestRunning.BuildLibrary (code, "NoName", dir); var expectedOutputFile = Path.Combine (dir, "NoName.dll"); var module = ModuleDefinition.ReadModule (expectedOutputFile); diff --git a/tools/nnyeah/tests/unit/utils/TestRunning.cs b/tools/nnyeah/tests/unit/utils/TestRunning.cs index 94a86d50f105..e4682d7db260 100644 --- a/tools/nnyeah/tests/unit/utils/TestRunning.cs +++ b/tools/nnyeah/tests/unit/utils/TestRunning.cs @@ -34,13 +34,22 @@ public static async Task TestAndExecute (string libraryCode, string callingCode, var initialLibraryDir = Cache.CreateTemporaryDirectory (); var finalLibraryDir = Cache.CreateTemporaryDirectory (); - var libCompilerOutput = await BuildLibrary (libraryCode, testName, initialLibraryDir); + await BuildLibrary (libraryCode, testName, initialLibraryDir); } - public static Task BuildLibrary (string libraryCode, string libName, string outputDirectory, PlatformName platformName = PlatformName.macOS) + public static async Task BuildLibrary (string libraryCode, string libName, string outputDirectory, PlatformName platformName = PlatformName.macOS) { var outputPath = Path.Combine (outputDirectory, $"{libName}.dll"); - return Compiler.CompileText (libraryCode, outputPath, platformName, isLibrary: true); + string msg = await Compiler.CompileText (libraryCode, outputPath, platformName, isLibrary: true); + Assert.IsTrue (File.Exists (outputPath), $"Compile failed with output: {msg}"); + } + + public static async Task BuildTemporaryLibrary (string code) + { + var dir = Cache.CreateTemporaryDirectory ("BuildTemporaryLibrary"); + await TestRunning.BuildLibrary (code, "NoName", dir); + var libraryFile = Path.Combine (dir, "NoName.dll"); + return libraryFile; } } } From 4542fce4a200caa108a4db6528adeb385220e276 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 31 May 2022 18:17:01 +0200 Subject: [PATCH 13/15] Bump maccore. (#15158) New commits in xamarin/maccore: * xamarin/maccore@713bcb2442 [mlaunch] Flush the output from the pty. Diff: https://github.com/xamarin/maccore/compare/29e384e9e3eada3066d9b70c03c48803876a9ea6..713bcb2442ac70e1741f4dccd2afa5cfed546fdb --- mk/xamarin.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mk/xamarin.mk b/mk/xamarin.mk index 5554b4536526..0e0cac78deda 100644 --- a/mk/xamarin.mk +++ b/mk/xamarin.mk @@ -7,7 +7,7 @@ MONO_BRANCH := $(shell cd $(MONO_PATH) 2> /dev/null && git symbolic-ref --sho endif ifdef ENABLE_XAMARIN -NEEDED_MACCORE_VERSION := 29e384e9e3eada3066d9b70c03c48803876a9ea6 +NEEDED_MACCORE_VERSION := 713bcb2442ac70e1741f4dccd2afa5cfed546fdb NEEDED_MACCORE_BRANCH := main MACCORE_DIRECTORY := maccore From 74380ebcd21af34ed269bf522d730f123916923d Mon Sep 17 00:00:00 2001 From: VS MobileTools Engineering Service 2 Date: Tue, 31 May 2022 09:42:02 -0700 Subject: [PATCH 14/15] Localized file check-in by OneLocBuild Task: Build definition ID 14411: Build ID 6217070 (#15150) --- tools/mtouch/TranslatedAssemblies/Errors.cs.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.de.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.es.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.fr.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.it.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.ja.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.ko.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.pl.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.pt-BR.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.ru.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.tr.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.zh-Hans.resx | 7 +++++++ tools/mtouch/TranslatedAssemblies/Errors.zh-Hant.resx | 7 +++++++ 13 files changed, 91 insertions(+) diff --git a/tools/mtouch/TranslatedAssemblies/Errors.cs.resx b/tools/mtouch/TranslatedAssemblies/Errors.cs.resx index 718f1679d3f6..3f8d1bd38b54 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.cs.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.cs.resx @@ -1743,4 +1743,11 @@ Nelze vytvořit instanci typu {0}. + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.de.resx b/tools/mtouch/TranslatedAssemblies/Errors.de.resx index adeb64fd9824..51086fbd97ce 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.de.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.de.resx @@ -1743,4 +1743,11 @@ Es kann keine Instanz des Typs {0}erstellt werden. + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.es.resx b/tools/mtouch/TranslatedAssemblies/Errors.es.resx index 9052edb2db0f..080d4f1f1de7 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.es.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.es.resx @@ -1743,4 +1743,11 @@ No se puede crear una instancia de tipo {0}. + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.fr.resx b/tools/mtouch/TranslatedAssemblies/Errors.fr.resx index 9283461907e7..c09fad86a8bf 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.fr.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.fr.resx @@ -1743,4 +1743,11 @@ Impossible de créer une instance du type {0}. + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.it.resx b/tools/mtouch/TranslatedAssemblies/Errors.it.resx index 1fd8ca0f881c..5a78532ff09e 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.it.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.it.resx @@ -1743,4 +1743,11 @@ Impossibile creare un'istanza del tipo di {0}. + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.ja.resx b/tools/mtouch/TranslatedAssemblies/Errors.ja.resx index c5e39edb7ecd..b09347377bcb 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.ja.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.ja.resx @@ -1744,4 +1744,11 @@ 型 {0} のインスタンスを作成できません。 + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.ko.resx b/tools/mtouch/TranslatedAssemblies/Errors.ko.resx index b39230e0291e..6769d399db94 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.ko.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.ko.resx @@ -1743,4 +1743,11 @@ {0} 형식의 인스턴스를 만들 수 없습니다. + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.pl.resx b/tools/mtouch/TranslatedAssemblies/Errors.pl.resx index 713e692699a6..d0a33106e8b5 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.pl.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.pl.resx @@ -1743,4 +1743,11 @@ Nie można utworzyć wystąpienia typu {0}. + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.pt-BR.resx b/tools/mtouch/TranslatedAssemblies/Errors.pt-BR.resx index 685558f10c88..ec5121d52a1e 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.pt-BR.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.pt-BR.resx @@ -1743,4 +1743,11 @@ Não foi possível criar uma instância do tipo {0}. + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.ru.resx b/tools/mtouch/TranslatedAssemblies/Errors.ru.resx index e20061cf14c8..fdb0e0335954 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.ru.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.ru.resx @@ -1743,4 +1743,11 @@ Невозможно создать экземпляр типа {0}. + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.tr.resx b/tools/mtouch/TranslatedAssemblies/Errors.tr.resx index a9ba0fd314a1..51b15370c486 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.tr.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.tr.resx @@ -1743,4 +1743,11 @@ {0} türünde örnek oluşturulamıyor. + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.zh-Hans.resx b/tools/mtouch/TranslatedAssemblies/Errors.zh-Hans.resx index 78258a2820c6..4b4fdbf6d413 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.zh-Hans.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.zh-Hans.resx @@ -1743,4 +1743,11 @@ 无法创建类型 {0} 的实例。 + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file diff --git a/tools/mtouch/TranslatedAssemblies/Errors.zh-Hant.resx b/tools/mtouch/TranslatedAssemblies/Errors.zh-Hant.resx index 7114bb5060ff..9e109829cfb9 100644 --- a/tools/mtouch/TranslatedAssemblies/Errors.zh-Hant.resx +++ b/tools/mtouch/TranslatedAssemblies/Errors.zh-Hant.resx @@ -1743,4 +1743,11 @@ 無法建立 {0} 類型的執行個體。 + + An exception occurred while trying to invoke the function {0}: {1}. + + 0: name of function + 1: exception info + + \ No newline at end of file From 8fff1548cb0525ca5f751b143f96d2d17340edc1 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 31 May 2022 18:43:01 +0200 Subject: [PATCH 15/15] Add newlines to issue template to fix markdown formatting problems. (#15152) --- ISSUE_TEMPLATE.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ISSUE_TEMPLATE.md b/ISSUE_TEMPLATE.md index e47e9a98d33f..2cb288818e61 100644 --- a/ISSUE_TEMPLATE.md +++ b/ISSUE_TEMPLATE.md @@ -25,8 +25,10 @@ For support requests use https://www.xamarin.com/support
Version information + ``` ``` +
### Build Logs