From 55837e3d8037370f97b4fe075999340b3deb297c Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Fri, 7 Dec 2018 15:07:21 +0100 Subject: [PATCH 01/23] [xharness] Handle Process.HasExited throwing exceptions. (#5239) Apparently Process.HasExited may throw exceptions, so handle those gracefully (by ignoring them completely): Unhandled Exception: System.AggregateException: One or more errors occurred. (No process is associated with this object.) ---> System.InvalidOperationException: No process is associated with this object. at System.Diagnostics.Process.EnsureState (System.Diagnostics.Process+State state) [0x00018] in :0 at System.Diagnostics.Process.get_HasExited () [0x0000b] in :0 at (wrapper remoting-invoke-with-check) System.Diagnostics.Process.get_HasExited() at xharness.Process_Extensions+<>c__DisplayClass2_0.b__2 () [0x00001] in <285dbdcf9e034cd496a3fef953fac640>:0 at System.Threading.CancellationToken.ActionToActionObjShunt (System.Object obj) [0x00000] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.CancellationCallbackInfo.ExecutionContextCallback (System.Object obj) [0x00007] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00071] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state) [0x0002b] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.CancellationCallbackInfo.ExecuteCallback () [0x00024] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.CancellationTokenSource.CancellationCallbackCoreWork (System.Threading.CancellationCallbackCoreWorkArguments args) [0x00042] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers (System.Boolean throwOnFirstException) [0x000c0] in <96207d0baa204f48a53ad6be05f5ecba>:0 --- End of inner exception stack trace --- at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers (System.Boolean throwOnFirstException) [0x00132] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.CancellationTokenSource.NotifyCancellation (System.Boolean throwOnFirstException) [0x0005f] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.CancellationTokenSource.Cancel (System.Boolean throwOnFirstException) [0x00006] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.CancellationTokenSource.Cancel () [0x00000] in <96207d0baa204f48a53ad6be05f5ecba>:0 at xharness.AppRunner+<>c__DisplayClass73_0.b__0 (System.Object v) [0x00029] in <285dbdcf9e034cd496a3fef953fac640>:0 at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context (System.Object state) [0x00007] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00071] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem () [0x00021] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.ThreadPoolWorkQueue.Dispatch () [0x00074] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback () [0x00000] in <96207d0baa204f48a53ad6be05f5ecba>:0 ---> (Inner Exception #0) System.InvalidOperationException: No process is associated with this object. at System.Diagnostics.Process.EnsureState (System.Diagnostics.Process+State state) [0x00018] in :0 at System.Diagnostics.Process.get_HasExited () [0x0000b] in :0 at (wrapper remoting-invoke-with-check) System.Diagnostics.Process.get_HasExited() at xharness.Process_Extensions+<>c__DisplayClass2_0.b__2 () [0x00001] in <285dbdcf9e034cd496a3fef953fac640>:0 at System.Threading.CancellationToken.ActionToActionObjShunt (System.Object obj) [0x00000] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.CancellationCallbackInfo.ExecutionContextCallback (System.Object obj) [0x00007] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00071] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.ExecutionContext.Run (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state) [0x0002b] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.CancellationCallbackInfo.ExecuteCallback () [0x00024] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.CancellationTokenSource.CancellationCallbackCoreWork (System.Threading.CancellationCallbackCoreWorkArguments args) [0x00042] in <96207d0baa204f48a53ad6be05f5ecba>:0 at System.Threading.CancellationTokenSource.ExecuteCallbackHandlers (System.Boolean throwOnFirstException) [0x000c0] in <96207d0baa204f48a53ad6be05f5ecba>:0 <--- --- tests/xharness/Process_Extensions.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tests/xharness/Process_Extensions.cs b/tests/xharness/Process_Extensions.cs index 0a2ff386ed..c07549de09 100644 --- a/tests/xharness/Process_Extensions.cs +++ b/tests/xharness/Process_Extensions.cs @@ -128,9 +128,18 @@ namespace xharness process.BeginOutputReadLine (); cancellation_token?.Register (() => { - if (!process.HasExited) { - StderrStream.WriteLine ($"Execution was cancelled."); - ProcessHelper.kill (process.Id, 9); + var hasExited = false; + try { + hasExited = process.HasExited; + } catch { + // Process.HasExited can sometimes throw exceptions, so + // just ignore those and to be safe treat it as the + // process didn't exit (the safe option being to not leave + // processes behind). + } + if (!hasExited) { + StderrStream.WriteLine ($"Execution of {pid} was cancelled."); + ProcessHelper.kill (pid, 9); } }); From 3621032ddc3bb48f907f05f1a32f32890fe4eadf Mon Sep 17 00:00:00 2001 From: Alex Soto Date: Fri, 7 Dec 2018 14:20:30 -0500 Subject: [PATCH 02/23] [AppKit] Adds some [ThreadSafe] to reported cases (#5238) * [AppKit] Adds some [ThreadSafe] to reported cases Fixes xamarin/xamarin-macios#5233 Fixes xamarin/xamarin-macios#5234 Fixes xamarin/xamarin-macios#5235 The following classes are thread safe: * NSFont [2] * NSBezierPath [1] * NSString [1] [1]: https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Multithreading/ThreadSafetySummary/ThreadSafetySummary.html [2]: https://developer.apple.com/library/archive/documentation/TextFonts/Conceptual/CocoaTextArchitecture/FontHandling/FontHandling.html --- src/appkit.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/appkit.cs b/src/appkit.cs index e22ff4a67b..8fcd76cf9e 100644 --- a/src/appkit.cs +++ b/src/appkit.cs @@ -1151,7 +1151,8 @@ namespace AppKit { [Export ("setSelectedObjects:"), Protected] bool SetSelectedObjects (NSObject [] objects); } - + + [ThreadSafe] [BaseType (typeof (NSObject))] interface NSBezierPath : NSSecureCoding, NSCopying { @@ -6184,6 +6185,7 @@ namespace AppKit { NSFontPanelModeMask GetValidModes (NSFontPanel fontPanel); } + [ThreadSafe] [BaseType (typeof (NSObject))] [DisableDefaultCtor] // crash at runtime (e.g. description). Documentation state: "You don’t create NSFont objects using the alloc and init methods." partial interface NSFont : NSSecureCoding, NSCopying { @@ -9703,6 +9705,7 @@ namespace AppKit { CGRect TotalBounds { get; } } + [ThreadSafe] [Category, BaseType (typeof (NSString))] interface NSStringDrawing_NSString { [Export ("sizeWithAttributes:")] From 7c4aa8cbf860ac15e4b45b0d3961159ca2975faf Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Mon, 10 Dec 2018 08:09:39 +0100 Subject: [PATCH 03/23] bump mono (2018-08) (#5241) * bump mono (2018-08) Commit list for mono/mono: * mono/mono@f919fb58c4e Fix https://github.com/mono/mono/issues/11898 (#11904) * mono/mono@95fbc224368 Fix race condition in XmlCharType.Instance (#11828) * mono/mono@bcda0048552 [aot] Emit runtime invoke wrappers for up to 40 parameters for bitcode, newly added tests depend on it. * mono/mono@f0e466618d1 [crash] Add managed exception class name (#11821) * mono/mono@23f2024af80 [2018-08] Fix Encoding serialization issue (#11807) * mono/mono@414cafac931 [interp] Don't include internal frames in stack trace (#11793) * mono/mono@68746a81f28 [ci] Disable log compression in pipeline builds for now - second attempt * mono/mono@1f62222fa64 [mini] use AOT trampolines in interp mixed mode (#11781) * mono/mono@d0184b6970e [ci] Disable log compression in pipeline builds for now * mono/mono@a4c0912ecfb [loader] ignore 'internalcall' impl attribute on 'abstract' methods * mono/mono@7b9d9b3f1ba [arm64] Fix passing r4/r8 arguments on the stack in the gsharedvt trampoline. * mono/mono@e3a4484af76 [2018-08] Add .NET 4.7.2 reference assemblies (#11733) Diff: https://github.com/mono/mono/compare/99b6da79449eb166ee2f7819f054e6776d923fff...f919fb58c4e3f803659e403814110697162750f6 * empty commit (trigger CI) --- external/mono | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/external/mono b/external/mono index 99b6da7944..f919fb58c4 160000 --- a/external/mono +++ b/external/mono @@ -1 +1 @@ -Subproject commit 99b6da79449eb166ee2f7819f054e6776d923fff +Subproject commit f919fb58c4e3f803659e403814110697162750f6 From 366d94d28a2ae53db966b8d0ff2a2b3987ce6ffb Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 10 Dec 2018 15:14:18 +0100 Subject: [PATCH 04/23] [mmp] Show the right error code in error message. (#5245) --- tools/mmp/driver.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/mmp/driver.cs b/tools/mmp/driver.cs index 2c73486fb9..ba8956f348 100644 --- a/tools/mmp/driver.cs +++ b/tools/mmp/driver.cs @@ -815,7 +815,7 @@ namespace Xamarin.Bundler { if (frameworks_copied_to_bundle_dir) { int install_ret = XcodeRun ("install_name_tool", $"{StringUtils.Quote (AppPath)} -add_rpath @loader_path/../Frameworks"); if (install_ret != 0) - throw new MonoMacException (5310, true, "install_name_tool failed with an error code '{0}'. Check build log for details.", ret); + throw new MonoMacException (5310, true, "install_name_tool failed with an error code '{0}'. Check build log for details.", install_ret); } if (dylibs_copied_to_bundle_dir) { int install_ret = XcodeRun ("install_name_tool", $"{StringUtils.Quote (AppPath)} -add_rpath @loader_path/../{BundleName}"); From 4cdb87e5a2ebc33d1355f023860d598a83083717 Mon Sep 17 00:00:00 2001 From: Alex Soto Date: Mon, 10 Dec 2018 13:13:20 -0500 Subject: [PATCH 05/23] [AudioUnit] Adds 'Latency' property [get|set]ter to AudioUnit object (#5221) Fixes xamarin/xamarin-macios#5217 --- src/AudioUnit/AudioUnit.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/src/AudioUnit/AudioUnit.cs b/src/AudioUnit/AudioUnit.cs index 1e0c4335c4..99bb8dcef8 100644 --- a/src/AudioUnit/AudioUnit.cs +++ b/src/AudioUnit/AudioUnit.cs @@ -736,6 +736,25 @@ namespace AudioUnit return MusicDeviceMIDIEvent (handle, status, data1, data2, offsetSampleFrame); } + public AudioUnitStatus SetLatency (double latency) + { + // ElementCount: Float64, AudioUnitScopeType.Global is the only valid scope for Latency. + return AudioUnitSetProperty (handle, AudioUnitPropertyIDType.Latency, AudioUnitScopeType.Global, 0, ref latency, sizeof (double)); + } + + [DllImport (Constants.AudioUnitLibrary)] + static extern AudioUnitStatus AudioUnitGetProperty (IntPtr inUnit, AudioUnitPropertyIDType inID, AudioUnitScopeType inScope, uint inElement, ref double outData, ref uint ioDataSize); + + public double GetLatency () + { + uint size = sizeof (double); + double latency = 0; + var err = AudioUnitGetProperty (handle, AudioUnitPropertyIDType.Latency, AudioUnitScopeType.Global, 0, ref latency, ref size); + if (err != 0) + throw new AudioUnitException ((int) err); + return latency; + } + #region SetRenderCallback public AudioUnitStatus SetRenderCallback (RenderDelegate renderDelegate, AudioUnitScopeType scope = AudioUnitScopeType.Global, uint audioUnitElement = 0) From fb4147d78df9e1ef58b159b12a4e577d5668bf5b Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Date: Mon, 10 Dec 2018 22:59:11 +0100 Subject: [PATCH 06/23] [Foundation] Make sure we use the cookies from the cookie storage. Fixes #5148 (#5244) The response object does not have all the cookie values, instead we must rust the cookie storage which can be used to retrieve ALL the cookies for a task. The header value has to be created manually because the native objects do not expose a valid way to get the header. Tests have been added to ensure we return the same as the managed client. Fixes https://github.com/xamarin/xamarin-macios/issues/5148 --- src/Foundation/NSUrlSessionHandler.cs | 64 +++++++++++++++++++ .../System.Net.Http/MessageHandlers.cs | 42 +++++++++++- 2 files changed, 105 insertions(+), 1 deletion(-) diff --git a/src/Foundation/NSUrlSessionHandler.cs b/src/Foundation/NSUrlSessionHandler.cs index b7e009589b..95f926141d 100644 --- a/src/Foundation/NSUrlSessionHandler.cs +++ b/src/Foundation/NSUrlSessionHandler.cs @@ -27,13 +27,16 @@ using System; using System.Collections.Generic; +using System.Globalization; using System.IO; using System.Linq; using System.Net; using System.Net.Http; +using System.Net.Http.Headers; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; +using System.Text; #if UNIFIED using CoreFoundation; @@ -53,8 +56,62 @@ namespace System.Net.Http { #else namespace Foundation { #endif + + // useful extensions for the class in order to set it in a header + static class NSHttpCookieExtensions + { + static void AppendSegment(StringBuilder builder, string name, string value) + { + if (builder.Length > 0) + builder.Append ("; "); + + builder.Append (name); + if (value != null) + builder.Append ("=").Append (value); + } + + // returns the header for a cookie + public static string GetHeaderValue (this NSHttpCookie cookie) + { + var header = new StringBuilder(); + AppendSegment (header, cookie.Name, cookie.Value); + AppendSegment (header, NSHttpCookie.KeyPath.ToString (), cookie.Path.ToString ()); + AppendSegment (header, NSHttpCookie.KeyDomain.ToString (), cookie.Domain.ToString ()); + AppendSegment (header, NSHttpCookie.KeyVersion.ToString (), cookie.Version.ToString ()); + + if (cookie.Comment != null) + AppendSegment (header, NSHttpCookie.KeyComment.ToString (), cookie.Comment.ToString()); + + if (cookie.CommentUrl != null) + AppendSegment (header, NSHttpCookie.KeyCommentUrl.ToString (), cookie.CommentUrl.ToString()); + + if (cookie.Properties.ContainsKey (NSHttpCookie.KeyDiscard)) + AppendSegment (header, NSHttpCookie.KeyDiscard.ToString (), null); + + if (cookie.ExpiresDate != null) { + // Format according to RFC1123; 'r' uses invariant info (DateTimeFormatInfo.InvariantInfo) + var dateStr = ((DateTime) cookie.ExpiresDate).ToUniversalTime ().ToString("r", CultureInfo.InvariantCulture); + AppendSegment (header, NSHttpCookie.KeyExpires.ToString (), dateStr); + } + + if (cookie.Properties.ContainsKey (NSHttpCookie.KeyMaximumAge)) { + var timeStampString = (NSString) cookie.Properties[NSHttpCookie.KeyMaximumAge]; + AppendSegment (header, NSHttpCookie.KeyMaximumAge.ToString (), timeStampString); + } + + if (cookie.IsSecure) + AppendSegment (header, NSHttpCookie.KeySecure.ToString(), null); + + if (cookie.IsHttpOnly) + AppendSegment (header, "httponly", null); // Apple does not show the key for the httponly + + return header.ToString (); + } + } + public partial class NSUrlSessionHandler : HttpMessageHandler { + private const string SetCookie = "Set-Cookie"; readonly Dictionary headerSeparators = new Dictionary { ["User-Agent"] = " ", ["Server"] = " " @@ -265,11 +322,18 @@ namespace Foundation { foreach (var v in urlResponse.AllHeaderFields) { // NB: Cocoa trolling us so hard by giving us back dummy dictionary entries if (v.Key == null || v.Value == null) continue; + // NSUrlSession tries to be smart with cookies, we will not use the raw value but the ones provided by the cookie storage + if (v.Key.ToString () == SetCookie) continue; httpResponse.Headers.TryAddWithoutValidation (v.Key.ToString (), v.Value.ToString ()); httpResponse.Content.Headers.TryAddWithoutValidation (v.Key.ToString (), v.Value.ToString ()); } + var cookies = session.Configuration.HttpCookieStorage.CookiesForUrl (response.Url); + for (var index = 0; index < cookies.Length; index++) { + httpResponse.Headers.TryAddWithoutValidation (SetCookie, cookies [index].GetHeaderValue ()); + } + inflight.Response = httpResponse; // We don't want to send the response back to the task just yet. Because we want to mimic .NET behavior diff --git a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs index cbeb348189..fd94a66b53 100644 --- a/tests/monotouch-test/System.Net.Http/MessageHandlers.cs +++ b/tests/monotouch-test/System.Net.Http/MessageHandlers.cs @@ -71,4 +71,44 @@ namespace MonoTests.System.Net.Http // The handlers throw different types of exceptions, so we can't assert much more than that something went wrong. } - }} +#if !__WATCHOS__ + // ensure that we do get the same number of cookies as the managed handler + [TestCase] + public void TestNSUrlSessionHandlerCookies () + { + bool areEqual = false; + var manageCount = 0; + var nativeCount = 0; + Exception ex = null; + + TestRuntime.RunAsync (DateTime.Now.AddSeconds (30), async () => + { + try { + var managedClient = new HttpClient (new HttpClientHandler ()); + var managedResponse = await managedClient.GetAsync ("https://google.com"); + if (managedResponse.Headers.TryGetValues ("Set-Cookie", out var managedCookies)) { + var nativeClient = new HttpClient (new NSUrlSessionHandler ()); + var nativeResponse = await nativeClient.GetAsync ("https://google.com"); + if (managedResponse.Headers.TryGetValues ("Set-Cookie", out var nativeCookies)) { + manageCount = managedCookies.Count (); + nativeCount = nativeCookies.Count (); + areEqual = manageCount == nativeCount; + } else { + manageCount = -1; + nativeCount = -1; + areEqual = false; + } + } + + } catch (Exception e) { + ex = e; + } + }, () => areEqual); + + Assert.IsTrue (areEqual, $"Cookies are different - Managed {manageCount} vs Native {nativeCount}"); + Assert.IsNull (ex, "Exception"); + } +#endif + + } +} From 0803f0917a8fe29cb4fc01c19d93eb9202782cae Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 11 Dec 2018 07:48:05 +0100 Subject: [PATCH 07/23] [builds] Download & extract the mono sdk package. (#5247) We don't consume it yet, that will come in separate pull requests as the necessary bits are included in the package. --- Make.config | 14 ++++++++++++++ builds/.gitignore | 1 + builds/Makefile | 26 ++++++++++++++++++++++++++ configure | 6 ++++++ 4 files changed, 47 insertions(+) diff --git a/Make.config b/Make.config index 52e1d636bc..aba0452797 100644 --- a/Make.config +++ b/Make.config @@ -326,5 +326,19 @@ JENKINS_RESULTS_DIRECTORY ?= $(abspath $(TOP)/jenkins-results) # Clone files instead of copying them on APFS file systems. Much faster. CP:=$(shell df -t apfs / >/dev/null 2>&1 && echo "cp -c" || echo "cp") +# Setup various variables depending on whether mono is downloaded or built from source +ifeq ($(MONO_BUILD_FROM_SOURCE),) +MONO_HASH:=$(shell git --git-dir=$(abspath $(TOP)/.git) --work-tree=$(abspath $(TOP)) ls-tree HEAD --full-tree -- external/mono | awk -F' ' '{printf "%s",$$3}') +MONO_FILENAME:=ios-release-Darwin-$(MONO_HASH).zip +MONO_URL:=https://xamjenkinsartifact.azureedge.net/mono-sdks/$(MONO_FILENAME) +MONO_SDK_BUILDDIR:=$(abspath builds/downloads/$(basename $(MONO_FILENAME))) +MONO_SDK_DESTDIR:=$(abspath builds/downloads/$(basename $(MONO_FILENAME))) +MONO_BUILD_MODE=download +else +MONO_SDK_BUILDDIR:=$(abspath $(MONO_PATH)/sdks/builds) +MONO_SDK_DESTDIR:=$(abspath $(MONO_PATH)/sdks/out) +MONO_BUILD_MODE=compile +endif + .SUFFIXES: MAKEFLAGS += --no-builtin-rules diff --git a/builds/.gitignore b/builds/.gitignore index 132447baeb..b3557803f7 100644 --- a/builds/.gitignore +++ b/builds/.gitignore @@ -1,3 +1,4 @@ +downloads .stamp* .deps.*.mk *.config.cache diff --git a/builds/Makefile b/builds/Makefile index c9f7e964d0..1b583ca20e 100644 --- a/builds/Makefile +++ b/builds/Makefile @@ -3,6 +3,32 @@ include $(TOP)/Make.config PREFIX=$(abspath $(IOS_DESTDIR)/$(MONOTOUCH_PREFIX)/) +download: downloads/$(basename $(MONO_FILENAME)) + +downloads/$(MONO_FILENAME): + $(Q) mkdir -p downloads + $(Q) echo "Downloading $(MONO_URL)..." + $(Q) curl -s -f -L $(MONO_URL) --output $@.tmp + $(Q) mv $@.tmp $@ + $(Q) echo "Downloaded $(MONO_URL)" + +downloads/$(basename $(MONO_FILENAME)): downloads/$(MONO_FILENAME) + $(Q) echo "Unzipping $(MONO_FILENAME)..." + $(Q) rm -Rf $@.tmp + $(Q) unzip -q -d $@.tmp $< + $(Q) mv $@.tmp $@ + $(Q) echo "Unzipped $(MONO_FILENAME)" + +clean-locals:: + $(Q) rm -Rf downloads + +.stamp-download-%: downloads/$(basename $(MONO_FILENAME)) + $(Q) touch $@ + +ifeq ($(MONO_BUILD_FROM_SOURCE),) +all-local:: download +endif + IPHONESIMULATOR_SDK=$(MONOTOUCH_PREFIX)/SDKs/MonoTouch.iphonesimulator.sdk IPHONESIMULATOR_PREFIX=$(MONOTOUCH_PREFIX)/SDKs/MonoTouch.iphonesimulator.sdk/usr IPHONEOS_SDK=$(MONOTOUCH_PREFIX)/SDKs/MonoTouch.iphoneos.sdk diff --git a/configure b/configure index 6112262563..569da5404b 100755 --- a/configure +++ b/configure @@ -26,6 +26,8 @@ Usage: configure [options] --enable-xamarin Enable additional Xamarin-specific parts of the build. --disable-packaged-llvm Compile LLVM instead of downloading a precompiled version. + + --disable-packaged-mono Compile Mono from source instead of downloading a precompiled version. EOL } @@ -88,6 +90,10 @@ while test x$1 != x; do echo "DISABLE_DOWNLOAD_LLVM=1" >> $CONFIGURED_FILE shift ;; + --disable-packaged-mono) + echo "MONO_BUILD_FROM_SOURCE=1" >> "$CONFIGURED_FILE" + shift + ;; --help|-h) show_help exit 0 From 49cd1923de8b4c2a0212e56013a77df8724555a2 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 11 Dec 2018 09:00:35 +0100 Subject: [PATCH 08/23] [CI] Add scripts to set github status from Azure DevOps. (#5246) --- jenkins/add-commit-comment.sh | 100 ++++++++++++++++ jenkins/add-commit-status.sh | 146 ++++++++++++++++++++++++ jenkins/vsts-device-tests-set-status.sh | 80 +++++++++++++ 3 files changed, 326 insertions(+) create mode 100755 jenkins/add-commit-comment.sh create mode 100755 jenkins/add-commit-status.sh create mode 100755 jenkins/vsts-device-tests-set-status.sh diff --git a/jenkins/add-commit-comment.sh b/jenkins/add-commit-comment.sh new file mode 100755 index 0000000000..e791cdcac5 --- /dev/null +++ b/jenkins/add-commit-comment.sh @@ -0,0 +1,100 @@ +#!/bin/bash -eu + +# Script to add a comment to a commit on GitHub. +# +# Arguments (all required): +# --token=: The GitHub Personal Access Token used to authenticate with GitHub. +# --file=: The file to add as the comment. +# --hash=: The hash to add the comment to. +# + +TOKEN= +FILE= +HASH= +VERBOSE= + +while ! test -z "${1:-}"; do + case "$1" in + --token=*) + TOKEN="${1:8}" + shift + ;; + --token) + TOKEN="$2" + shift 2 + ;; + --file=*) + FILE="${1:7}" + shift + ;; + --file) + FILE="$2" + shift 2 + ;; + --hash=*) + HASH="${1:7}" + shift + ;; + --hash) + HASH="$2" + shift 2 + ;; + -v | --verbose) + VERBOSE=1 + shift + ;; + *) + echo "Unknown argument: $1" + exit 1 + ;; + esac +done + +if test -z "$TOKEN"; then + echo "The GitHub token is required (--token=)" + exit 1 +fi + +if test -z "$FILE"; then + echo "The file to add as a comment is required (--file=)" + exit 1 +elif ! test -f "$FILE"; then + echo "The file $FILE does not exist" + exit 1 +fi + + +if test -z "$HASH"; then + echo "The commit hash is required (--hash=)" + exit 1 +fi + +JSONFILE=$(mktemp) +LOGFILE=$(mktemp) +cleanup () +{ + rm -f "$JSONFILE" "$LOGFILE" +} +trap cleanup ERR +trap cleanup EXIT + +printf '{\n"body": ' > "$JSONFILE" +python -c 'import json,sys; print(json.dumps(sys.stdin.read()))' < "$FILE" >> "$JSONFILE" +printf '}\n' >> "$JSONFILE" + +if test -n "$VERBOSE"; then + echo "JSON file:" + sed 's/^/ /' "$JSONFILE"; +fi + +if ! curl -f -v -H "Authorization: token $TOKEN" -H "User-Agent: command line tool" -d "@$JSONFILE" "https://api.github.com/repos/xamarin/xamarin-macios/commits/$HASH/comments" > "$LOGFILE" 2>&1; then + echo "Failed to add commit message." + echo "curl output:" + sed 's/^/ /' "$LOGFILE" + echo "Json body:" + sed 's/^/ /' "$JSONFILE" + exit 1 +else + if test -n "$VERBOSE"; then sed 's/^/ /' "$LOGFILE"; fi + echo "Successfully added commit message to https://github.com/xamarin/xamarin-macios/commit/$HASH" +fi diff --git a/jenkins/add-commit-status.sh b/jenkins/add-commit-status.sh new file mode 100755 index 0000000000..a5291b7198 --- /dev/null +++ b/jenkins/add-commit-status.sh @@ -0,0 +1,146 @@ +#!/bin/bash -eu + +# Script to add a status to a commit on GitHub. +# +# Arguments (all required): +# --token=: The GitHub Personal Access Token used to authenticate with GitHub. +# --hash=: The hash to add the comment to. +# --state=: The status state. +# --target-url=: The status url. +# --description=: The status description. +# --context=: The status context. +# + +TOKEN= +HASH= +STATE= +TARGET_URL= +DESCRIPTION= +CONTEXT= +VERBOSE= + +while ! test -z "${1:-}"; do + case "$1" in + --token=*) + TOKEN="${1:8}" + shift + ;; + --token) + TOKEN="$2" + shift 2 + ;; + --hash=*) + HASH="${1:7}" + shift + ;; + --hash) + HASH="$2" + shift 2 + ;; + --state=*) + STATE="${1:8}" + shift + ;; + --state) + STATE="$2" + shift 2 + ;; + --target-url=*) + TARGET_URL="${1:13}" + shift + ;; + --target-url) + TARGET_URL="$2" + shift 2 + ;; + --description=*) + DESCRIPTION="${1:14}" + shift + ;; + --description) + DESCRIPTION="$2" + shift 2 + ;; + --context=*) + CONTEXT="${1:10}" + shift + ;; + --context) + CONTEXT="$2" + shift 2 + ;; + -v | --verbose) + VERBOSE=1 + shift + ;; + *) + echo "Unknown argument: $1" + exit 1 + ;; + esac +done + +if test -z "$TOKEN"; then + echo "The GitHub token is required (--token=)" + exit 1 +fi + +if test -z "$HASH"; then + echo "The commit hash is required (--hash=)" + exit 1 +fi + +if test -z "$STATE"; then + echo "The state of the status is required (--state=)" + exit 1 +fi + +if test -z "$TARGET_URL"; then + echo "The target url of the status is required (--target-url=)" + exit 1 +fi + +if test -z "$DESCRIPTION"; then + echo "The description of the status is required (--description=)" + exit 1 +fi + +if test -z "$CONTEXT"; then + echo "The context of the status is required (--context=)" + exit 1 +fi + +JSONFILE=$(mktemp) +LOGFILE=$(mktemp) +cleanup () +{ + rm -f "$JSONFILE" "$LOGFILE" +} +trap cleanup ERR +trap cleanup EXIT + +( + printf '{\n' + printf "\t\"state\": \"%s\",\n" "$STATE" + printf "\t\"target_url\": \"%s\",\n" "$TARGET_URL" + printf "\t\"description\": %s,\n" "$(echo -n "$DESCRIPTION" | python -c 'import json,sys; print(json.dumps(sys.stdin.read()))')" + printf "\t\"context\": \"%s\"\n" "$CONTEXT" + printf "}\n" +) > "$JSONFILE" + +if test -n "$VERBOSE"; then + echo "JSON file:" + sed 's/^/ /' "$JSONFILE"; +fi + +if ! curl -f -v -H "Authorization: token $TOKEN" -H "User-Agent: command line tool" -d "@$JSONFILE" "https://api.github.com/repos/xamarin/xamarin-macios/statuses/$HASH" > "$LOGFILE" 2>&1; then + echo "Failed to add status." + echo "curl output:" + sed 's/^/ /' "$LOGFILE" + echo "Json body:" + sed 's/^/ /' "$JSONFILE" + exit 1 +else + if test -n "$VERBOSE"; then sed 's/^/ /' "$LOGFILE"; fi + echo "Successfully added status to https://github.com/xamarin/xamarin-macios/commit/$HASH" +fi diff --git a/jenkins/vsts-device-tests-set-status.sh b/jenkins/vsts-device-tests-set-status.sh new file mode 100755 index 0000000000..03eff788a7 --- /dev/null +++ b/jenkins/vsts-device-tests-set-status.sh @@ -0,0 +1,80 @@ +#!/bin/bash -eux + +cd "$(dirname "${BASH_SOURCE[0]}")/.." + +TOKEN= +START= +while ! test -z "$1"; do + case "$1" in + --token=*) + TOKEN="${1:8}" + shift + ;; + --token) + TOKEN="$2" + shift 2 + ;; + --start) + START=1 + shift + ;; + *) + echo "Unknown argument: $1" + exit 1 + ;; + esac +done + +if test -z "$TOKEN"; then + echo "The GitHub token is required (--token=)" + exit 1 +fi + +P=$(cat tmp.p) + +VSTS_BUILD_URL="${SYSTEM_TEAMFOUNDATIONCOLLECTIONURI}${SYSTEM_TEAMPROJECT}/_build/index?buildId=${BUILD_BUILDID}" + +# Add a GitHub status to the commit we're testing +GH_STATE=failure +DESCRIPTION="Running device tests" +RESULT_EMOJII= +if test -n "$START"; then + GH_STATE=pending + DESCRIPTION="Running device tests" +else + case "$(echo "$AGENT_JOBSTATUS" | tr '[:upper:]' '[:lower:]')" in + succeeded) + GH_STATE=success + DESCRIPTION="Device tests passed" + RESULT_EMOJII="✅ " + ;; + failed | canceled | succeededwithissues | *) + GH_STATE=error + DESCRIPTION="Device tests completed ($AGENT_JOBSTATUS)" + RESULT_EMOJII="🔥 " + ;; + esac +fi +./jenkins/add-commit-status.sh --token="$TOKEN" --hash="$BUILD_REVISION" --state="$GH_STATE" --target-url="$VSTS_BUILD_URL" --description="$DESCRIPTION" --context="VSTS: device tests" + +if test -z "$START"; then + # When we're done, add a GitHub comment to the commit we're testing + MESSAGE_FILE=commit-message.txt + cleanup () + { + rm -f "$MESSAGE_FILE" + } + trap cleanup ERR + trap cleanup EXIT + + printf "%s%s on [Azure DevOps](%s): [Html Report](http://xamarin-storage/%s/jenkins-results/tests/index.html) %s\\n\\n" "$RESULT_EMOJII" "$DESCRIPTION" "$VSTS_BUILD_URL" "$P" "$RESULT_EMOJII" > "$MESSAGE_FILE" + + FILE=$PWD/tests/TestSummary.md + if ! test -f "$FILE"; then + printf "🔥 Tests failed catastrophically (no summary found)\\n" >> "$MESSAGE_FILE" + else + cat "$FILE" >> "$MESSAGE_FILE" + fi + + ./jenkins/add-commit-comment.sh --token="$TOKEN" --file="$MESSAGE_FILE" "--hash=$BUILD_REVISION" +fi From 4d31505bf91ca33e4f611ac324105909d97d1fc1 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Tue, 11 Dec 2018 09:35:16 +0000 Subject: [PATCH 09/23] Remove unnecessary references to Mono.Security. (#5242) --- src/Makefile | 4 ---- src/ObjCRuntime/Runtime.cs | 6 ------ src/ObjCRuntime/RuntimeOptions.cs | 6 ------ src/xammac.tmpl.csproj | 1 - 4 files changed, 17 deletions(-) diff --git a/src/Makefile b/src/Makefile index 7856bd6647..86e650b9ea 100644 --- a/src/Makefile +++ b/src/Makefile @@ -91,7 +91,6 @@ $(IOS_BUILD_DIR)/AssemblyInfo.cs: $(TOP)/src/AssemblyInfo.cs.in $(IOS_BUILD_DIR)/native/core.dll: $(IOS_CORE_SOURCES) frameworks.sources $(Q) mkdir -p $(IOS_BUILD_DIR)native $(call Q_PROF_CSC,ios) $(IOS_CSC) -nologo -out:$@ -target:library -debug -unsafe \ - -r:$(IOS_LIBDIR)/Mono.Security.dll \ -nowarn:219,618,114,414,1635,3021,$(IOS_WARNINGS_THAT_YOU_SHOULD_FIX) \ -define:COREBUILD $(IOS_DEFINES) \ $(IOS_native_DEFINES) \ @@ -126,7 +125,6 @@ $(IOS_BUILD_DIR)/native-$(1)%Xamarin.iOS.dll $(IOS_BUILD_DIR)/native-$(1)%Xamari @mkdir -p $(IOS_BUILD_DIR)/native-$(1) $$(call Q_PROF_CSC,ios/$(1) bit) $$(IOS_CSC) -nologo -out:$$@ -target:library -debug -unsafe -optimize \ -deterministic \ - -r:$(IOS_LIBDIR)/Mono.Security.dll \ $$(ARGS_$(1)) \ -publicsign -keyfile:$(PRODUCT_KEY_PATH) $$(IOS_DEFINES) \ $$(IOS_native_DEFINES) \ @@ -480,7 +478,6 @@ $(MAC_BUILD_DIR)/$(1)/$(2): $(MAC_BUILD_DIR)/$(3)/generated-sources $(MAC_SOURCE $$(MAC_$(3)_CSC) -nologo -out:$$@ -target:library -debug -unsafe \ -deterministic \ $$(MAC_COMMON_DEFINES),OBJECT_REF_TRACKING \ - -r:Mono.Security.dll \ $$(MAC_$(3)_ARGS) \ $$(ARGS_$(6)) \ -publicsign -keyfile:$(SN_KEY) \ @@ -955,7 +952,6 @@ $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVOS%dll $(TVOS_BUILD_DIR)/tvos-64/Xamarin.TVO $(call Q_PROF_CSC,tvos) $(TV_CSC) -nologo -out:$(basename $@).dll -target:library -debug -unsafe -optimize \ -publicsign -keyfile:$(PRODUCT_KEY_PATH) $(TVOS_DEFINES) \ -deterministic \ - -r:$(TVOS_LIBDIR)/Mono.Security.dll \ $(ARGS_64) \ -nowarn:219,618,114,414,1635,3021,$(IOS_WARNINGS_THAT_YOU_SHOULD_FIX) \ $(TVOS_SOURCES) @$(TVOS_BUILD_DIR)/tvos/generated_sources diff --git a/src/ObjCRuntime/Runtime.cs b/src/ObjCRuntime/Runtime.cs index 9001aee2db..beb608dfdd 100644 --- a/src/ObjCRuntime/Runtime.cs +++ b/src/ObjCRuntime/Runtime.cs @@ -22,12 +22,6 @@ using Registrar; using AppKit; #endif -#if !COREBUILD && (XAMARIN_APPLETLS || XAMARIN_NO_TLS) -#if !MMP && !MTOUCH && !MTOUCH_TEST -using Mono.Security.Interface; -#endif -#endif - namespace ObjCRuntime { public partial class Runtime { diff --git a/src/ObjCRuntime/RuntimeOptions.cs b/src/ObjCRuntime/RuntimeOptions.cs index 2e4597a4f0..ff13794d1b 100644 --- a/src/ObjCRuntime/RuntimeOptions.cs +++ b/src/ObjCRuntime/RuntimeOptions.cs @@ -20,12 +20,6 @@ using MonoTouch.Foundation; using MonoTouch.ObjCRuntime; #endif -#if !COREBUILD && (XAMARIN_APPLETLS || XAMARIN_NO_TLS) -#if !MTOUCH && !MMP && !MMP_TEST -using Mono.Security.Interface; -#endif -#endif - #if MMP || MMP_TEST || MTOUCH namespace Xamarin.Bundler { #elif SYSTEM_NET_HTTP diff --git a/src/xammac.tmpl.csproj b/src/xammac.tmpl.csproj index 6afeeffa82..3818b52f1e 100644 --- a/src/xammac.tmpl.csproj +++ b/src/xammac.tmpl.csproj @@ -40,7 +40,6 @@ - From c00e9af445d8fb15df40b62cb4df765d3d17cf05 Mon Sep 17 00:00:00 2001 From: Chris Hamons Date: Tue, 11 Dec 2018 10:28:55 -0500 Subject: [PATCH 10/23] [mmp] Add rpath during compile and not after via install_name_tool (#5251) - https://github.com/xamarin/xamarin-macios/issues/5243 - https://github.com/xamarin/xamarin-macios/issues/5248 - There were multiple issues where we'd run out of space and install_name_tool would randomly fail. We can easily move these two to during initial clang and avoid those cases. --- tools/mmp/driver.cs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/tools/mmp/driver.cs b/tools/mmp/driver.cs index ba8956f348..8bbc02f63b 100644 --- a/tools/mmp/driver.cs +++ b/tools/mmp/driver.cs @@ -812,16 +812,6 @@ namespace Xamarin.Bundler { // if not then the compilation really failed throw new MonoMacException (5103, true, String.Format ("Failed to compile. Error code - {0}. Please file a bug report at https://github.com/xamarin/xamarin-macios/issues/new", ret)); } - if (frameworks_copied_to_bundle_dir) { - int install_ret = XcodeRun ("install_name_tool", $"{StringUtils.Quote (AppPath)} -add_rpath @loader_path/../Frameworks"); - if (install_ret != 0) - throw new MonoMacException (5310, true, "install_name_tool failed with an error code '{0}'. Check build log for details.", install_ret); - } - if (dylibs_copied_to_bundle_dir) { - int install_ret = XcodeRun ("install_name_tool", $"{StringUtils.Quote (AppPath)} -add_rpath @loader_path/../{BundleName}"); - if (install_ret != 0) - throw new MonoMacException (5310, true, "install_name_tool failed with an error code '{0}'. Check build log for details.", ret); - } if (generate_plist) GeneratePList (); @@ -1229,6 +1219,11 @@ namespace Xamarin.Bundler { args.Append (StringUtils.Quote (finalLibPath)).Append (' '); } + if (frameworks_copied_to_bundle_dir) + args.Append ("-rpath @loader_path/../Frameworks "); + if (dylibs_copied_to_bundle_dir) + args.Append ($"-rpath @loader_path/../{BundleName} "); + if (is_extension) args.Append ("-e _xamarin_mac_extension_main -framework NotificationCenter").Append(' '); From 07b040087e197704bdb049f1826440bc922d2058 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Tue, 11 Dec 2018 17:50:20 +0100 Subject: [PATCH 11/23] [MachO] Add support for ARM64e and ARM64_32. (#5253) Also remove some duplicated code. --- tools/common/MachO.cs | 51 +++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/tools/common/MachO.cs b/tools/common/MachO.cs index 6c8f7d4f08..95f2a4c1ae 100644 --- a/tools/common/MachO.cs +++ b/tools/common/MachO.cs @@ -23,11 +23,13 @@ namespace Xamarin Thumb = 64, LLVM = 128, ARMv7k = 256, + ARM64e = 512, + ARM64_32 = 1024, SimulatorArchMask = i386 | x86_64, - DeviceArchMask = ARMv6 | ARMv7 | ARMv7s | ARMv7k | ARM64, + DeviceArchMask = ARMv6 | ARMv7 | ARMv7s | ARMv7k | ARM64 | ARM64e | ARM64_32, ArchMask = SimulatorArchMask | DeviceArchMask, - Arch64Mask = x86_64 | ARM64, - Arch32Mask = i386 | ARMv6 | ARMv7 | ARMv7s | ARMv7k, + Arch64Mask = x86_64 | ARM64 | ARM64e, + Arch32Mask = i386 | ARMv6 | ARMv7 | ARMv7s | ARMv7k | ARM64_32 /* This is a 32-bit arch for our purposes */, } public class MachO @@ -47,6 +49,7 @@ namespace Xamarin internal const uint MH_DYLIB = 0x6; /* dynamically bound shared library */ + // Values here match the corresponding values in the Abi enum. public enum Architectures { None = 0, i386 = 1, @@ -55,6 +58,9 @@ namespace Xamarin ARMv7s = 8, ARM64 = 16, x86_64 = 32, + ARMv7k = 256, + ARM64e = 512, + ARM64_32 = 1024, } internal enum LoadCommands : uint @@ -382,7 +388,7 @@ namespace Xamarin return rv; } - static Abi GetArch (int cputype, int cpusubtype) + public static Abi GetArch (int cputype, int cpusubtype) { switch (cputype) { case 12: // arm @@ -399,7 +405,20 @@ namespace Xamarin return Abi.None; } case 12 | 0x01000000: - return Abi.ARM64; + switch (cpusubtype) { + case 2: + return Abi.ARM64e; + case 0: + default: + return Abi.ARM64; + } + case 12 | 0x02000000: // CPU_TYPE_ARM | CPU_ARCH_ABI64_32 (64-bit hardware with 32-bit types; LP32) + switch (cpusubtype) { + case 1: // CPU_SUBTYPE_ARM64_32_V8 + return Abi.ARM64_32; + default: + return Abi.None; + } case 7: // x86 return Abi.i386; case 7 | 0x01000000: // x64 @@ -635,27 +654,7 @@ namespace Xamarin public MachO.Architectures Architecture { get { - switch (cputype) { - case 12: // arm - switch (cpusubtype) { - case 6: - return MachO.Architectures.ARMv6; - case 9: - return MachO.Architectures.ARMv7; - case 11: - return MachO.Architectures.ARMv7s; - default: - return MachO.Architectures.None; - } - case 12 | 0x01000000: - return MachO.Architectures.ARM64; - case 7: // x86 - return MachO.Architectures.i386; - case 7 | 0x01000000: // x64 - return MachO.Architectures.x86_64; - } - - return MachO.Architectures.None; + return (MachO.Architectures) MachO.GetArch (cputype, cpusubtype); } } From 4061adc2a413f1034291da926c1ffd407d8d181e Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Tue, 11 Dec 2018 11:51:05 -0500 Subject: [PATCH 12/23] [interp] fix mixed mode in Release configuration (#5230) * [mtouch] do not strip assemblies when interpreter is used * [xharness] add release mixed-mode configuration * [xharness] enable debug mixed-mode config for mscorlib * [mtouch] add link to mono issue --- tests/xharness/Jenkins.cs | 5 ++++- tools/mtouch/Application.cs | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/tests/xharness/Jenkins.cs b/tests/xharness/Jenkins.cs index 3069cd0cf3..04cedfbc2d 100644 --- a/tests/xharness/Jenkins.cs +++ b/tests/xharness/Jenkins.cs @@ -197,14 +197,17 @@ namespace xharness yield return new TestData { Variation = "Debug (all optimizations)", MTouchExtraArgs = "--registrar:static --optimize:all", Debug = true, Profiling = false, Defines = "OPTIMIZEALL" }; yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, }; yield return new TestData { Variation = "Debug (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = true, Profiling = false, }; + yield return new TestData { Variation = "Release (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = false, Profiling = false, }; break; case "mscorlib": yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, Undefines = "FULL_AOT_RUNTIME" }; - yield return new TestData { Variation = "Debug (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = true, Profiling = false, Ignored = true, Undefines = "FULL_AOT_RUNTIME" }; + yield return new TestData { Variation = "Debug (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = true, Profiling = false, Undefines = "FULL_AOT_RUNTIME" }; + yield return new TestData { Variation = "Release (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = false, Profiling = false, Undefines = "FULL_AOT_RUNTIME" }; break; case "mini": yield return new TestData { Variation = "Debug (interpreter)", MTouchExtraArgs = "--interpreter", Debug = true, Profiling = false, Undefines = "FULL_AOT_RUNTIME" }; yield return new TestData { Variation = "Debug (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = true, Profiling = false, Undefines = "FULL_AOT_RUNTIME" }; + yield return new TestData { Variation = "Release (interpreter -mscorlib)", MTouchExtraArgs = "--interpreter=-mscorlib", Debug = false , Profiling = false, Undefines = "FULL_AOT_RUNTIME" }; break; } break; diff --git a/tools/mtouch/Application.cs b/tools/mtouch/Application.cs index bc1d8f4d1b..89a0e73677 100644 --- a/tools/mtouch/Application.cs +++ b/tools/mtouch/Application.cs @@ -2175,7 +2175,14 @@ namespace Xamarin.Bundler { return false; if (PackageManagedDebugSymbols) return false; - if (IsInterpreted (Assembly.GetIdentity (path))) + /* FIXME: should be `if (IsInterpreted (Assembly.GetIdentity (path)))`. + * The problem is that in mixed mode we can't do the transition + * between "interp"->"aot'd methods using gsharedvt", so we + * fall back to the interp and thus need the IL not to be + * stripped out. Once Mono supports this, we can add back the + * more precise check. + * See https://github.com/mono/mono/issues/11942 */ + if (UseInterpreter) return false; return true; }); From 6688b82ac5ba533f678351545fe418eddff80a19 Mon Sep 17 00:00:00 2001 From: Matt Sylvia Date: Tue, 11 Dec 2018 12:03:45 -0500 Subject: [PATCH 13/23] Post branch version number bump Bumping the version number after branching d16-0 --- Make.versions | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Make.versions b/Make.versions index 2146391bda..c7e73328f8 100644 --- a/Make.versions +++ b/Make.versions @@ -43,5 +43,5 @@ # line changed in git). # -IOS_PACKAGE_VERSION=12.5.1.$(IOS_COMMIT_DISTANCE) -MAC_PACKAGE_VERSION=5.5.1.$(MAC_COMMIT_DISTANCE) +IOS_PACKAGE_VERSION=12.6.0.$(IOS_COMMIT_DISTANCE) +MAC_PACKAGE_VERSION=5.6.0.$(MAC_COMMIT_DISTANCE) From ffae762db26fc719442d52547f2d735d1db3088b Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Date: Wed, 12 Dec 2018 10:38:48 +0100 Subject: [PATCH 14/23] [XHarness] Add support for xunit and nunit tests on Mac OS X. (#5182) This change adds support to execute the tests provided by mono as assemblies.This includes: 1. App generation to run the bcl tests on modern and full. 2. Needed workaround to delay the compilation of the assemblies until we have them from the SDK. 3. All failing tests are ignored. --- tests/Makefile | 2 + .../bcl-test/BCLTests/BCLTests-mac.csproj.in | 200 ++++++++++++ tests/bcl-test/BCLTests/Info-mac.plist.in | 20 ++ .../templates/common/ApplicationOptions.cs | 4 + .../common/TestRunner.Core/LogWriter.cs | 8 +- .../common/TestRunner.Core/TcpTextWriter.cs | 2 + .../TestRunner.xUnit/XUnitTestRunner.cs | 3 + .../templates/iOSApp/ViewController.cs | 4 +- .../BCLTests/templates/macOS/Assert.cs | 188 +++++++++++ .../BCLTests/templates/macOS/MacTestMain.cs | 68 ++++ .../BCLTestImportTargetFactory.cs | 37 ++- tests/xharness/Harness.cs | 6 +- tests/xharness/Jenkins.cs | 1 + tests/xharness/MakefileGenerator.cs | 2 + tests/xharness/ProjectFileExtensions.cs | 2 +- .../BCLTestImporter/ApplicationOptions.cs | 5 +- .../BCLTestAssemblyDefinition.cs | 3 +- .../TestAssemblyDefinitionTest.cs | 2 +- .../BCLTestProjectDefinitionWorkaround.cs | 308 +++++++++++++++++- .../BCLTestProjectGenerator.cs | 224 +++++++++++-- .../BCLTestImporter/Platform.cs | 3 +- .../BCLTestImporter/Program.cs | 8 +- .../BCLTestImporter/RegisterTypeGenerator.cs | 57 +++- 23 files changed, 1115 insertions(+), 42 deletions(-) create mode 100644 tests/bcl-test/BCLTests/BCLTests-mac.csproj.in create mode 100644 tests/bcl-test/BCLTests/Info-mac.plist.in create mode 100644 tests/bcl-test/BCLTests/templates/macOS/Assert.cs create mode 100644 tests/bcl-test/BCLTests/templates/macOS/MacTestMain.cs diff --git a/tests/Makefile b/tests/Makefile index 947881940e..cf77be3d36 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -196,6 +196,8 @@ $(TOP)/tools/mtouch/SdkVersions.cs: $(TOP)/tools/common/SdkVersions.cs.in .stamp-build-mono-unit-tests: $(TOP)/.git/modules/external/mono/HEAD make -j8 -C $(TOP)/external/mono/mcs/class -i do-test PROFILE=MONOTOUCH # TODO: This should not be needed and we should get the dlls from the SDK. make -j8 -C $(TOP)/external/mono/mcs/class -i do-xunit-test PROFILE=MONOTOUCH # TODO: This should not be needed and we should get the dlls from the SDK. + make -j8 -C $(TOP)/external/mono/mcs/class -i do-test PROFILE=xammac_net_4_5 # TODO: This should not be needed and we should get the dlls from the SDK. + make -j8 -C $(TOP)/external/mono/mcs/class -i do-xunit-test PROFILE=xammac_net_4_5 # TODO: This should not be needed and we should get the dlls from the SDK. nuget restore bcl-test/BCLTests/BCLTests.csproj $(Q) touch $@ diff --git a/tests/bcl-test/BCLTests/BCLTests-mac.csproj.in b/tests/bcl-test/BCLTests/BCLTests-mac.csproj.in new file mode 100644 index 0000000000..55e151b5cf --- /dev/null +++ b/tests/bcl-test/BCLTests/BCLTests-mac.csproj.in @@ -0,0 +1,200 @@ + + + + Debug + AnyCPU + {EEE20F63-4282-450A-8584-93F640929D13} + {A3F8F2AB-B479-4A4A-A458-A89E7DC349F1};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Exe + %NAME% + Resources + %NAME% + 67,168,169,219,414,612,618,649,672 + %TARGET FRAMEWORK VERSION% + %TARGET EXTRA INFO% + %DEFINE CONSTANTS% + + + true + full + false + bin\AnyCPU\%NAME%\Debug + DEBUG;MONOMAC;NO_GUI_TESTING;$(DefineConstants) + prompt + 4 + false + false + Mac Developer + false + false + None + x86_64 + cjk,mideast,other,rare,west + + + full + true + bin\AnyCPU\%NAME%\Release + MONOMAC;NO_GUI_TESTING;$(DefineConstants) + prompt + 4 + false + None + false + Mac Developer + false + false + cjk,mideast,other,rare,west + + + + + + + + ..\..\..\external\mono\external\xunit-binaries\xunit.core.dll + + + ..\..\..\external\mono\external\xunit-binaries\xunit.assert.dll + + + ..\..\..\external\mono\external\xunit-binaries\xunit.abstractions.dll + + + ..\..\..\external\mono\external\xunit-binaries\xunit.execution.dotnet.dll + + + ..\..\..\external\mono\mcs\class\lib\monotouch\nunitlite.dll + + + ..\..\..\external\mono\external\xunit-binaries\Xunit.NetCore.Extensions.dll + + + ..\..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.1.1\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll + False + + + ..\..\..\packages\Microsoft.Extensions.Logging.Abstractions.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\..\..\packages\System.Buffers.4.4.0\lib\netstandard2.0\System.Buffers.dll + + + ..\..\..\packages\System.Runtime.CompilerServices.Unsafe.4.5.1\lib\netstandard2.0\System.Runtime.CompilerServices.Unsafe.dll + + + ..\..\..\packages\System.Memory.4.5.1\lib\netstandard2.0\System.Memory.dll + + + ..\..\..\packages\Microsoft.Extensions.Primitives.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Primitives.dll + + + ..\..\..\packages\Microsoft.Extensions.Configuration.Abstractions.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Abstractions.dll + + + ..\..\..\packages\Microsoft.Extensions.Configuration.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.dll + + + ..\..\..\packages\Microsoft.Extensions.Configuration.Binder.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Configuration.Binder.dll + + + ..\..\..\packages\Microsoft.Extensions.Options.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Options.dll + + + ..\..\..\packages\Microsoft.Extensions.Logging.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.dll + + + ..\..\..\packages\xunit.runner.utility.2.4.0\lib\netstandard2.0\xunit.runner.utility.netstandard20.dll + + + ..\..\..\external\mono\mcs\class\lib\monotouch\System.Runtime.Serialization.Formatters.Soap.dll + + + ..\..\..\packages\Microsoft.Extensions.Options.ConfigurationExtensions.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll + + + ..\..\..\packages\Microsoft.Extensions.Logging.Configuration.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Configuration.dll + + + ..\..\..\packages\Microsoft.Extensions.Logging.Console.2.1.1\lib\netstandard2.0\Microsoft.Extensions.Logging.Console.dll + + + ..\..\..\packages\Mono.Options.5.3.0.1\lib\netstandard1.3\Mono.Options.dll + + + + +%REFERENCES% + + + + + + + Info.plist + + + + + + TestRunner.NUnit\NUnitTestRunner.cs + + + TestRunner.Core\Extensions.Bool.cs + + + TestRunner.Core\LogWriter.cs + + + TestRunner.Core\MinimumLogLevel.cs + + + TestRunner.Core\TcpTextWriter.cs + + + TestRunner.Core\TestAssemblyInfo.cs + + + TestRunner.Core\TestCompletionStatus.cs + + + TestRunner.Core\TestExecutionState.cs + + + TestRunner.Core\TestFailureInfo.cs + + + TestRunner.Core\TestRunner.cs + + + TestRunner.xUnit\XUnitFilter.cs + + + TestRunner.xUnit\XUnitFilterType.cs + + + TestRunner.xUnit\XUnitResultFileFormat.cs + + + TestRunner.xUnit\XUnitTestRunner.cs + + + ApplicationOptions.cs + + %REGISTER TYPE% + + MacTestMain.cs + + + Assert.cs + + + + + TestRunner.xUnit\NUnitXml.xslt + + + + + + diff --git a/tests/bcl-test/BCLTests/Info-mac.plist.in b/tests/bcl-test/BCLTests/Info-mac.plist.in new file mode 100644 index 0000000000..4d95078fb7 --- /dev/null +++ b/tests/bcl-test/BCLTests/Info-mac.plist.in @@ -0,0 +1,20 @@ + + + + + CFBundleDisplayName + %APPLICATION NAME% + CFBundleIdentifier + %BUNDLE INDENTIFIER% + CFBundleName + systemtests + CFBundleVersion + 1 + LSMinimumSystemVersion + 10.9 + NSPrincipalClass + NSApplication + LSUIElement + 1 + + diff --git a/tests/bcl-test/BCLTests/templates/common/ApplicationOptions.cs b/tests/bcl-test/BCLTests/templates/common/ApplicationOptions.cs index a956c47697..9c2212294c 100644 --- a/tests/bcl-test/BCLTests/templates/common/ApplicationOptions.cs +++ b/tests/bcl-test/BCLTests/templates/common/ApplicationOptions.cs @@ -26,6 +26,7 @@ namespace BCLTests { Transport = defaults.StringForKey ("network.transport"); SortNames = defaults.BoolForKey ("display.sort"); LogFile = defaults.StringForKey ("log.file"); + ResultFile = defaults.StringForKey ("result.file"); bool b; if (bool.TryParse (Environment.GetEnvironmentVariable ("NUNIT_AUTOEXIT"), out b)) @@ -61,6 +62,7 @@ namespace BCLTests { { "enablexml", "Enable the xml reported.", v => EnableXml = false }, { "xmlmode", "The xml mode.", v => XmlMode = (XmlMode) Enum.Parse (typeof (XmlMode), v, false) }, { "logfile=", "A path where output will be saved.", v => LogFile = v }, + { "result=", "The path to be used to store the result", v => ResultFile = v}, }; try { @@ -87,6 +89,8 @@ namespace BCLTests { public string Transport { get; set; } = "TCP"; public string LogFile { get; set; } + + public string ResultFile { get; set; } public bool ShowUseNetworkLogger { get { return (EnableNetwork && !String.IsNullOrWhiteSpace (HostName) && (HostPort > 0 || Transport == "FILE")); } diff --git a/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/LogWriter.cs b/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/LogWriter.cs index 8d8df13ba1..3395d3d9fc 100644 --- a/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/LogWriter.cs +++ b/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/LogWriter.cs @@ -1,7 +1,9 @@ using System; using System.IO; using Foundation; +#if !MONOMAC using UIKit; +#endif using ObjCRuntime; using Constants = global::ObjCRuntime.Constants; @@ -26,7 +28,7 @@ namespace Xamarin.iOS.UnitTests static string UniqueIdentifier { get { -#if !__WATCHOS__ +#if !__WATCHOS__ && !MONOMAC IntPtr handle = UIDevice.CurrentDevice.Handle; if (UIDevice.CurrentDevice.RespondsToSelector (new Selector ("uniqueIdentifier"))) return NSString.FromHandle (objc_msgSend (handle, Selector.GetHandle("uniqueIdentifier"))); @@ -37,7 +39,7 @@ namespace Xamarin.iOS.UnitTests public void InitLogging () { -#if !__WATCHOS__ +#if !__WATCHOS__ && !MONOMAC UIDevice device = UIDevice.CurrentDevice; #endif @@ -45,7 +47,7 @@ namespace Xamarin.iOS.UnitTests writer.WriteLine ("[Runner executing:\t{0}]", "Run everything"); writer.WriteLine ("[MonoTouch Version:\t{0}]", Constants.Version); writer.WriteLine ("[Assembly:\t{0}.dll ({1} bits)]", typeof (NSObject).Assembly.GetName ().Name, IntPtr.Size * 8); -#if !__WATCHOS__ +#if !__WATCHOS__ && !MONOMAC writer.WriteLine ("[{0}:\t{1} v{2}]", device.Model, device.SystemName, device.SystemVersion); writer.WriteLine ("[Device Name:\t{0}]", device.Name); #endif diff --git a/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TcpTextWriter.cs b/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TcpTextWriter.cs index 8d6f1cf1ae..5b4b9116b0 100644 --- a/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TcpTextWriter.cs +++ b/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TcpTextWriter.cs @@ -7,7 +7,9 @@ using System.IO; using System.Net.Sockets; using System.Text; +#if __IOS__ using UIKit; +#endif namespace BCLTests.TestRunner.Core { public class TcpTextWriter : TextWriter { diff --git a/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitTestRunner.cs b/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitTestRunner.cs index f894e2a64b..37e44a8295 100644 --- a/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitTestRunner.cs +++ b/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitTestRunner.cs @@ -692,6 +692,9 @@ namespace Xamarin.iOS.UnitTests.XUnit try { OnAssemblyStart (assemblyInfo.Assembly); assemblyElement = Run (assemblyInfo.Assembly, assemblyInfo.FullPath); + } catch (FileNotFoundException ex) { + OnWarning ($"Assembly '{assemblyInfo.Assembly}' using path '{assemblyInfo.FullPath}' cannot be found on the filesystem. xUnit requires access to actual on-disk file."); + OnWarning ($"Exception is '{ex}'"); } finally { OnAssemblyFinish (assemblyInfo.Assembly); if (assemblyElement != null) diff --git a/tests/bcl-test/BCLTests/templates/iOSApp/ViewController.cs b/tests/bcl-test/BCLTests/templates/iOSApp/ViewController.cs index e8fc044728..b33f91f7b9 100644 --- a/tests/bcl-test/BCLTests/templates/iOSApp/ViewController.cs +++ b/tests/bcl-test/BCLTests/templates/iOSApp/ViewController.cs @@ -17,10 +17,12 @@ namespace BCLTests { { // var t = Path.GetFileName (typeof (ActivatorCas).Assembly.Location); foreach (var name in RegisterType.TypesToRegister.Keys) { - var a = Assembly.Load (name); + var a = RegisterType.TypesToRegister [name].Assembly; if (a == null) { Console.WriteLine ($"# WARNING: Unable to load assembly {name}."); continue; + } else { + Console.WriteLine ($"Loading assembly: {name}."); } yield return new TestAssemblyInfo (a, name); } diff --git a/tests/bcl-test/BCLTests/templates/macOS/Assert.cs b/tests/bcl-test/BCLTests/templates/macOS/Assert.cs new file mode 100644 index 0000000000..824d01b581 --- /dev/null +++ b/tests/bcl-test/BCLTests/templates/macOS/Assert.cs @@ -0,0 +1,188 @@ +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Resources; +using System.Runtime.InteropServices; +using System.Diagnostics; + +#if XAMCORE_2_0 +using Foundation; +using ObjCRuntime; +#else +using MonoTouch.Foundation; +using MonoTouch.ObjCRuntime; +#endif + +using NUnit.Framework; +using NUnit.Framework.Constraints; + +namespace MonoTests { +/* + class CategoryAttribute : Attribute + { + public string Category { get; set; } + + public CategoryAttribute (string category) + { + this.Category = category; + } + } +/* + static class Assert + { + public static void AreEqual (object a, object b, string msg) + { + NUnit.Framework.Assert.That (a, Is.EqualTo (b), msg); + } + + public static void AreEqual (object a, object b) + { + NUnit.Framework.Assert.That (a, Is.EqualTo (b)); + } + + public static void IsNotNull (object o, string msg) + { + NUnit.Framework.Assert.That (o, Is.Not.Null, msg); + } + + public static void IsNotNull (object o) + { + NUnit.Framework.Assert.That (o, Is.Not.Null); + } + + public static void IsNull (object o, string msg) + { + NUnit.Framework.Assert.That (o, Is.Null, msg); + } + + public static void IsNull (object o) + { + NUnit.Framework.Assert.That (o, Is.Null); + } + + public static void IsTrue (object o, string msg) + { + NUnit.Framework.Assert.That (o, Is.True, msg); + } + + public static void IsTrue (object o) + { + NUnit.Framework.Assert.That (o, Is.True); + } + + public static void IsFalse (object o, string msg) + { + NUnit.Framework.Assert.That (o, Is.False, msg); + } + + public static void IsFalse (object o) + { + NUnit.Framework.Assert.That (o, Is.False); + } + + public static void AreSame (object a, object b) + { + NUnit.Framework.Assert.That (a, Is.SameAs (b)); + } + + public static void AreSame (object a, object b, string msg) + { + NUnit.Framework.Assert.That (a, Is.SameAs (b), msg); + } + + public static void Fail (string msg) + { + NUnit.Framework.Assert.Fail (msg); + } + } +*/ + // nunit 1.x compatibility + public class TestCase { + protected virtual void SetUp () + { + } + + public static void Assert (string msg, bool condition) + { + NUnit.Framework.Assert.True (condition, msg); + } + + public static void AssertEquals (object a, object b) + { + NUnit.Framework.Assert.That (a, Is.EqualTo (b)); + } + + public static void AssertEquals (string msg, object a, object b) + { + NUnit.Framework.Assert.That (a, Is.EqualTo (b), msg); + } + + public static void AssertNull (object a) + { + NUnit.Framework.Assert.That (a, Is.Null); + } + + public static void AssertNull (string msg, object a) + { + NUnit.Framework.Assert.That (a, Is.Null, msg); + } + + public static void AssertNotNull (object a) + { + NUnit.Framework.Assert.That (a, Is.Not.Null); + } + + public static void AssertNotNull (string msg, object a) + { + NUnit.Framework.Assert.That (a, Is.Not.Null, msg); + } + + public static void Fail (string msg) + { + NUnit.Framework.Assert.Fail (msg); + } + } + + public class Assertion : TestCase { + } + + public class TestFixtureSetUpAttribute : SetUpAttribute { + } + + public class StringAssert { + #region StartsWith + static public void StartsWith(string expected, string actual, string message, params object[] args) + { + Assert.That(actual, new StartsWithConstraint(expected), message, args); + } + + static public void StartsWith(string expected, string actual, string message) + { + StartsWith(expected, actual, message, null); + } + + static public void StartsWith(string expected, string actual) + { + StartsWith(expected, actual, string.Empty, null); + } + #endregion + + #region Contains + static public void Contains(string expected, string actual, string message, params object[] args) + { + Assert.That(actual, new SubstringConstraint(expected), message, args); + } + + static public void Contains(string expected, string actual, string message) + { + Contains(expected, actual, message, null); + } + + static public void Contains(string expected, string actual) + { + Contains(expected, actual, string.Empty, null); + } + #endregion + } +} + diff --git a/tests/bcl-test/BCLTests/templates/macOS/MacTestMain.cs b/tests/bcl-test/BCLTests/templates/macOS/MacTestMain.cs new file mode 100644 index 0000000000..208b4eb1ba --- /dev/null +++ b/tests/bcl-test/BCLTests/templates/macOS/MacTestMain.cs @@ -0,0 +1,68 @@ +using System; +using System.Linq; +using System.Reflection; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Security.Cryptography; +#if XAMCORE_2_0 || __UNIFIED__ +using AppKit; +using Foundation; +#else +using MonoMac.AppKit; +using MonoMac.Foundation; +#endif +using BCLTests; +using Xamarin.iOS.UnitTests; +using Xamarin.iOS.UnitTests.NUnit; +using BCLTests.TestRunner.Core; +using Xamarin.iOS.UnitTests.XUnit; +using System.IO; + +namespace Xamarin.Mac.Tests +{ + static class MainClass + { + static int Main (string[] args) + { + NSApplication.Init(); + return RunTests (args); + } + + internal static IEnumerable GetTestAssemblies () + { + // var t = Path.GetFileName (typeof (ActivatorCas).Assembly.Location); + foreach (var name in RegisterType.TypesToRegister.Keys) { + var a = RegisterType.TypesToRegister [name].Assembly; + yield return new TestAssemblyInfo (a, name); + } + } + + static int RunTests (string [] original_args) + { + Console.WriteLine ("Running tests"); + var options = ApplicationOptions.Current; + + // we generate the logs in two different ways depending if the generate xml flag was + // provided. If it was, we will write the xml file to the tcp writer if present, else + // we will write the normal console output using the LogWriter + var logger = new LogWriter (Console.Out); + logger.MinimumLogLevel = MinimumLogLevel.Info; + var testAssemblies = GetTestAssemblies (); + TestRunner runner; + if (RegisterType.IsXUnit) + runner = new XUnitTestRunner (logger); + else + runner = new NUnitTestRunner (logger); + + runner.Run (testAssemblies.ToList ()); + + using (var writer = new StreamWriter(options.ResultFile)) { + runner.WriteResultsToFile (writer); + } + logger.Info ($"Xml result can be found {options.ResultFile}"); + + logger.Info ($"Tests run: {runner.TotalTests} Passed: {runner.PassedTests} Inconclusive: {runner.InconclusiveTests} Failed: {runner.FailedTests} Ignored: {runner.SkippedTests}"); + return runner.FailedTests != 0 ? 1 : 0; + } + } +} diff --git a/tests/xharness/BCLTestImporter/BCLTestImportTargetFactory.cs b/tests/xharness/BCLTestImporter/BCLTestImportTargetFactory.cs index 85dbcd885a..4c63b52390 100644 --- a/tests/xharness/BCLTestImporter/BCLTestImportTargetFactory.cs +++ b/tests/xharness/BCLTestImporter/BCLTestImportTargetFactory.cs @@ -27,11 +27,11 @@ namespace xharness.BCLTestImporter { } // generate all the different test targets. - public List GetBclTargets () + public List GetiOSBclTargets () { var result = new List (); // generate all projects, then create a new iOSTarget per project - foreach (var (name, path, xunit, platforms) in projectGenerator.GenerateAllTestProjects ()) { + foreach (var (name, path, xunit, platforms) in projectGenerator.GenerateAlliOSTestProjects ()) { var prefix = xunit ? "xUnit" : "NUnit"; result.Add (new iOSTestProject (path) { Name = $"[{prefix}] Mono {name}", @@ -46,5 +46,38 @@ namespace xharness.BCLTestImporter { } return result; } + + public List GetMacBclTargets (MacFlavors flavor) + { + Platform platform; + if (flavor == MacFlavors.Full) + platform = Platform.MacOSFull; + else + platform = Platform.MacOSModern; + var result = new List (); + foreach (var (name, path, xunit) in projectGenerator.GenerateAllMacTestProjects (platform)) { + var prefix = xunit ? "xUnit" : "NUnit"; + result.Add (new MacTestProject (path, targetFrameworkFlavor: flavor, generateVariations: false) { + Name = $"[{prefix}] Mono {name}", + Platform = "AnyCPU", + IsExecutableProject = true, + Dependency = async () => { + var rv = await Harness.BuildBclTests (); + if (!rv.Succeeded) + throw new Exception ($"Failed to build BCL tests, exit code: {rv.ExitCode}. Check the harness log for more details."); + } + }); + } + return result; + } + + public List GetMacBclTargets () + { + var result = new List (); + foreach (var flavor in new [] { MacFlavors.Full, MacFlavors.Modern}) { + result.AddRange (GetMacBclTargets (flavor)); + } + return result; + } } } diff --git a/tests/xharness/Harness.cs b/tests/xharness/Harness.cs index 5cee1114cf..e6c45185bf 100644 --- a/tests/xharness/Harness.cs +++ b/tests/xharness/Harness.cs @@ -295,6 +295,10 @@ namespace xharness MacTestProjects.Add (bclTestProject); } } + var monoImportTestFactory = new BCLTestImportTargetFactory (this); + foreach (var target in monoImportTestFactory.GetMacBclTargets ()) { + MacTestProjects.Add (target); + } } void AutoConfigureIOS () @@ -360,7 +364,7 @@ namespace xharness // add all the tests that are using the precompiled mono assemblies var monoImportTestFactory = new BCLTestImportTargetFactory (this); - foreach (var target in monoImportTestFactory.GetBclTargets ()) { + foreach (var target in monoImportTestFactory.GetiOSBclTargets ()) { IOSTestProjects.Add (target); } diff --git a/tests/xharness/Jenkins.cs b/tests/xharness/Jenkins.cs index 04cedfbc2d..22c89d3706 100644 --- a/tests/xharness/Jenkins.cs +++ b/tests/xharness/Jenkins.cs @@ -727,6 +727,7 @@ namespace xharness build.ProjectPlatform = project.Platform; build.SpecifyPlatform = false; build.SpecifyConfiguration = build.ProjectConfiguration != "Debug"; + build.Dependency = project.Dependency; RunTestTask exec; IEnumerable execs; var ignored_main = ignored; diff --git a/tests/xharness/MakefileGenerator.cs b/tests/xharness/MakefileGenerator.cs index 3e696083a4..bb3a0e7679 100644 --- a/tests/xharness/MakefileGenerator.cs +++ b/tests/xharness/MakefileGenerator.cs @@ -109,6 +109,8 @@ namespace xharness // build/[install/]run targets for specific test projects. foreach (var target in allTargets) { + if (target.Name.IndexOf ("BCLTests", StringComparison.Ordinal) != -1) // special case for those targets that are auto generated from the mono assemblies + continue; var make_escaped_simplified_name = target.SimplifiedName.Replace (" ", "\\ "); var make_escaped_name = target.Name.Replace (" ", "\\ "); diff --git a/tests/xharness/ProjectFileExtensions.cs b/tests/xharness/ProjectFileExtensions.cs index 9d18815264..660d78262b 100644 --- a/tests/xharness/ProjectFileExtensions.cs +++ b/tests/xharness/ProjectFileExtensions.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using System.Linq; using System.Xml; diff --git a/tools/bcl-test-importer/BCLTestImporter/ApplicationOptions.cs b/tools/bcl-test-importer/BCLTestImporter/ApplicationOptions.cs index 1664b61cdd..a20a0a1f9d 100644 --- a/tools/bcl-test-importer/BCLTestImporter/ApplicationOptions.cs +++ b/tools/bcl-test-importer/BCLTestImporter/ApplicationOptions.cs @@ -16,7 +16,8 @@ namespace BCLTestImporter { {Platform.iOS, "monotouch"}, {Platform.WatchOS, "monotouch_watch"}, {Platform.TvOS, "monotouch_tv"}, - {Platform.MacOS, "xammac"}, + {Platform.MacOSFull, "xammac"}, + {Platform.MacOSModern, "xammac"}, }; #endregion @@ -340,7 +341,7 @@ namespace BCLTestImporter { { "iOS", "Specifies that the platform to which the projects are going to be build is iOS.", i => Platform = Platform.iOS }, { "watchOS", "Specifies that the platform to which the projects are going to be build is watchOS.", w => Platform = Platform.WatchOS }, { "tvOS", "Specifies that the platform to which the projects are going to be build is tvOS.", t => Platform = Platform.TvOS }, - { "macOS", "Specifies that the platform to which the projects are going to be build is macOS.", m => Platform = Platform.MacOS }, + { "macOS", "Specifies that the platform to which the projects are going to be build is macOS.", m => Platform = Platform.MacOSFull }, { "generate-project", "Flag used to state that a new test project should be generated." + " Output path must be provided via -o.", f => GenerateProject = f != null }, { "generate-all-projects", "Flag used to state that all the test projects should be generated." diff --git a/tools/bcl-test-importer/BCLTestImporter/BCLTestAssemblyDefinition.cs b/tools/bcl-test-importer/BCLTestImporter/BCLTestAssemblyDefinition.cs index aae88acf37..c9d8312653 100644 --- a/tools/bcl-test-importer/BCLTestImporter/BCLTestAssemblyDefinition.cs +++ b/tools/bcl-test-importer/BCLTestImporter/BCLTestAssemblyDefinition.cs @@ -12,7 +12,8 @@ namespace BCLTestImporter { {Platform.iOS, "monotouch"}, {Platform.WatchOS, "monotouch"}, {Platform.TvOS, "monotouch"}, - {Platform.MacOS, "xammac"}, + {Platform.MacOSFull, "xammac_net_4_5"}, + {Platform.MacOSModern, "xammac_net_4_5"}, }; #endregion diff --git a/tools/bcl-test-importer/BCLTestImporter/BCLTestImporterTests/TestAssemblyDefinitionTest.cs b/tools/bcl-test-importer/BCLTestImporter/BCLTestImporterTests/TestAssemblyDefinitionTest.cs index 620a29e445..ee14d28480 100644 --- a/tools/bcl-test-importer/BCLTestImporter/BCLTestImporterTests/TestAssemblyDefinitionTest.cs +++ b/tools/bcl-test-importer/BCLTestImporter/BCLTestImporterTests/TestAssemblyDefinitionTest.cs @@ -63,7 +63,7 @@ namespace BCLTestImporterTests { var testAssemblyDefinition = new BCLTestAssemblyDefinition ("MONOTOUCH_System.Json.Microsoft_xunit-test.dll"); var home = Environment.GetEnvironmentVariable ("HOME"); var expectedPath = Path.Combine (home, "mcs/class/lib", "xammac", "tests", testAssemblyDefinition.Name); - Assert.Equal (expectedPath, testAssemblyDefinition.GetPath (Environment.GetEnvironmentVariable("HOME"), Platform.MacOS)); + Assert.Equal (expectedPath, testAssemblyDefinition.GetPath (Environment.GetEnvironmentVariable("HOME"), Platform.MacOSFull)); } } } diff --git a/tools/bcl-test-importer/BCLTestImporter/BCLTestProjectDefinitionWorkaround.cs b/tools/bcl-test-importer/BCLTestImporter/BCLTestProjectDefinitionWorkaround.cs index 5e7d5d00aa..99fcc142d4 100644 --- a/tools/bcl-test-importer/BCLTestImporter/BCLTestProjectDefinitionWorkaround.cs +++ b/tools/bcl-test-importer/BCLTestImporter/BCLTestProjectDefinitionWorkaround.cs @@ -9,7 +9,7 @@ namespace BCLTestImporter // Added for the workaround so that it does not make the code uglier public partial struct BCLTestProjectDefinition { - static Dictionary> cachedAssemblyInfo = + static Dictionary> iOSCachedAssemblyInfo = new Dictionary> { {"SystemNumericsTests", new List<(string assembly, string hint)> { @@ -138,12 +138,316 @@ namespace BCLTestImporter }}, }; + private static Dictionary> macCachedAssemblyInfo = + new Dictionary> { + {"MonoCSharpTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"Mono.CSharp", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/Mono.CSharp.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"xammac_net_4_5_Mono.CSharp_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_Mono.CSharp_test.dll"), + }}, + {"MonoDataSqilteTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"Mono.Data.Sqlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/Mono.Data.Sqlite.dll"), + (assembly:"System.Data", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Data.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"xammac_net_4_5_Mono.Data.Sqlite_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_Mono.Data.Sqlite_test.dll"), + }}, + {"MonoDataTdsTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"Mono.Data.Tds", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/Mono.Data.Tds.dll"), + (assembly:"xammac_net_4_5_Mono.Data.Tds_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_Mono.Data.Tds_test.dll"), + }}, + {"MonoPoxisTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"Mono.Posix", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/Mono.Posix.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"xammac_net_4_5_Mono.Posix_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_Mono.Posix_test.dll"), + }}, + {"MonoSecurtiyTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"Mono.Security", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/Mono.Security.dll"), + (assembly:"xammac_net_4_5_Mono.Security_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_Mono.Security_test.dll"), + }}, + {"SystemComponentModelDataAnnotationsTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.ComponentModel.DataAnnotations", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.ComponentModel.DataAnnotations.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"xammac_net_4_5_System.ComponentModel.DataAnnotations_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.ComponentModel.DataAnnotations_test.dll"), + }}, + {"SystemConfigurationTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"System.Configuration", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Configuration.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Xml", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.dll"), + (assembly:"xammac_net_4_5_System.Configuration_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Configuration_test.dll"), + }}, + {"SystemCoreTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"xammac_net_4_5_System.Core_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Core_test.dll"), + }}, + {"SystemDataLinqTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"System.Data", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Data.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Data.Linq", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Data.Linq.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"xammac_net_4_5_System.Data.Linq_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Data.Linq_test.dll"), + }}, + {"SystemDataTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"System.Data", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Data.dll"), + (assembly:"System.Xml", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Configuration", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Configuration.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"Mono.Data.Sqlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/Mono.Data.Sqlite.dll"), + (assembly:"xammac_net_4_5_System.Data_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Data_test.dll"), + }}, + {"SystemIOCompressionFileSystemTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.IO.Compression", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.IO.Compression.dll"), + (assembly:"System.IO.Compression.FileSystem", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.IO.Compression.FileSystem.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"xammac_net_4_5_System.IO.Compression.FileSystem_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.IO.Compression.FileSystem_test.dll"), + }}, + {"SystemIOCompressionTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.IO.Compression", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.IO.Compression.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"xammac_net_4_5_System.IO.Compression_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.IO.Compression_test.dll"), + }}, + {"SystemIdentityModelTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"System.IdentityModel", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.IdentityModel.dll"), + (assembly:"System.Runtime.Serialization", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Runtime.Serialization.dll"), + (assembly:"System.Xml", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.dll"), + (assembly:"xammac_net_4_5_System.IdentityModel_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.IdentityModel_test.dll"), + }}, + {"SystemJsonTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Json", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Json.dll"), + (assembly:"xammac_net_4_5_System.Json_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Json_test.dll"), + }}, + {"SystemNetHttpTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Net.Http", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Net.Http.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"xammac_net_4_5_System.Net.Http_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Net.Http_test.dll"), + }}, + {"SystemNumericsTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Numerics", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Numerics.dll"), + (assembly:"xammac_net_4_5_System.Numerics_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Numerics_test.dll"), + }}, + {"SystemRuntimeSerializationFormattersSoapTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Runtime.Serialization.Formatters.Soap", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Runtime.Serialization.Formatters.Soap.dll"), + (assembly:"xammac_net_4_5_System.Runtime.Serialization.Formatters.Soap_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Runtime.Serialization.Formatters.Soap_test.dll"), + }}, + {"SystemSecurityTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Security", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Security.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"System.Xml", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.dll"), + (assembly:"xammac_net_4_5_System.Security_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Security_test.dll"), + }}, + {"SystemServiceModelTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"System.ServiceModel", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.ServiceModel.dll"), + (assembly:"System.Runtime.Serialization", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Runtime.Serialization.dll"), + (assembly:"System.Xml", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.IdentityModel", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.IdentityModel.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"System.Security", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Security.dll"), + (assembly:"xammac_net_4_5_System.ServiceModel_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.ServiceModel_test.dll"), + }}, + {"SystemTransactionsTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Transactions", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Transactions.dll"), + (assembly:"xammac_net_4_5_System.Transactions_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Transactions_test.dll"), + }}, + {"SystemXmlLinqTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System.Xml", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.dll"), + (assembly:"System.Xml.Linq", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.Linq.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"xammac_net_4_5_System.Xml.Linq_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Xml.Linq_test.dll"), + }}, + {"SystemXmlTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"System.Xml", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"System.Data", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Data.dll"), + (assembly:"xammac_net_4_5_System.Xml_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Xml_test.dll"), + }}, + {"SystemTests", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"nunitlite", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/nunitlite.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"System.Xml", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.dll"), + (assembly:"System.Configuration", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Configuration.dll"), + (assembly:"System.Data", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Data.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"Mono.Security", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/Mono.Security.dll"), + (assembly:"xammac_net_4_5_System_test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System_test.dll"), + }}, + {"MicrosoftCSharpXunit", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"xunit.core", hint:""), + (assembly:"xunit.abstractions", hint:""), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"Xunit.NetCore.Extensions", hint:"{MONO_ROOT}external/xunit-binaries/Xunit.NetCore.Extensions.dll"), + (assembly:"Microsoft.CSharp", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/Microsoft.CSharp.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"xunit.assert", hint:""), + (assembly:"xammac_net_4_5_Microsoft.CSharp_xunit-test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_Microsoft.CSharp_xunit-test.dll"), + }}, + {"SystemCoreXunit", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"xunit.core", hint:""), + (assembly:"xunit.abstractions", hint:""), + (assembly:"xunit.assert", hint:""), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"Microsoft.CSharp", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/Microsoft.CSharp.dll"), + (assembly:"Xunit.NetCore.Extensions", hint:"{MONO_ROOT}external/xunit-binaries/Xunit.NetCore.Extensions.dll"), + (assembly:"xunit.execution.dotnet", hint:""), + (assembly:"xammac_net_4_5_System.Core_xunit-test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Core_xunit-test.dll"), + }}, + {"SystemDataXunit", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"System.Data", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Data.dll"), + (assembly:"System.Xml", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"xunit.core", hint:""), + (assembly:"xunit.abstractions", hint:""), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"xunit.assert", hint:""), + (assembly:"Xunit.NetCore.Extensions", hint:"{MONO_ROOT}external/xunit-binaries/Xunit.NetCore.Extensions.dll"), + (assembly:"xammac_net_4_5_System.Data_xunit-test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Data_xunit-test.dll"), + }}, + {"SystemJsonXunit", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"xunit.core", hint:""), + (assembly:"xunit.abstractions", hint:""), + (assembly:"xunit.assert", hint:""), + (assembly:"System.Json", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Json.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"xammac_net_4_5_System.Json_xunit-test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Json_xunit-test.dll"), + }}, + {"SystemNumericsXunit", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"xunit.core", hint:""), + (assembly:"xunit.abstractions", hint:""), + (assembly:"xunit.assert", hint:""), + (assembly:"System.Numerics", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Numerics.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"Xunit.NetCore.Extensions", hint:"{MONO_ROOT}external/xunit-binaries/Xunit.NetCore.Extensions.dll"), + (assembly:"Microsoft.CSharp", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/Microsoft.CSharp.dll"), + (assembly:"xammac_net_4_5_System.Numerics_xunit-test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Numerics_xunit-test.dll"), + }}, + {"SystemRuntimeCompilerServicesXunit", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"xunit.core", hint:""), + (assembly:"xunit.abstractions", hint:""), + (assembly:"System.Runtime.CompilerServices.Unsafe", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Runtime.CompilerServices.Unsafe.dll"), + (assembly:"xunit.assert", hint:""), + (assembly:"xammac_net_4_5_System.Runtime.CompilerServices.Unsafe_xunit-test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Runtime.CompilerServices.Unsafe_xunit-test.dll"), + }}, + {"SystemSecurityXunit", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"xunit.core", hint:""), + (assembly:"xunit.abstractions", hint:""), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"xunit.assert", hint:""), + (assembly:"System.Security", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Security.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"xammac_net_4_5_System.Security_xunit-test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Security_xunit-test.dll"), + }}, + {"SystemXmlLinqXunit", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"System.Xml", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.dll"), + (assembly:"xunit.core", hint:""), + (assembly:"xunit.abstractions", hint:""), + (assembly:"System.Xml.Linq", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Xml.Linq.dll"), + (assembly:"Xunit.NetCore.Extensions", hint:"{MONO_ROOT}external/xunit-binaries/Xunit.NetCore.Extensions.dll"), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"xunit.assert", hint:""), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"xammac_net_4_5_System.Xml.Linq_xunit-test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System.Xml.Linq_xunit-test.dll"), + }}, + {"SystemXunit", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"xunit.core", hint:""), + (assembly:"xunit.abstractions", hint:""), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"xunit.assert", hint:""), + (assembly:"Xunit.NetCore.Extensions", hint:"{MONO_ROOT}external/xunit-binaries/Xunit.NetCore.Extensions.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"xammac_net_4_5_System_xunit-test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_System_xunit-test.dll"), + }}, + {"CorlibXunit", new List<(string assembly, string hint)> { + (assembly:"mscorlib", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/mscorlib.dll"), + (assembly:"xunit.core", hint:""), + (assembly:"xunit.abstractions", hint:""), + (assembly:"Xunit.NetCore.Extensions", hint:"{MONO_ROOT}external/xunit-binaries/Xunit.NetCore.Extensions.dll"), + (assembly:"xunit.assert", hint:""), + (assembly:"System", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.dll"), + (assembly:"System.Core", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Core.dll"), + (assembly:"System.Numerics", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Numerics.dll"), + (assembly:"System.Runtime.CompilerServices.Unsafe", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/System.Runtime.CompilerServices.Unsafe.dll"), + (assembly:"xammac_net_4_5_corlib_xunit-test.dll", hint:"{MONO_ROOT}mcs/class/lib/xammac_net_4_5/tests/xammac_net_4_5_corlib_xunit-test.dll"), + }}, + }; public List<(string assembly, string hintPath)> GetCachedAssemblyInclusionInformation (string monoRootPath, Platform platform) { if (!monoRootPath.EndsWith ("/")) monoRootPath += "/"; - var info = cachedAssemblyInfo[Name]; + var info = new List<(string assembly, string hintPath)> (); + switch (platform){ + case Platform.iOS: + case Platform.TvOS: + case Platform.WatchOS: + info = iOSCachedAssemblyInfo[Name]; + break; + case Platform.MacOSFull: + case Platform.MacOSModern: + info = macCachedAssemblyInfo[Name]; + break; + } // lets fix the path var fixedResult = new List<(string assembly, string hintPath)> (); foreach (var (assembly, hin) in info){ diff --git a/tools/bcl-test-importer/BCLTestImporter/BCLTestProjectGenerator.cs b/tools/bcl-test-importer/BCLTestImporter/BCLTestProjectGenerator.cs index b78c65a125..efab158e4c 100644 --- a/tools/bcl-test-importer/BCLTestImporter/BCLTestProjectGenerator.cs +++ b/tools/bcl-test-importer/BCLTestImporter/BCLTestProjectGenerator.cs @@ -23,15 +23,22 @@ namespace BCLTestImporter { internal static readonly string WatchOSTemplatePathKey = "%TEMPLATE PATH%"; internal static readonly string WatchOSCsporjAppKey = "%WATCH APP PROJECT PATH%"; internal static readonly string WatchOSCsporjExtensionKey ="%WATCH EXTENSION PROJECT PATH%"; + internal static readonly string TargetFrameworkVersionKey = "%TARGET FRAMEWORK VERSION%"; + internal static readonly string TargetExtraInfoKey = "%TARGET EXTRA INFO%"; + internal static readonly string DefineConstantsKey = "%DEFINE CONSTANTS%"; static readonly Dictionary plistTemplateMatches = new Dictionary { {Platform.iOS, "Info.plist.in"}, {Platform.TvOS, "Info-tv.plist.in"}, {Platform.WatchOS, "Info-watchos.plist.in"}, + {Platform.MacOSFull, "Info-mac.plist.in"}, + {Platform.MacOSModern, "Info-mac.plist.in"}, }; static readonly Dictionary projectTemplateMatches = new Dictionary { {Platform.iOS, "BCLTests.csproj.in"}, {Platform.TvOS, "BCLTests-tv.csproj.in"}, {Platform.WatchOS, "BCLTests-watchos.csproj.in"}, + {Platform.MacOSFull, "BCLTests-mac.csproj.in"}, + {Platform.MacOSModern, "BCLTests-mac.csproj.in"}, }; static readonly Dictionary watchOSProjectTemplateMatches = new Dictionary { @@ -56,13 +63,15 @@ namespace BCLTestImporter { "System", "System.Xml", "System.Xml.Linq", + "System.Core", + "xunit.core", + "xunit.abstractions", + "xunit.assert", }; - // Ww have different lists for the test projects: - // 1. commonTestProjects: Those projects that can be ran in all platforms. - // 2. iOSTestProjects: Those projects that can be ran on iOS - - static readonly List<(string name, string[] assemblies)> commonTestProjects = new List<(string name, string[] assemblies)> { + // we have two different types of list, those that are for the iOS like projects (ios, tvos and watch os) and those + // for mac + static readonly List<(string name, string[] assemblies)> commoniOSTestProjects = new List<(string name, string[] assemblies)> { // NUNIT TESTS (name:"SystemTests", assemblies: new[] {"MONOTOUCH_System_test.dll"}), @@ -153,6 +162,77 @@ namespace BCLTestImporter { "MONOTOUCH_Mono.Data.Tds_test.dll", // issue https://gist.github.com/mandel-macaque/d97fa28f8a73c3016d1328567da77a0b }; + private static readonly List<(string name, string[] assemblies)> macTestProjects = new List<(string name, string[] assemblies)> { + + // NUNIT Projects + (name:"MonoCSharpTests", assemblies: new [] {"xammac_net_4_5_Mono.CSharp_test.dll"}), + (name:"MonoDataSqilteTests", assemblies: new [] {"xammac_net_4_5_Mono.Data.Sqlite_test.dll"}), + (name:"MonoDataTdsTests", assemblies: new [] {"xammac_net_4_5_Mono.Data.Tds_test.dll"}), + (name:"MonoPoxisTests", assemblies: new [] {"xammac_net_4_5_Mono.Posix_test.dll"}), + (name:"MonoSecurtiyTests", assemblies: new [] {"xammac_net_4_5_Mono.Security_test.dll"}), + (name:"SystemComponentModelDataAnnotationsTests", assemblies: new [] {"xammac_net_4_5_System.ComponentModel.DataAnnotations_test.dll"}), + (name:"SystemConfigurationTests", assemblies: new [] {"xammac_net_4_5_System.Configuration_test.dll"}), + (name:"SystemCoreTests", assemblies: new [] {"xammac_net_4_5_System.Core_test.dll"}), + (name:"SystemDataLinqTests", assemblies: new [] {"xammac_net_4_5_System.Data.Linq_test.dll"}), + (name:"SystemDataTests", assemblies: new [] {"xammac_net_4_5_System.Data_test.dll"}), + (name:"SystemIOCompressionFileSystemTests", assemblies: new [] {"xammac_net_4_5_System.IO.Compression.FileSystem_test.dll"}), + (name:"SystemIOCompressionTests", assemblies: new [] {"xammac_net_4_5_System.IO.Compression_test.dll"}), + (name:"SystemIdentityModelTests", assemblies: new [] {"xammac_net_4_5_System.IdentityModel_test.dll"}), + (name:"SystemJsonTests", assemblies: new [] {"xammac_net_4_5_System.Json_test.dll"}), + (name:"SystemNetHttpTests", assemblies: new [] {"xammac_net_4_5_System.Net.Http_test.dll"}), + (name:"SystemNumericsTests", assemblies: new [] {"xammac_net_4_5_System.Numerics_test.dll"}), + (name:"SystemRuntimeSerializationFormattersSoapTests", assemblies: new [] {"xammac_net_4_5_System.Runtime.Serialization.Formatters.Soap_test.dll"}), + (name:"SystemSecurityTests", assemblies: new [] {"xammac_net_4_5_System.Security_test.dll"}), + (name:"SystemServiceModelTests", assemblies: new [] {"xammac_net_4_5_System.ServiceModel_test.dll"}), + (name:"SystemTransactionsTests", assemblies: new [] {"xammac_net_4_5_System.Transactions_test.dll"}), + (name:"SystemXmlLinqTests", assemblies: new [] {"xammac_net_4_5_System.Xml.Linq_test.dll"}), + (name:"SystemXmlTests", assemblies: new [] {"xammac_net_4_5_System.Xml_test.dll"}), + (name:"SystemTests", assemblies: new [] {"xammac_net_4_5_System_test.dll"}), + + // xUnit Projects + (name:"MicrosoftCSharpXunit", assemblies: new [] {"xammac_net_4_5_Microsoft.CSharp_xunit-test.dll"}), + (name:"SystemCoreXunit", assemblies: new [] {"xammac_net_4_5_System.Core_xunit-test.dll"}), + (name:"SystemDataXunit", assemblies: new [] {"xammac_net_4_5_System.Data_xunit-test.dll"}), + (name:"SystemJsonXunit", assemblies: new [] {"xammac_net_4_5_System.Json_xunit-test.dll"}), + (name:"SystemNumericsXunit", assemblies: new [] {"xammac_net_4_5_System.Numerics_xunit-test.dll"}), + (name:"SystemRuntimeCompilerServicesXunit", assemblies: new [] {"xammac_net_4_5_System.Runtime.CompilerServices.Unsafe_xunit-test.dll"}), + (name:"SystemSecurityXunit", assemblies: new [] {"xammac_net_4_5_System.Security_xunit-test.dll"}), + (name:"SystemXmlLinqXunit", assemblies: new [] {"xammac_net_4_5_System.Xml.Linq_xunit-test.dll"}), + (name:"SystemXunit", assemblies: new [] {"xammac_net_4_5_System_xunit-test.dll"}), + (name:"CorlibXunit", assemblies: new [] {"xammac_net_4_5_corlib_xunit-test.dll"}), + }; + + static readonly List macIgnoredAssemblies = new List { + "xammac_net_4_5_corlib_test.dll ", // exception when loading the image via refection + "xammac_net_4_5_I18N.CJK_test.dll", + "xammac_net_4_5_I18N.MidEast_test.dll", + "xammac_net_4_5_I18N.Other_test.dll", + "xammac_net_4_5_I18N.Rare_test.dll", + "xammac_net_4_5_I18N.West_test.dll", + "xammac_net_4_5_Mono.CSharp_test.dll", //issue https://github.com/xamarin/maccore/issues/1186 + "xammac_net_4_5_Mono.Data.Sqlite_test.dll", // issue https://github.com/xamarin/maccore/issues/1187 + "xammac_net_4_5_Mono.Posix_test.dll", // issue https://github.com/xamarin/maccore/issues/1188 + "xammac_net_4_5_Mono.Posix_test.dll", // issues https://github.com/xamarin/maccore/issues/1189 and https://github.com/xamarin/maccore/issues/1190 + "xammac_net_4_5_System.Core_test.dll", // issue https://github.com/xamarin/maccore/issues/1191 + "xammac_net_4_5_System.Data_test.dll", // issues https://github.com/xamarin/maccore/issues/1192 and https://github.com/xamarin/maccore/issues/1193 + "xammac_net_4_5_System.IdentityModel_test.dll", // issues https://github.com/xamarin/maccore/issues/1194 + "xammac_net_4_5_System.IO.Compression.FileSystem_test.dll", // issues https://github.com/xamarin/maccore/issues/1195 + "xammac_net_4_5_System.IO.Compression_test.dll", // issue https://github.com/xamarin/maccore/issues/1146 + "xammac_net_4_5_System.IdentityModel_test.dll", // issues https://github.com/xamarin/maccore/issues/1196 + "xammac_net_4_5_System.Security_test.dll", // issue https://github.com/xamarin/maccore/issues/1197 + "xammac_net_4_5_System.ServiceModel_test.dll", // issues https://github.com/xamarin/maccore/issues/1198 + "xammac_net_4_5_System_test.dll", // issues https://github.com/xamarin/maccore/issues/1199 + "xammac_net_4_5_System.Transactions_test.dll", // issues https://github.com/xamarin/maccore/issues/1200 + "xammac_net_4_5_System.Xml_test.dll", // issues https://github.com/xamarin/maccore/issues/1201 and https://github.com/xamarin/maccore/issues/1202 + "xammac_net_4_5_corlib_xunit-test.dll", // issues https://github.com/xamarin/maccore/issues/1203 + "xammac_net_4_5_System.Core_xunit-test.dll", // issue https://github.com/xamarin/maccore/issues/1204 + "xammac_net_4_5_System.Data_xunit-test.dll", // issue https://gist.github.com/mandel-macaque/3f4d1eeca511cb8654fb518cc3bb2e92 + "xammac_net_4_5_System_xunit-test.dll", // issue https://github.com/xamarin/maccore/issues/1209 + "xammac_net_4_5_System.Configuration_test.dll", // issue https://github.com/xamarin/maccore/issues/1189 and https://github.com/xamarin/maccore/issues/1190 + "xammac_net_4_5_System.Security_xunit-test.dll", // https://github.com/xamarin/maccore/issues/1243 + + }; + readonly bool isCodeGeneration; public bool Override { get; set; } public string OutputDirectoryPath { get; private set; } @@ -195,6 +275,10 @@ namespace BCLTestImporter { return Path.Combine (OutputDirectoryPath, $"{projectName}-tvos.csproj"); case Platform.WatchOS: return Path.Combine (OutputDirectoryPath, $"{projectName}-watchos.csproj"); + case Platform.MacOSFull: + return Path.Combine (OutputDirectoryPath, $"{projectName}-mac-full.csproj"); + case Platform.MacOSModern: + return Path.Combine (OutputDirectoryPath, $"{projectName}-mac-modern.csproj"); default: return null; } @@ -225,6 +309,9 @@ namespace BCLTestImporter { return Path.Combine (rootDir, "Info-tv.plist"); case Platform.WatchOS: return Path.Combine (rootDir, "Info-watchos.plist"); + case Platform.MacOSFull: + case Platform.MacOSModern: + return Path.Combine (rootDir, "Info-mac.plist"); default: return Path.Combine (rootDir, "Info.plist"); } @@ -285,8 +372,9 @@ namespace BCLTestImporter { return tvOSIgnoredAssemblies.Contains (a.Name); case Platform.WatchOS: return watcOSIgnoredAssemblies.Contains (a.Name); - default: - return true; + case Platform.MacOSFull: + case Platform.MacOSModern: + return macIgnoredAssemblies.Contains (a.Name); } } return false; @@ -314,7 +402,7 @@ namespace BCLTestImporter { } var registerTypePath = Path.Combine (generatedCodeDir, "RegisterType.cs"); var registerCode = await RegisterTypeGenerator.GenerateCodeAsync (def.name, projectDefinition.IsXUnit, - RegisterTypesTemplatePath); + RegisterTypesTemplatePath, Platform.WatchOS); using (var file = new StreamWriter (registerTypePath, false)) { // false is do not append await file.WriteAsync (registerCode); } @@ -391,7 +479,7 @@ namespace BCLTestImporter { var registerTypePath = Path.Combine (generatedCodeDir, "RegisterType.cs"); var registerCode = await RegisterTypeGenerator.GenerateCodeAsync (def.name, projectDefinition.IsXUnit, - RegisterTypesTemplatePath); + RegisterTypesTemplatePath, Platform.iOS); using (var file = new StreamWriter (registerTypePath, false)) { // false is do not append await file.WriteAsync (registerCode); @@ -417,6 +505,48 @@ namespace BCLTestImporter { return projectPaths; } + async Task> GenerateMacTestProjectsAsync ( + IEnumerable<(string name, string[] assemblies)> projects, string generatedDir, Platform platform) + { + var projectPaths = new List<(string name, string path, bool xunit)> (); + foreach (var def in projects) { + var projectDefinition = new BCLTestProjectDefinition (def.name, def.assemblies); + if (IsIgnored (projectDefinition, platform)) // some projects are ignored, so we just continue + continue; + + if (!projectDefinition.Validate ()) + throw new InvalidOperationException ("xUnit and NUnit assemblies cannot be mixed in a test project."); + // generate the required type registration info + var generatedCodeDir = Path.Combine (generatedDir, projectDefinition.Name); + Directory.CreateDirectory (generatedCodeDir); + var registerTypePath = Path.Combine (generatedCodeDir, "RegisterType-mac.cs"); + + var registerCode = await RegisterTypeGenerator.GenerateCodeAsync (def.name, projectDefinition.IsXUnit, + RegisterTypesTemplatePath, platform); + + using (var file = new StreamWriter (registerTypePath, false)) { // false is do not append + await file.WriteAsync (registerCode); + } + + var plistTemplate = Path.Combine (PlistTemplateRootPath, plistTemplateMatches[platform]); + var plist = await BCLTestInfoPlistGenerator.GenerateCodeAsync (plistTemplate, projectDefinition.Name); + var infoPlistPath = GetPListPath (generatedCodeDir, platform); + using (var file = new StreamWriter (infoPlistPath, false)) { // false is do not append + await file.WriteAsync (plist); + } + + var projectTemplatePath = Path.Combine (ProjectTemplateRootPath, projectTemplateMatches[platform]); + var generatedProject = await GenerateMacAsync (projectDefinition.Name, registerTypePath, + projectDefinition.GetCachedAssemblyInclusionInformation (MonoRootPath, platform), projectTemplatePath, infoPlistPath, platform); + var projectPath = GetProjectPath (projectDefinition.Name, platform); + projectPaths.Add ((name: projectDefinition.Name, path: projectPath, xunit: projectDefinition.IsXUnit)); + using (var file = new StreamWriter (projectPath, false)) { // false is do not append + await file.WriteAsync (generatedProject); + } + } + return projectPaths; + } + /// /// Generates all the project files for the given projects and platform /// @@ -428,11 +558,19 @@ namespace BCLTestImporter { async Task> GenerateTestProjectsAsync ( IEnumerable<(string name, string[] assemblies)> projects, Platform platform, string generatedDir) { - List<(string name, string path, bool xunit)> result; - if (platform == Platform.WatchOS) + List<(string name, string path, bool xunit)> result = new List<(string name, string path, bool xunit)> (); + switch (platform) { + case Platform.WatchOS: result = await GenerateWatchOSTestProjectsAsync (projects, generatedDir); - else + break; + case Platform.iOS: result = await GenerateiOSTestProjectsAsync (projects, platform, generatedDir); + break; + case Platform.MacOSFull: + case Platform.MacOSModern: + result = await GenerateMacTestProjectsAsync (projects, generatedDir, platform); + break; + } return result; } @@ -449,7 +587,7 @@ namespace BCLTestImporter { var projects = new Dictionary platforms)> (); foreach (var platform in new [] {Platform.iOS, Platform.TvOS, Platform.WatchOS}) { - var generated = await GenerateTestProjectsAsync (commonTestProjects, platform, generatedCodePathRoot); + var generated = await GenerateTestProjectsAsync (commoniOSTestProjects, platform, generatedCodePathRoot); foreach (var (name, path, xunit) in generated) { if (!projects.ContainsKey (name)) { projects [name] = (path, xunit, new List { platform }); @@ -467,7 +605,7 @@ namespace BCLTestImporter { } // creates all the projects that have already been defined - public async Task platforms)>> GenerateAllTestProjectsAsync () + public async Task platforms)>> GenerateAlliOSTestProjectsAsync () { var projectPaths = new List<(string name, string path, bool xunit, List platforms)> (); if (!isCodeGeneration) @@ -482,8 +620,23 @@ namespace BCLTestImporter { return projectPaths; } - public List<(string name, string path, bool xunit, List platforms)> GenerateAllTestProjects () => GenerateAllTestProjectsAsync ().Result; + public List<(string name, string path, bool xunit, List platforms)> GenerateAlliOSTestProjects () => GenerateAlliOSTestProjectsAsync ().Result; + public async Task> GenerateAllMacTestProjectsAsync (Platform platform) + { + if (!isCodeGeneration) + throw new InvalidOperationException ("Project generator was instantiated to delete the generated code."); + var generatedCodePathRoot = GeneratedCodePathRoot; + if (!Directory.Exists (generatedCodePathRoot)) { + Directory.CreateDirectory (generatedCodePathRoot); + } + + var generated = await GenerateTestProjectsAsync (macTestProjects, platform, generatedCodePathRoot); + return generated; + } + + public List<(string name, string path, bool xunit)> GenerateAllMacTestProjects (Platform platform) => GenerateAllMacTestProjectsAsync (platform).Result; + /// /// Generates an iOS project for testing purposes. The generated project will contain the references to the /// mono test assemblies to run. @@ -514,6 +667,39 @@ namespace BCLTestImporter { } } + static async Task GenerateMacAsync (string projectName, string registerPath, List<(string assembly, string hintPath)> info, string templatePath, string infoPlistPath, Platform platform) + { + infoPlistPath = infoPlistPath.Replace ('/', '\\'); + var sb = new StringBuilder (); + foreach (var assemblyInfo in info) { + if (!excludeDlls.Contains (assemblyInfo.assembly)) + sb.AppendLine (GetReferenceNode (assemblyInfo.assembly, assemblyInfo.hintPath)); + } + + using (var reader = new StreamReader(templatePath)) { + var result = await reader.ReadToEndAsync (); + result = result.Replace (NameKey, projectName); + result = result.Replace (ReferencesKey, sb.ToString ()); + result = result.Replace (RegisterTypeKey, GetRegisterTypeNode (registerPath)); + result = result.Replace (PlistKey, infoPlistPath); + switch (platform){ + case Platform.MacOSFull: + result = result.Replace (TargetFrameworkVersionKey, "v4.5"); + result = result.Replace (TargetExtraInfoKey, + "true"); + result = result.Replace (DefineConstantsKey, "XAMCORE_2_0;ADD_BCL_EXCLUSIONS;XAMMAC_4_5"); + break; + case Platform.MacOSModern: + result = result.Replace (TargetFrameworkVersionKey, "v2.0"); + result = result.Replace (TargetExtraInfoKey, + "Xamarin.Mac"); + result = result.Replace (DefineConstantsKey, "XAMCORE_2_0;ADD_BCL_EXCLUSIONS;MOBILE;XAMMAC"); + break; + } + return result; + } + } + internal string GenerateWatchProject (string projectName, string template, string infoPlistPath) { var result = template.Replace (NameKey, projectName); @@ -568,14 +754,14 @@ namespace BCLTestImporter { Directory.Delete (GeneratedCodePathRoot, true); // delete all the common projects foreach (var platform in new [] {Platform.iOS, Platform.TvOS}) { - foreach (var testProject in commonTestProjects) { + foreach (var testProject in commoniOSTestProjects) { var projectPath = GetProjectPath (testProject.name, platform); if (File.Exists (projectPath)) File.Delete (projectPath); } } // delete each of the generated project files - foreach (var projectDefinition in commonTestProjects) { + foreach (var projectDefinition in commoniOSTestProjects) { var projectPath = GetProjectPath (projectDefinition.name, Platform.iOS); if (File.Exists (projectPath)) File.Delete (projectPath); @@ -593,7 +779,7 @@ namespace BCLTestImporter { foreach (var platform in new [] {Platform.iOS, Platform.TvOS}) { var testDir = BCLTestAssemblyDefinition.GetTestDirectory (MonoRootPath, platform); var missingAssembliesPlatform = Directory.GetFiles (testDir, NUnitPattern).Select (Path.GetFileName).Union ( - Directory.GetFiles (testDir, xUnitPattern).Select (Path.GetFileName)).ToList (); + Directory.GetFiles (testDir, xUnitPattern).Select (Path.GetFileName)).ToList (); foreach (var assembly in CommonIgnoredAssemblies) { missingAssembliesPlatform.Remove (assembly); @@ -601,7 +787,7 @@ namespace BCLTestImporter { // loop over the mono root path and grab all the assemblies, then intersect the found ones with the added // and ignored ones. - foreach (var projectDefinition in commonTestProjects) { + foreach (var projectDefinition in commoniOSTestProjects) { foreach (var testAssembly in projectDefinition.assemblies) { missingAssembliesPlatform.Remove (testAssembly); } diff --git a/tools/bcl-test-importer/BCLTestImporter/Platform.cs b/tools/bcl-test-importer/BCLTestImporter/Platform.cs index afe61ddca5..57bd0e9751 100644 --- a/tools/bcl-test-importer/BCLTestImporter/Platform.cs +++ b/tools/bcl-test-importer/BCLTestImporter/Platform.cs @@ -6,6 +6,7 @@ namespace BCLTestImporter { iOS, WatchOS, TvOS, - MacOS, + MacOSFull, + MacOSModern, } } \ No newline at end of file diff --git a/tools/bcl-test-importer/BCLTestImporter/Program.cs b/tools/bcl-test-importer/BCLTestImporter/Program.cs index 15f21ae521..3e1d52b8e3 100644 --- a/tools/bcl-test-importer/BCLTestImporter/Program.cs +++ b/tools/bcl-test-importer/BCLTestImporter/Program.cs @@ -170,7 +170,7 @@ namespace BCLTestImporter { outputWriter.WriteLine ("Generated project is:"); outputWriter.WriteLine (generatedProject); - using (var file = new StreamWriter (appOptions.Output, !appOptions.Override)) { // falso is do not append + using (var file = new StreamWriter (appOptions.Output, !appOptions.Override)) { // false is do not append file.Write (generatedProject); } return 0; @@ -186,7 +186,7 @@ namespace BCLTestImporter { var generatedCode = RegisterTypeGenerator.GenerateCode (typesPerAssembly, appOptions.IsXUnit, appOptions.RegisterTypeTemplate); outputWriter.WriteLine ("Generated code is:"); outputWriter.WriteLine (generatedCode); - using (var file = new StreamWriter (appOptions.Output, !appOptions.Override)) { // falso is do not append + using (var file = new StreamWriter (appOptions.Output, !appOptions.Override)) { // false is do not append file.Write (generatedCode); } return 0; @@ -213,7 +213,9 @@ namespace BCLTestImporter { } outputWriter.WriteLine ("Generating all the registered test projects"); - projectGenerator.GenerateAllTestProjectsAsync ().Wait (); + projectGenerator.GenerateAlliOSTestProjectsAsync().Wait (); + projectGenerator.GenerateAllMacTestProjectsAsync(Platform.MacOSFull).Wait (); + projectGenerator.GenerateAllMacTestProjectsAsync(Platform.MacOSModern).Wait (); return 0; } } diff --git a/tools/bcl-test-importer/BCLTestImporter/RegisterTypeGenerator.cs b/tools/bcl-test-importer/BCLTestImporter/RegisterTypeGenerator.cs index f8aacebd82..6529dc73be 100644 --- a/tools/bcl-test-importer/BCLTestImporter/RegisterTypeGenerator.cs +++ b/tools/bcl-test-importer/BCLTestImporter/RegisterTypeGenerator.cs @@ -15,7 +15,7 @@ namespace BCLTestImporter { // the following cache is a workaround until mono does provide the required binaries precompiled, at that point // we will remove the dict and we will use the refection based method. - static Dictionary cache = new Dictionary { + static Dictionary iOSCache = new Dictionary { {"SystemNumericsTests", ("MonoTests.System.Numerics", "MONOTOUCH_System.Numerics_test.dll", "MonoTests.System.Numerics.BigIntegerTest")}, {"SystemRuntimeSerializationTests", ("MonoTests", "MONOTOUCH_System.Runtime.Serialization_test.dll", "MonoTests.XmlComparer")}, {"SystemXmlLinqTests", ("MonoTests.System.Xml", "MONOTOUCH_System.Xml.Linq_test.dll", "MonoTests.System.Xml.ExtensionsTest")}, @@ -33,14 +33,61 @@ namespace BCLTestImporter { {"SystemLinqXunit", ("Microsoft.Test.ModuleCore", "MONOTOUCH_System.Xml.Linq_xunit-test.dll", "Microsoft.Test.ModuleCore.LtmContext")}, {"SystemRuntimeCompilerServicesUnsafeXunit", ("System.Runtime.CompilerServices", "MONOTOUCH_System.Runtime.CompilerServices.Unsafe_xunit-test.dll", "System.Runtime.CompilerServices.UnsafeTests")}, }; + + static Dictionary macCache = new Dictionary { + {"MonoCSharpTests", ("MonoTests.Visit", "xammac_net_4_5_Mono.CSharp_test.dll", "MonoTests.Visit.ASTVisitorTest")}, + {"MonoDataSqilteTests", ("MonoTests.Mono.Data.Sqlite", "xammac_net_4_5_Mono.Data.Sqlite_test.dll", "MonoTests.Mono.Data.Sqlite.SqliteiOS82BugTests")}, + {"MonoDataTdsTests", ("MonoTests.Mono.Data.Tds", "xammac_net_4_5_Mono.Data.Tds_test.dll", "MonoTests.Mono.Data.Tds.TdsConnectionPoolTest")}, + {"MonoPoxisTests", ("MonoTests.System.IO", "xammac_net_4_5_Mono.Posix_test.dll", "MonoTests.System.IO.StdioFileStreamTest")}, + {"MonoSecurtiyTests", ("MonoTests.System.Security.Cryptography", "xammac_net_4_5_Mono.Security_test.dll", "MonoTests.System.Security.Cryptography.SHA224ManagedTest")}, + {"SystemComponentModelDataAnnotationsTests", ("MonoTests.System.ComponentModel.DataAnnotations", "xammac_net_4_5_System.ComponentModel.DataAnnotations_test.dll", "MonoTests.System.ComponentModel.DataAnnotations.AssociatedMetadataTypeTypeDescriptionProviderTests")}, + {"SystemConfigurationTests", ("MonoTests.System.Configuration", "xammac_net_4_5_System.Configuration_test.dll", "MonoTests.System.Configuration.ProviderCollectionTest")}, + {"SystemCoreTests", ("MonoTests.System.Threading", "xammac_net_4_5_System.Core_test.dll", "MonoTests.System.Threading.ReaderWriterLockSlimTests")}, + {"SystemDataLinqTests", ("DbLinqTest", "xammac_net_4_5_System.Data.Linq_test.dll", "DbLinqTest.MsSqlDataContextTest")}, + {"SystemDataTests", ("MonoTests.System.Xml", "xammac_net_4_5_System.Data_test.dll", "MonoTests.System.Xml.XmlDataDocumentTest2")}, + {"SystemIOCompressionFileSystemTests", ("MonoTests.System.IO.Compression.FileSystem", "xammac_net_4_5_System.IO.Compression.FileSystem_test.dll", "MonoTests.System.IO.Compression.FileSystem.ZipArchiveTests")}, + {"SystemIOCompressionTests", ("MonoTests.System.IO.Compression", "xammac_net_4_5_System.IO.Compression_test.dll", "MonoTests.System.IO.Compression.ZipArchiveTests")}, + {"SystemIdentityModelTests", ("MonoTests.System.IdentityModel.Tokens", "xammac_net_4_5_System.IdentityModel_test.dll", "MonoTests.System.IdentityModel.Tokens.InMemorySymmetricSecurityKeyTest")}, + {"SystemJsonTests", ("MonoTests.System", "xammac_net_4_5_System.Json_test.dll", "MonoTests.System.JsonValueTests")}, + {"SystemNetHttpTests", ("MonoTests.System.Net.Http", "xammac_net_4_5_System.Net.Http_test.dll", "MonoTests.System.Net.Http.ByteArrayContentTest")}, + {"SystemNumericsTests", ("MonoTests.System.Numerics", "xammac_net_4_5_System.Numerics_test.dll", "MonoTests.System.Numerics.BigIntegerTest")}, + {"SystemRuntimeSerializationFormattersSoapTests", ("MonoTests.System.Runtime.Serialization.Formatters.Soap", "xammac_net_4_5_System.Runtime.Serialization.Formatters.Soap_test.dll", "MonoTests.System.Runtime.Serialization.Formatters.Soap.SerializationCallbackTest")}, + {"SystemSecurityTests", ("MonoCasTests.System.Security.Cryptography", "xammac_net_4_5_System.Security_test.dll", "MonoCasTests.System.Security.Cryptography.CryptographicAttributeObjectCas")}, + {"SystemTransactionsTests", ("MonoTests.System.Transactions", "xammac_net_4_5_System.Transactions_test.dll", "MonoTests.System.Transactions.AsyncTest")}, + {"SystemXmlLinqTests", ("MonoTests.System.Xml", "xammac_net_4_5_System.Xml.Linq_test.dll", "MonoTests.System.Xml.ExtensionsTest")}, + {"SystemXmlTests", ("nist_dom.fundamental", "xammac_net_4_5_System.Xml_test.dll", "nist_dom.fundamental.AttrTest")}, + {"SystemTests", ("MonoCasTests.System", "xammac_net_4_5_System_test.dll", "MonoCasTests.System.FileStyleUriParserCas")}, + {"MicrosoftCSharpXunit", ("Microsoft.CSharp.RuntimeBinder.Tests", "xammac_net_4_5_Microsoft.CSharp_xunit-test.dll", "Microsoft.CSharp.RuntimeBinder.Tests.AccessTests")}, + {"SystemCoreXunit", ("System.Dynamic.Tests", "xammac_net_4_5_System.Core_xunit-test.dll", "System.Dynamic.Tests.BinaryOperationTests")}, + {"SystemDataXunit", ("System.Data.SqlClient.Tests", "xammac_net_4_5_System.Data_xunit-test.dll", "System.Data.SqlClient.Tests.CloneTests")}, + {"SystemJsonXunit", ("System.Json.Tests", "xammac_net_4_5_System.Json_xunit-test.dll", "System.Json.Tests.JsonArrayTests")}, + {"SystemNumericsXunit", ("System.Numerics.Tests", "xammac_net_4_5_System.Numerics_xunit-test.dll", "System.Numerics.Tests.GenericVectorTests")}, + {"SystemRuntimeCompilerServicesXunit", ("System.Runtime.CompilerServices", "xammac_net_4_5_System.Runtime.CompilerServices.Unsafe_xunit-test.dll", "System.Runtime.CompilerServices.UnsafeTests")}, + {"SystemXmlLinqXunit", ("Microsoft.Test.ModuleCore", "xammac_net_4_5_System.Xml.Linq_xunit-test.dll", "Microsoft.Test.ModuleCore.LtmContext")}, + {"SystemServiceModelTests", ("MonoTests.System.ServiceModel", "xammac_net_4_5_System.ServiceModel_test.dll", "MonoTests.System.ServiceModel.Bug36080")}, + {"SystemSecurityXunit", ("System.Security.Cryptography.Pkcs.Tests", "xammac_net_4_5_System.Security_xunit-test.dll", "System.Security.Cryptography.Pkcs.Tests.CryptographicAttributeObjectCollectionTests")}, + {"SystemXunit", ("RegexTestNamespace", "xammac_net_4_5_System_xunit-test.dll", "RegexTestNamespace.RegexTestClass")}, + {"CorlibXunit", ("System.Collections.Generic.Tests", "xammac_net_4_5_corlib_xunit-test.dll", "System.Collections.Generic.Tests.ByteComparersTests")}, + }; - public static async Task GenerateCodeAsync (string projectName, bool isXunit, string templatePath) + public static async Task GenerateCodeAsync (string projectName, bool isXunit, string templatePath, Platform platform) { - var cachedData = cache[projectName]; + Dictionary cache = null; + switch (platform){ + case Platform.iOS: + case Platform.TvOS: + case Platform.WatchOS: + cache = iOSCache; + break; + case Platform.MacOSFull: + case Platform.MacOSModern: + cache = macCache; + break; + } var importStringBuilder = new StringBuilder (); var keyValuesStringBuilder = new StringBuilder (); - importStringBuilder.AppendLine ($"using {cachedData.testNamespace};"); - keyValuesStringBuilder.AppendLine ($"\t\t\t{{ \"{cachedData.testAssembly}\", typeof ({cachedData.testType})}}, "); + importStringBuilder.AppendLine ($"using {cache[projectName].testNamespace};"); + keyValuesStringBuilder.AppendLine ($"\t\t\t{{ \"{cache[projectName].testAssembly}\", typeof ({cache[projectName].testType})}}, "); // got the lines we want to add, read the template and substitute using (var reader = new StreamReader(templatePath)) { var result = await reader.ReadToEndAsync (); From c8aa44beffc73ce2ee9c9e8a48c148bdbc312df7 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Wed, 12 Dec 2018 15:01:03 +0100 Subject: [PATCH 15/23] [jenkins] Print out the environment for debug purposes. (#5261) This can be quite useful when writing new CI logic. --- jenkins/Jenkinsfile | 1 + jenkins/run-tests.sh | 3 +++ 2 files changed, 4 insertions(+) diff --git a/jenkins/Jenkinsfile b/jenkins/Jenkinsfile index c10da650ba..7456b21efb 100644 --- a/jenkins/Jenkinsfile +++ b/jenkins/Jenkinsfile @@ -395,6 +395,7 @@ timestamps { stage ('Checkout') { currentStage = "${STAGE_NAME}" echo ("Building on ${env.NODE_NAME}") + sh ("env | sort") // Print out environment for debug purposes scmVars = checkout scm isPr = (env.CHANGE_ID && !env.CHANGE_ID.empty ? true : false) branchName = env.BRANCH_NAME diff --git a/jenkins/run-tests.sh b/jenkins/run-tests.sh index 41cd9ff4fd..b1e087a6b5 100755 --- a/jenkins/run-tests.sh +++ b/jenkins/run-tests.sh @@ -3,6 +3,9 @@ cd "$(dirname "${BASH_SOURCE[0]}")/.." WORKSPACE=$(pwd) +# Print out environment for debug purposes +env | sort + report_error () { printf "🔥 [Test run failed](%s) 🔥\\n" "$URL" >> "$WORKSPACE/jenkins/pr-comments.md" From d7c2a45ca9351106f83fcf7f08c1b09a8a5fb563 Mon Sep 17 00:00:00 2001 From: Chris Hamons Date: Wed, 12 Dec 2018 09:55:57 -0500 Subject: [PATCH 16/23] Add 'NoBindingEmbedding' style binding project support (#5167) - Existing binding projects embed the native libraries within the assembly as managed resource - This does not scale well and has performance implications - This PR creates a new property, NoBindingEmbedding which when true processes the building and consumption of binding projects differently. - Existing binding projects are not affected, they will continue as is - I've written a full XM test suite and ported a subset to iOS. Since iOS only supports checked in projects, and I didn't want to make the existing situation worse by adding more, I only wrote tests that could use the existing test projects. -When we complete some form of msbuild testing reform, we'll revisit these tests. - Remove two files in MyiOSFrameworkBinding that are not used (we use copies elsewhere) - Remove unnecessary sleep and fix broken touch command - Output failing test log to console instead of test output - VSfM does not handle thousands of lines of test failure message well - Add ability to generate binding projects with LinkWith --- msbuild/Makefile | 9 +- .../Tasks/CreateBindingResourcePackage.cs | 16 + .../Xamarin.Mac.Common.targets | 18 +- .../Xamarin.Mac.ObjCBinding.CSharp.targets | 10 +- .../Xamarin.Mac.Tasks.csproj | 4 + .../Tasks/CreateBindingResourcePackageBase.cs | 83 ++++ .../Xamarin.MacDev.Tasks.Core.csproj | 2 + msbuild/Xamarin.Shared/Xamarin.Shared.targets | 66 +++ .../Xamarin.iOS.Common.targets | 7 +- .../Xamarin.iOS.ObjCBinding.CSharp.targets | 9 +- .../Xamarin.iOS.Tasks.Core.csproj | 3 + .../Tasks/CreateBindingResourcePackage.cs | 16 + .../Xamarin.iOS.Tasks.csproj | 1 + .../MyiOSFrameworkBinding/ApiDefinition.cs | 67 ---- .../MyiOSFrameworkBinding/StructsAndEnums.cs | 6 - .../NativeReferencesNoEmbedding.cs | 159 ++++++++ .../TestHelpers/TestBase.cs | 3 +- .../Xamarin.iOS.Tasks.Tests.csproj | 1 + tests/common/mac/ProjectTestHelpers.cs | 38 +- tests/mmptest/mmptest.csproj | 1 + .../src/BindingProjectNoEmbeddingTests.cs | 249 ++++++++++++ tests/mmptest/src/BindingProjectTests.cs | 117 +++--- tests/xharness/AppRunner.cs | 1 + tests/xharness/BCLTestInfo.cs | 1 + tests/xharness/GitHub.cs | 1 + tests/xharness/Jenkins.cs | 1 + tests/xharness/Simulators.cs | 1 + tests/xharness/SolutionGenerator.cs | 1 + tests/xharness/TVOSTarget.cs | 1 + tests/xharness/Target.cs | 1 + tests/xharness/TestProject.cs | 1 + tests/xharness/TodayExtensionTarget.cs | 1 + tests/xharness/WatchOSTarget.cs | 1 + tests/xharness/xharness.csproj | 4 +- tools/common/Application.cs | 147 +------ tools/common/Assembly.cs | 377 ++++++++++++------ tools/common/FileCopier.cs | 179 +++++++++ .../common}/PListExtensions.cs | 2 +- tools/common/Target.cs | 10 +- tools/mmp/driver.cs | 2 +- tools/mmp/mmp.csproj | 6 + tools/mtouch/mtouch.csproj | 6 + 42 files changed, 1205 insertions(+), 424 deletions(-) create mode 100644 msbuild/Xamarin.Mac.Tasks/Tasks/CreateBindingResourcePackage.cs create mode 100644 msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CreateBindingResourcePackageBase.cs create mode 100644 msbuild/Xamarin.Shared/Xamarin.Shared.targets create mode 100644 msbuild/Xamarin.iOS.Tasks/Tasks/CreateBindingResourcePackage.cs delete mode 100644 msbuild/tests/MyiOSFrameworkBinding/ApiDefinition.cs delete mode 100644 msbuild/tests/MyiOSFrameworkBinding/StructsAndEnums.cs create mode 100644 msbuild/tests/Xamarin.iOS.Tasks.Tests/ProjectsTests/NativeReferencesNoEmbedding.cs create mode 100644 tests/mmptest/src/BindingProjectNoEmbeddingTests.cs create mode 100644 tools/common/FileCopier.cs rename {tests/xharness => tools/common}/PListExtensions.cs (99%) diff --git a/msbuild/Makefile b/msbuild/Makefile index 237e3c4598..5173b89796 100644 --- a/msbuild/Makefile +++ b/msbuild/Makefile @@ -31,6 +31,7 @@ IOS_TARGETS = \ $(wildcard Xamarin.iOS.Tasks.Core/Xamarin.MonoTouch.*.targets) \ $(wildcard Xamarin.iOS.Tasks.Core/Xamarin.iOS.*.props) \ $(wildcard Xamarin.iOS.Tasks.Core/Xamarin.iOS.*.targets) \ + $(wildcard Xamarin.Shared/Xamarin.*.targets) \ IOS_BINDING_TARGETS = $(wildcard Xamarin.ObjcBinding.Tasks/*.targets) @@ -142,7 +143,7 @@ endif ## XM definitions ## -MAC_TARGETS = $(wildcard Xamarin.Mac.Tasks/*.props) $(wildcard Xamarin.Mac.Tasks/*.targets) +MAC_TARGETS = $(wildcard Xamarin.Mac.Tasks/*.props) $(wildcard Xamarin.Mac.Tasks/*.targets) $(wildcard Xamarin.Shared/Xamarin.*.targets) MAC_BINDING_TARGETS = MAC_TASK_ASSEMBLIES = Xamarin.Mac.Tasks @@ -216,6 +217,9 @@ $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/msbuild/iOS/%: Xamarin.ObjcBinding.Tasks/% $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/msbuild/iOS/%: Xamarin.iOS.Tasks.Core/% | $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/msbuild/iOS $(Q) install -m 644 $< $@ +$(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/msbuild/iOS/%: Xamarin.Shared/% | $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/msbuild/iOS + $(Q) install -m 644 $< $@ + $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/msbuild/iOS/%.dll: build/%.dll | $(IOS_DESTDIR)$(MONOTOUCH_PREFIX)/lib/msbuild/iOS $(Q) install -m 644 $< $@ @@ -283,6 +287,9 @@ $(MAC_DESTDIR)$(MAC_FRAMEWORK_CURRENT_DIR)/etc/mono/4.5/machine.config: $(TOP)/t $(MAC_DESTDIR)$(MAC_FRAMEWORK_CURRENT_DIR)/lib/msbuild/%: Xamarin.Mac.Tasks/% | $(MAC_DESTDIR)$(MAC_FRAMEWORK_CURRENT_DIR)/lib/msbuild $(Q) install -m 644 $< $@ +$(MAC_DESTDIR)$(MAC_FRAMEWORK_CURRENT_DIR)/lib/msbuild/%: Xamarin.Shared/% | $(MAC_DESTDIR)$(MAC_FRAMEWORK_CURRENT_DIR)/lib/msbuild + $(Q) install -m 644 $< $@ + $(MAC_DESTDIR)$(MAC_FRAMEWORK_CURRENT_DIR)/lib/msbuild/%.dll: build/%.dll | $(MAC_DESTDIR)$(MAC_FRAMEWORK_CURRENT_DIR)/lib/msbuild $(Q) install -m 644 $< $@ diff --git a/msbuild/Xamarin.Mac.Tasks/Tasks/CreateBindingResourcePackage.cs b/msbuild/Xamarin.Mac.Tasks/Tasks/CreateBindingResourcePackage.cs new file mode 100644 index 0000000000..626b139c2f --- /dev/null +++ b/msbuild/Xamarin.Mac.Tasks/Tasks/CreateBindingResourcePackage.cs @@ -0,0 +1,16 @@ +using System; +using System.IO; +using System.Linq; +using System.Collections.Generic; +using System.Text; + +using Xamarin.MacDev.Tasks; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Xamarin.Mac.Tasks +{ + public class CreateBindingResourcePackage : CreateBindingResourcePackageBase + { + } +} diff --git a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Common.targets b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Common.targets index a0f64fef19..47ef1410ba 100644 --- a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Common.targets +++ b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Common.targets @@ -61,6 +61,8 @@ Copyright (C) 2014 Xamarin. All rights reserved. + + @@ -482,9 +484,21 @@ Copyright (C) 2014 Xamarin. All rights reserved. IsAppExtension="$(IsAppExtension)" PartialAppManifests="@(_PartialAppManifest)" /> + + + + _DetectAppManifest; + _DetectSdkLocations; + _GenerateBundleName; + ResolveReferences; + _CompileEntitlements; + _CompileAppManifest; + _ExpandNativeReferences; + + - diff --git a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.ObjCBinding.CSharp.targets b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.ObjCBinding.CSharp.targets index f51f26bafd..b17349586c 100644 --- a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.ObjCBinding.CSharp.targets +++ b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.ObjCBinding.CSharp.targets @@ -16,6 +16,7 @@ Copyright (C) 2014 Xamarin Inc. All rights reserved. + @@ -56,15 +57,18 @@ Copyright (C) 2014 Xamarin Inc. All rights reserved. + + <_GeneratedSourcesFileList>$(GeneratedSourcesDir)sources.list - + _GenerateBindings; _PrepareNativeReferences; _CollectGeneratedSources; $(CompileDependsOn) + _CreateBindingResourcePackage; @@ -119,8 +123,8 @@ Copyright (C) 2014 Xamarin Inc. All rights reserved. IntermediateOutputPath="$(IntermediateOutputPath)" NativeReferences="@(NativeReference)" > - - + + diff --git a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj index db34a0e1d5..ec7707450e 100644 --- a/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj +++ b/msbuild/Xamarin.Mac.Tasks/Xamarin.Mac.Tasks.csproj @@ -31,6 +31,7 @@ + @@ -118,6 +119,9 @@ PreserveNewest + + PreserveNewest + diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CreateBindingResourcePackageBase.cs b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CreateBindingResourcePackageBase.cs new file mode 100644 index 0000000000..cad82bc9b2 --- /dev/null +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Tasks/CreateBindingResourcePackageBase.cs @@ -0,0 +1,83 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Xml; + +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Xamarin.MacDev.Tasks { + public abstract class CreateBindingResourcePackageBase : Task { + public string SessionId { get; set; } + + [Required] + public string OutputPath { get; set; } + + [Required] + public ITaskItem[] NativeReferences { get; set; } + + [Required] + public string ProjectDir { get; set; } + + [Required] + public string BindingAssembly { get; set; } + + [Output] + public ITaskItem Manifest { get; set; } + + public override bool Execute () + { + // LinkWith must be migrated for NoBindingEmbedding styled binding projects + if (NativeReferences.Length == 0) { + Log.LogError (7068, null, $"Can't create a binding resource package unless there are native references in the binding project."); + return false; + } + + string bindingResourcePath = Path.Combine (ProjectDir, OutputPath, Path.ChangeExtension (Path.GetFileName (BindingAssembly), ".resources")); + Log.LogMessage ($"Creating binding resource package: {bindingResourcePath}"); + + Directory.CreateDirectory (bindingResourcePath); + foreach (var nativeRef in NativeReferences) + Xamarin.Bundler.FileCopier.UpdateDirectory (nativeRef.ItemSpec, bindingResourcePath); + + string manifestPath = CreateManifest (bindingResourcePath); + + Manifest = new TaskItem ("Manifest") { ItemSpec = manifestPath }; + + return true; + } + + string [] NativeReferenceAttributeNames = new string [] { "Kind", "ForceLoad", "SmartLink", "Frameworks", "WeakFrameworks", "LinkerFlags", "NeedsGccExceptionHandling", "IsCxx"}; + + string CreateManifest (string resourcePath) + { + XmlWriterSettings settings = new XmlWriterSettings() { + OmitXmlDeclaration = true, + Indent = true, + IndentChars = "\t", + }; + + string manifestPath = Path.Combine (resourcePath, "manifest"); + using (var writer = XmlWriter.Create (manifestPath, settings)) { + writer.WriteStartElement ("BindingAssembly"); + + foreach (var nativeRef in NativeReferences) { + writer.WriteStartElement ("NativeReference"); + writer.WriteAttributeString ("Name", Path.GetFileName (nativeRef.ItemSpec)); + + foreach (string attribute in NativeReferenceAttributeNames) { + writer.WriteStartElement (attribute); + writer.WriteString (nativeRef.GetMetadata (attribute)); + writer.WriteEndElement (); + } + + writer.WriteEndElement (); + } + writer.WriteEndElement (); + } + return manifestPath; + } + } +} diff --git a/msbuild/Xamarin.MacDev.Tasks.Core/Xamarin.MacDev.Tasks.Core.csproj b/msbuild/Xamarin.MacDev.Tasks.Core/Xamarin.MacDev.Tasks.Core.csproj index 8b8c6b2e29..d8bf318ffa 100644 --- a/msbuild/Xamarin.MacDev.Tasks.Core/Xamarin.MacDev.Tasks.Core.csproj +++ b/msbuild/Xamarin.MacDev.Tasks.Core/Xamarin.MacDev.Tasks.Core.csproj @@ -67,6 +67,7 @@ + @@ -116,6 +117,7 @@ + diff --git a/msbuild/Xamarin.Shared/Xamarin.Shared.targets b/msbuild/Xamarin.Shared/Xamarin.Shared.targets new file mode 100644 index 0000000000..a6ff73157b --- /dev/null +++ b/msbuild/Xamarin.Shared/Xamarin.Shared.targets @@ -0,0 +1,66 @@ + + + + + + + + + + + <_FrameworkNativeReference Include="@(NativeReference -> '%(Identity)/%(Filename)')" Condition="'%(Extension)' == '.framework'" /> + <_FileNativeReference Include="@(NativeReference)" Condition="'%(Extension)' != '.framework'" /> + + + + + $(ProjectDir)$(OutputPath)$(AssemblyName).resources + + + + + + + + + + + + $(CleanDependsOn); + _CleanBindingResourcePackage + + + + + + + + + diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets index 247dcef7f8..a4a78d3dad 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets +++ b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Common.targets @@ -102,6 +102,8 @@ Copyright (C) 2013-2016 Xamarin. All rights reserved. + + + _GenerateBindings; _PrepareNativeReferences; _CollectGeneratedSources; $(CompileDependsOn) + _CreateBindingResourcePackage; @@ -87,8 +90,8 @@ Copyright (C) 2013-2016 Xamarin Inc. All rights reserved. SessionId="$(BuildSessionId)" IntermediateOutputPath="$(IntermediateOutputPath)" NativeReferences="@(NativeReference)"> - - + + diff --git a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Tasks.Core.csproj b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Tasks.Core.csproj index 45fc042c95..d096a2985b 100644 --- a/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Tasks.Core.csproj +++ b/msbuild/Xamarin.iOS.Tasks.Core/Xamarin.iOS.Tasks.Core.csproj @@ -214,5 +214,8 @@ PreserveNewest + + PreserveNewest + diff --git a/msbuild/Xamarin.iOS.Tasks/Tasks/CreateBindingResourcePackage.cs b/msbuild/Xamarin.iOS.Tasks/Tasks/CreateBindingResourcePackage.cs new file mode 100644 index 0000000000..879c709293 --- /dev/null +++ b/msbuild/Xamarin.iOS.Tasks/Tasks/CreateBindingResourcePackage.cs @@ -0,0 +1,16 @@ +using System; +using System.IO; +using System.Linq; +using System.Collections.Generic; +using System.Text; + +using Xamarin.MacDev.Tasks; +using Microsoft.Build.Framework; +using Microsoft.Build.Utilities; + +namespace Xamarin.iOS.Tasks +{ + public class CreateBindingResourcePackage : CreateBindingResourcePackageBase + { + } +} diff --git a/msbuild/Xamarin.iOS.Tasks/Xamarin.iOS.Tasks.csproj b/msbuild/Xamarin.iOS.Tasks/Xamarin.iOS.Tasks.csproj index fb7b1341be..56c112cb46 100644 --- a/msbuild/Xamarin.iOS.Tasks/Xamarin.iOS.Tasks.csproj +++ b/msbuild/Xamarin.iOS.Tasks/Xamarin.iOS.Tasks.csproj @@ -74,6 +74,7 @@ + diff --git a/msbuild/tests/MyiOSFrameworkBinding/ApiDefinition.cs b/msbuild/tests/MyiOSFrameworkBinding/ApiDefinition.cs deleted file mode 100644 index 2ba034dcd2..0000000000 --- a/msbuild/tests/MyiOSFrameworkBinding/ApiDefinition.cs +++ /dev/null @@ -1,67 +0,0 @@ -using System; - -using UIKit; -using Foundation; -using ObjCRuntime; -using CoreGraphics; - -namespace MyiOSBinding -{ - // The first step to creating a binding is to add your native library ("libNativeLibrary.a") - // to the project by right-clicking (or Control-clicking) the folder containing this source - // file and clicking "Add files..." and then simply select the native library (or libraries) - // that you want to bind. - // - // When you do that, you'll notice that MonoDevelop generates a code-behind file for each - // native library which will contain a [LinkWith] attribute. MonoDevelop auto-detects the - // architectures that the native library supports and fills in that information for you, - // however, it cannot auto-detect any Frameworks or other system libraries that the - // native library may depend on, so you'll need to fill in that information yourself. - // - // Once you've done that, you're ready to move on to binding the API... - // - // - // Here is where you'd define your API definition for the native Objective-C library. - // - // For example, to bind the following Objective-C class: - // - // @interface Widget : NSObject { - // } - // - // The C# binding would look like this: - // - // [BaseType (typeof (NSObject))] - // interface Widget { - // } - // - // To bind Objective-C properties, such as: - // - // @property (nonatomic, readwrite, assign) CGPoint center; - // - // You would add a property definition in the C# interface like so: - // - // [Export ("center")] - // CGPoint Center { get; set; } - // - // To bind an Objective-C method, such as: - // - // -(void) doSomething:(NSObject *)object atIndex:(NSInteger)index; - // - // You would add a method definition to the C# interface like so: - // - // [Export ("doSomething:atIndex:")] - // void DoSomething (NSObject object, int index); - // - // Objective-C "constructors" such as: - // - // -(id)initWithElmo:(ElmoMuppet *)elmo; - // - // Can be bound as: - // - // [Export ("initWithElmo:")] - // IntPtr Constructor (ElmoMuppet elmo); - // - // For more information, see http://developer.xamarin.com/guides/ios/advanced_topics/binding_objective-c/ - // -} - diff --git a/msbuild/tests/MyiOSFrameworkBinding/StructsAndEnums.cs b/msbuild/tests/MyiOSFrameworkBinding/StructsAndEnums.cs deleted file mode 100644 index 5b8cc52c0f..0000000000 --- a/msbuild/tests/MyiOSFrameworkBinding/StructsAndEnums.cs +++ /dev/null @@ -1,6 +0,0 @@ -using System; - -namespace MyiOSBinding -{ -} - diff --git a/msbuild/tests/Xamarin.iOS.Tasks.Tests/ProjectsTests/NativeReferencesNoEmbedding.cs b/msbuild/tests/Xamarin.iOS.Tasks.Tests/ProjectsTests/NativeReferencesNoEmbedding.cs new file mode 100644 index 0000000000..56eaadae1c --- /dev/null +++ b/msbuild/tests/Xamarin.iOS.Tasks.Tests/ProjectsTests/NativeReferencesNoEmbedding.cs @@ -0,0 +1,159 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using NUnit.Framework; +using Xamarin.Tests; +using Xamarin.Utils; + +namespace Xamarin.iOS.Tasks +{ + [TestFixture ("iPhone")] + [TestFixture ("iPhoneSimulator")] + public class NativeReferencesNoEmbedding : ProjectTest { + + public NativeReferencesNoEmbedding (string platform) : base (platform) + { + } + + void SetNoBindingEmbedding () + { + // TODO - This is a hack. We should be setting it only on the binding project, but + // the iOS msbuild test system doesn't have an easy way to access since it's just a project reference + // and not loaded up here... + Engine.ProjectCollection.SetGlobalProperty ("NoBindingEmbedding", "true"); + } + + void BuildProjectNoEmbedding (ProjectPaths project, bool clean = true) + { + Engine.ProjectCollection.SetGlobalProperty ("Platform", Platform); + var proj = SetupProject (Engine, project.ProjectCSProjPath); + + SetNoBindingEmbedding (); + + if (clean) + RunTarget (proj, "Clean", 0); + RunTarget (proj, "Build", 0); + } + + string GetMessages () => string.Join ("\n", Engine.Logger.MessageEvents.Select (x => x.Message)); + + void ClearMessages () => Engine.Logger.MessageEvents.Clear (); + + // [TestCase (true)] MISSING_TEST - Tests are framework only + // [TestCase (false)] MISSING_TEST - Also, project reference only + public void LibrariesEmbeddedProperly (bool useProjectReference) + { + Assert.Fail (); + } + + // [TestCase (false)] MISSING_TEST - Project reference only + [TestCase (true)] + public void FrameworksEmbeddedProperly (bool useProjectReference) + { + // TODO - Checked in projects are project reference only... + Assert.True (useProjectReference); + + var bindingApp = SetupProjectPaths ("MyiOSAppWithBinding", "../", true, Platform); + + BuildProjectNoEmbedding (bindingApp); + + string libPath = Path.Combine (Directory.GetCurrentDirectory (), bindingApp.ProjectBinPath, "MyiOSBinding.dll"); + Assert.True (File.Exists (libPath), $"Did not find expected library: {libPath}"); + + int returnValue = ExecutionHelper.Execute ("/Library/Frameworks/Mono.framework/Commands/monodis", "--presources " + libPath, out string monoDisResults); + Assert.AreEqual (0, returnValue); + Assert.IsFalse (monoDisResults.Contains ("XTest.framework"), $"Binding Library contained embedded resource: {monoDisResults}"); + + string finalFrameworkPath = Path.Combine (bindingApp.AppBundlePath, "Frameworks/XTest.framework/XTest"); + Assert.True (File.Exists (finalFrameworkPath), $"{finalFrameworkPath} file was not part of bundle?"); + } + + // [Test] MISSING_TEST - No LinkWith only projects + public void DoesNotSupportLinkWith () + { + Assert.Fail (); + } + + [TestCase (true)] + // [TestCase (false)] MISSING_TEST - Framework only tests + public void ShouldNotUnnecessarilyRebuildBindingProject (bool framework) + { + Assert.True (framework); + + var bindingLib = SetupProjectPaths ("MyiOSFrameworkBinding", "../", true, ""); + + const string CreatePackageString = "Creating binding resource package"; + + // First build should create a package + BuildProjectNoEmbedding (bindingLib); + Assert.True (GetMessages ().Contains (CreatePackageString), "First build did not create package?"); + ClearMessages (); + + // No change build should not + BuildProjectNoEmbedding (bindingLib, clean : false); + Assert.False (GetMessages ().Contains (CreatePackageString), "Rebuild build did create package?"); + ClearMessages (); + + // Touching the binding project should + Touch (bindingLib.ProjectCSProjPath); + BuildProjectNoEmbedding (bindingLib, clean: false); + Assert.True (GetMessages ().Contains (CreatePackageString), "Bindng project build did not create package?"); + ClearMessages (); + + // Touching the binding file should + Touch (Path.Combine (Path.GetDirectoryName (bindingLib.ProjectCSProjPath), @"../../../tests/bindings-framework-test/ApiDefinition.cs")); + BuildProjectNoEmbedding (bindingLib, clean: false); + Assert.True (GetMessages ().Contains (CreatePackageString), "Bindng file build did not create package?"); + ClearMessages (); + + // No change build should not + BuildProjectNoEmbedding (bindingLib, clean: false); + Assert.False (GetMessages ().Contains (CreatePackageString), "Second rebuild build did create package?"); + ClearMessages (); + + // Touching native library should + Touch (Path.Combine (Path.GetDirectoryName (bindingLib.ProjectCSProjPath), @"../../../tests/test-libraries/.libs/ios/XTest.framework/XTest")); + BuildProjectNoEmbedding (bindingLib, clean: false); + Assert.True (GetMessages ().Contains (CreatePackageString), "Bindng build did not create package?"); + } + + [TestCase (true)] + // [TestCase (false)] MISSING_TEST - Project reference only + public void ShouldNotUnnecessarilyRebuildFinalProject (bool useProjectReference) + { + Assert.True (useProjectReference); + + var appProject = SetupProjectPaths ("MyiOSAppWithBinding", "../", true, ""); + + const string BuildString = "/Library/Frameworks/Xamarin.iOS.framework/Versions/Current/bin/mtouch"; + + // First build should create run mtouch + BuildProjectNoEmbedding (appProject); + Assert.True (GetMessages ().Contains (BuildString), "First build did not run mtouch?"); + ClearMessages (); + + // But not a rebuild + BuildProjectNoEmbedding (appProject, clean: false); + Assert.False (GetMessages ().Contains (BuildString), "Rebuild build did run mtouch?"); + ClearMessages (); + + if (!useProjectReference) { + Assert.Fail (); // TODO - Checked in projects are project reference only... + } else { + var libProject = SetupProjectPaths ("MyiOSFrameworkBinding", "../", true, ""); + + Touch (libProject.ProjectCSProjPath); + BuildProjectNoEmbedding (appProject, clean: false); + Assert.True (GetMessages ().Contains (BuildString), "Binding binary build did not run mtouch?"); + } + } + + // [TestCase (true)] - MISSING_TEST - Requires special "chain" project that is not checked in + // [TestCase (false)] - MISSING_TEST - Requires special "chain" project that is not checked in + public void MultipleDependencyChain (bool useProjectReference) + { + Assert.Fail (); + } + } +} diff --git a/msbuild/tests/Xamarin.iOS.Tasks.Tests/TestHelpers/TestBase.cs b/msbuild/tests/Xamarin.iOS.Tasks.Tests/TestHelpers/TestBase.cs index a60405e8d2..1b3db17228 100644 --- a/msbuild/tests/Xamarin.iOS.Tasks.Tests/TestHelpers/TestBase.cs +++ b/msbuild/tests/Xamarin.iOS.Tasks.Tests/TestHelpers/TestBase.cs @@ -331,8 +331,7 @@ namespace Xamarin.iOS.Tasks { if (!File.Exists (file)) Assert.Fail ("Expected file '{0}' did not exist", file); - File.SetLastWriteTimeUtc (file, DateTime.UtcNow.AddDays (1)); - System.Threading.Thread.Sleep (1000); + File.SetLastWriteTimeUtc (file, DateTime.UtcNow); } public void RunTarget (Project project, string target, int expectedErrorCount = 0) diff --git a/msbuild/tests/Xamarin.iOS.Tasks.Tests/Xamarin.iOS.Tasks.Tests.csproj b/msbuild/tests/Xamarin.iOS.Tasks.Tests/Xamarin.iOS.Tasks.Tests.csproj index f2868ba734..a3f315a2e7 100644 --- a/msbuild/tests/Xamarin.iOS.Tasks.Tests/Xamarin.iOS.Tasks.Tests.csproj +++ b/msbuild/tests/Xamarin.iOS.Tasks.Tests/Xamarin.iOS.Tasks.Tests.csproj @@ -110,6 +110,7 @@ + diff --git a/tests/common/mac/ProjectTestHelpers.cs b/tests/common/mac/ProjectTestHelpers.cs index 6148c8e5fe..2f13954510 100644 --- a/tests/common/mac/ProjectTestHelpers.cs +++ b/tests/common/mac/ProjectTestHelpers.cs @@ -159,6 +159,7 @@ namespace Xamarin.MMP.Tests // Binding project specific public string APIDefinitionConfig { get; set; } public string StructsAndEnumsConfig { get; set; } + public string LinkWithName { get; set; } = null; // Only generates if non-null // Unified Executable Specific public bool AssetIcons { get; set; } @@ -204,21 +205,28 @@ namespace Xamarin.MMP.Tests { StringBuilder output = new StringBuilder (); Environment.SetEnvironmentVariable ("MONO_PATH", null); - int compileResult = Xamarin.Bundler.Driver.RunCommand (exe, args != null ? args.ToString() : string.Empty, environment, output, suppressPrintOnErrors: shouldFail); + int compileResult = Xamarin.Bundler.Driver.RunCommand (exe, args != null ? args.ToString () : string.Empty, environment, output, suppressPrintOnErrors: shouldFail); if (!shouldFail && compileResult != 0 && Xamarin.Bundler.Driver.Verbosity < 1) { - // Driver.RunCommand won't print failed output unless verbosity > 0, so let's do it ourselves. Console.WriteLine ($"Execution failed; exit code: {compileResult}"); - Console.WriteLine (output); } - Func getInfo = () => getAdditionalFailInfo != null ? getAdditionalFailInfo() : ""; - if (!shouldFail) - Assert.AreEqual (0, compileResult, stepName + " failed:\n\n'" + output + "' " + exe + " " + args + getInfo ()); - else - Assert.AreNotEqual (0, compileResult, stepName + " did not fail as expected:\n\n'" + output + "' " + exe + " " + args + getInfo ()); - + Func getInfo = () => getAdditionalFailInfo != null ? getAdditionalFailInfo () : ""; + bool passed = shouldFail ? compileResult != 0 : compileResult == 0; + if (!passed) { + string outputLine = PrintRedirectIfLong ($"{exe}{args} Output: {output} {getInfo ()}"); + Assert.Fail ($@"{stepName} {(shouldFail ? "passed" : "failed")} unexpectedly: {outputLine}"); + } return output.ToString (); } + public static string PrintRedirectIfLong (string outputLine) + { + if (outputLine.Length > 5000) { + Console.WriteLine (outputLine); + outputLine = "(Additional info redirected to console)"; + } + return outputLine; + } + public static string RunAndAssert (string exe, StringBuilder args, string stepName, bool shouldFail = false, Func getAdditionalFailInfo = null, string[] environment = null) { return RunAndAssert (exe, args.ToString (), stepName, shouldFail, getAdditionalFailInfo, environment); @@ -342,7 +350,19 @@ namespace Xamarin.MMP.Tests CopyFileWithSubstitutions (Path.Combine (sourceDir, "ApiDefinition.cs"), Path.Combine (config.TmpDir, "ApiDefinition.cs"), text => text.Replace ("%CODE%", config.APIDefinitionConfig)); CopyFileWithSubstitutions (Path.Combine (sourceDir, "StructsAndEnums.cs"), Path.Combine (config.TmpDir, "StructsAndEnums.cs"), text => text.Replace ("%CODE%", config.StructsAndEnumsConfig)); + string linkWithName = null; + if (config.LinkWithName != null) { + string fileName = Path.GetFileNameWithoutExtension (config.LinkWithName); + linkWithName = $"{fileName}.linkwith.cs"; + File.WriteAllText (Path.Combine (config.TmpDir, linkWithName), $@"using ObjCRuntime; + +[assembly: LinkWith (""{config.LinkWithName}"", SmartLink = true, ForceLoad = true)]"); + + } + return CopyFileWithSubstitutions (Path.Combine (sourceDir, config.ProjectName), Path.Combine (config.TmpDir, config.ProjectName), text => { + if (linkWithName != null) + text = text.Replace ("%ITEMGROUP%", $@"%ITEMGROUP%"); return ProjectTextReplacement (config, text); }); } diff --git a/tests/mmptest/mmptest.csproj b/tests/mmptest/mmptest.csproj index 16d0f58ac2..09fe2649b5 100644 --- a/tests/mmptest/mmptest.csproj +++ b/tests/mmptest/mmptest.csproj @@ -111,6 +111,7 @@ + SdkVersions.cs diff --git a/tests/mmptest/src/BindingProjectNoEmbeddingTests.cs b/tests/mmptest/src/BindingProjectNoEmbeddingTests.cs new file mode 100644 index 0000000000..b48f57fb62 --- /dev/null +++ b/tests/mmptest/src/BindingProjectNoEmbeddingTests.cs @@ -0,0 +1,249 @@ +using System; +using System.IO; +using System.Linq; +using System.Collections.Generic; +using System.Text; +using NUnit.Framework; +using Xamarin.Utils; + +namespace Xamarin.MMP.Tests +{ + public class BindingProjectNoEmbeddingTests + { + static void Touch (string projectPath) => File.SetLastWriteTimeUtc (projectPath, DateTime.UtcNow); + + static void AssertNoResourceWithName (string tmpDir, string projectName, string resourceName) + { + string bindingName = BindingProjectTests.RemoveCSProj (projectName); + string bindingLibraryPath = Path.Combine (tmpDir, $"bin/Debug/{bindingName}.dll"); + string resourceOutput = TI.RunAndAssert ("/Library/Frameworks/Mono.framework/Commands/monodis", "--presources " + bindingLibraryPath, "monodis"); + Assert.False (resourceOutput.Contains (resourceName), "Binding project output contained embedded library"); + } + + static void AssertFileInBundle (string tmpDir, BindingProjectType type, string path, bool assertIsSymLink = false) + { + string bundlePath = Path.Combine (tmpDir, $"bin/Debug/{(type == BindingProjectType.Modern ? "UnifiedExample" : "XM45Example")}.app/Contents/{path}"); + Assert.True (File.Exists (bundlePath), $"{path} not in bundle as expected."); + if (assertIsSymLink) + Assert.True (File.GetAttributes (bundlePath).HasFlag (FileAttributes.ReparsePoint)); + } + + [TestCase (BindingProjectType.Modern, false)] + [TestCase (BindingProjectType.Full, true)] + public void LibrariesEmbeddedProperly (BindingProjectType type, bool useProjectReference) + { + MMPTests.RunMMPTest (tmpDir => { + var projects = BindingProjectTests.GenerateTestProject (type, tmpDir); + BindingProjectTests.SetNoEmbedding (projects.Item1); + + string appBuildLog = BindingProjectTests.SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference, setupDefaultNativeReference: true).Item2; + + AssertNoResourceWithName (tmpDir, projects.Item1.ProjectName, "SimpleClassDylib.dylib"); + AssertFileInBundle (tmpDir, type, "MonoBundle/SimpleClassDylib.dylib"); + }); + } + + [TestCase (BindingProjectType.Modern, true)] + [TestCase (BindingProjectType.Full, false)] + public void FrameworksEmbeddedProperly (BindingProjectType type, bool useProjectReference) + { + MMPTests.RunMMPTest (tmpDir => { + string frameworkPath = FrameworkBuilder.CreateThinFramework (tmpDir); + + var projects = BindingProjectTests.GenerateTestProject (type, tmpDir); + BindingProjectTests.SetNoEmbedding (projects.Item1); + projects.Item1.ItemGroup = NativeReferenceTests.CreateSingleNativeRef (frameworkPath, "Framework"); + + string appBuildLog = BindingProjectTests.SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference, false).Item2; + + AssertNoResourceWithName (tmpDir, projects.Item1.ProjectName, "Foo"); + AssertFileInBundle (tmpDir, type, "Frameworks/Foo.framework/Foo", assertIsSymLink: true); + }); + } + + [TestCase (BindingProjectType.Modern)] + public void DoesNotSupportLinkWith (BindingProjectType type) + { + MMPTests.RunMMPTest (tmpDir => { + var projects = BindingProjectTests.GenerateTestProject (type, tmpDir); + BindingProjectTests.SetNoEmbedding (projects.Item1); + + projects.Item1.LinkWithName = "SimpleClassDylib.dylib"; + + string libBuildLog = BindingProjectTests.SetupAndBuildBindingProject (projects.Item1, false, shouldFail: true); + Assert.True (libBuildLog.Contains ("Can't create a binding resource package unless there are native references in the binding project."), $"Did not fail as expected: {TI.PrintRedirectIfLong (libBuildLog)}"); + }); + } + + [TestCase (true)] + [TestCase (false)] + public void ShouldNotUnnecessarilyRebuildBindingProject (bool framework) + { + MMPTests.RunMMPTest (tmpDir => { + var projects = BindingProjectTests.GenerateTestProject (BindingProjectType.Modern, tmpDir); + BindingProjectTests.SetNoEmbedding (projects.Item1); + + string projectPath = Path.Combine (tmpDir, "MobileBinding.csproj"); + string bindingFilePath = Path.Combine (tmpDir, "ApiDefinition.cs"); + const string CreatePackageString = "Creating binding resource package"; + + // First build should create a package + string frameworkPath = null; + + if (framework) { + frameworkPath = FrameworkBuilder.CreateThinFramework (tmpDir); + projects.Item1.ItemGroup += NativeReferenceTests.CreateSingleNativeRef (Path.GetFullPath (frameworkPath), "Framework"); + } + string libBuildLog = BindingProjectTests.SetupAndBuildBindingProject (projects.Item1, setupDefaultNativeReference: !framework); + + Assert.True (libBuildLog.Contains (CreatePackageString), $"First build did not create package? {TI.PrintRedirectIfLong (libBuildLog)}"); + + // No change build should not + libBuildLog = TI.BuildProject (projectPath, true); + Assert.False (libBuildLog.Contains (CreatePackageString), $"Rebuild build did create package? {TI.PrintRedirectIfLong (libBuildLog)}"); + + // Touching the binding project should + Touch (projectPath); + libBuildLog = TI.BuildProject (projectPath, true); + Assert.True (libBuildLog.Contains (CreatePackageString), $"Binding Project build did not create package? {TI.PrintRedirectIfLong (libBuildLog)}"); + + // Touching the binding file should + Touch (bindingFilePath); + libBuildLog = TI.BuildProject (projectPath, true); + Assert.True (libBuildLog.Contains (CreatePackageString), $"Binding File build did not create package? {TI.PrintRedirectIfLong (libBuildLog)}"); + + // No change build should not + libBuildLog = TI.BuildProject (projectPath, true); + Assert.False (libBuildLog.Contains (CreatePackageString), $"Second Rebuild build did create package? {TI.PrintRedirectIfLong (libBuildLog)}"); + + // Touching native library should + Touch (framework ? frameworkPath + "/Foo" : NativeReferenceTests.SimpleDylibPath); + libBuildLog = TI.BuildProject (projectPath, true); + Assert.True (libBuildLog.Contains (CreatePackageString), $"Native Library build did not create package? {TI.PrintRedirectIfLong (libBuildLog)}"); + }); + } + + [TestCase (true, true)] + [TestCase (true, false)] + [TestCase (false, true)] + [TestCase (false, false)] + public void ShouldNotUnnecessarilyRebuildFinalProject (bool useProjectReference, bool framework) + { + MMPTests.RunMMPTest (tmpDir => { + var projects = BindingProjectTests.GenerateTestProject (BindingProjectType.Modern, tmpDir); + BindingProjectTests.SetNoEmbedding (projects.Item1); + + const string BuildString = "xcrun -sdk macosx clang"; + + string frameworkPath = null; + if (framework) { + frameworkPath = FrameworkBuilder.CreateThinFramework (tmpDir); + projects.Item1.ItemGroup += NativeReferenceTests.CreateSingleNativeRef (Path.GetFullPath (frameworkPath), "Framework"); + } + string appBuildLog = BindingProjectTests.SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference, setupDefaultNativeReference: !framework).Item2; + + Assert.True (appBuildLog.Contains (BuildString), $"First build did not run mmp? {TI.PrintRedirectIfLong (appBuildLog)}"); + + string projectPath = Path.Combine (tmpDir, "UnifiedExample.csproj"); + string mainPath = Path.Combine (tmpDir, "Main.cs"); + + // No change build should not + string buildLog = TI.BuildProject (projectPath, true); + Assert.False (buildLog.Contains (BuildString), $"Rebuild ran mmp again? {TI.PrintRedirectIfLong (buildLog)}"); + + if (useProjectReference) { + // Touching the binding definition should + Touch (Path.Combine (tmpDir, "ApiDefinition.cs")); + buildLog = TI.BuildProject (projectPath, true); + Assert.True (buildLog.Contains (BuildString), $"Binding definition build did not run mmp again? {TI.PrintRedirectIfLong (buildLog)}"); + } + else { + // Touching the binding assembly should + Touch (Path.Combine (tmpDir, "bin/Debug/MobileBinding.dll")); + buildLog = TI.BuildProject (projectPath, true); + Assert.True (buildLog.Contains (BuildString), $"Binding build did not run mmp again? {TI.PrintRedirectIfLong (buildLog)}"); + } + }); + } + + [TestCase (true)] + [TestCase (false)] + public void MultipleNativeReferences (bool useProjectReference) + { + MMPTests.RunMMPTest (tmpDir => { + // This is a bit of a hack, you can't just rename dylibs like this + string secondNativeLibPath = Path.Combine (tmpDir, "SimpleClassDylib2.dylib"); + File.Copy (NativeReferenceTests.SimpleDylibPath, secondNativeLibPath); + + var projects = BindingProjectTests.GenerateTestProject (BindingProjectType.Modern, tmpDir); + BindingProjectTests.SetNoEmbedding (projects.Item1); + projects.Item1.ItemGroup += NativeReferenceTests.CreateSingleNativeRef (secondNativeLibPath, "Dynamic"); + + BindingProjectTests.SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference, setupDefaultNativeReference: true); + + // manifest and 2 dylibs + Assert.AreEqual (3, Directory.GetFiles (Path.Combine (tmpDir, "bin/Debug/MobileBinding.resources")).Length); + + // 2 dylibs + libMonoPosixHelper.dylib + Assert.AreEqual (3, Directory.GetFiles (Path.Combine (tmpDir, "bin/Debug/UnifiedExample.app/Contents/MonoBundle")).Where (x => x.EndsWith (".dylib")).Count ()); + }); + } + + [TestCase (true)] + [TestCase (false)] + public void MultipleDependencyChain (bool useProjectReference) + { + // App can depend on Lib that depends on binding lib with native reference and everything gets packaged in correctly + MMPTests.RunMMPTest (tmpDir => { + TI.UnifiedTestConfig binding = new TI.UnifiedTestConfig (tmpDir) { ProjectName = "MobileBinding.csproj" }; + binding.ItemGroup += NativeReferenceTests.CreateSingleNativeRef (NativeReferenceTests.SimpleDylibPath, "Dynamic"); + binding.APIDefinitionConfig += @"[BaseType (typeof (NSObject))] + interface SimpleClass { + [Export (""doIt"")] + int DoIt (); + }"; + BindingProjectTests.SetNoEmbedding (binding); + + TI.GenerateBindingLibraryProject (binding); + TI.BuildProject (Path.Combine (tmpDir, "MobileBinding.csproj"), true); + + + TI.UnifiedTestConfig library = new TI.UnifiedTestConfig (tmpDir) { ProjectName = "UnifiedLibrary" }; + library.TestCode = "public class MyClass { public static void Go () { var c = new ExampleBinding.SimpleClass (); c.DoIt (); } }"; + + if (useProjectReference) + library.References = $@""; + else + library.References = $@"{Path.Combine (tmpDir, "bin/Debug", "MobileBinding.dll")}"; + + TI.GenerateUnifiedLibraryProject (library); + TI.BuildProject (Path.Combine (tmpDir, "UnifiedLibrary.csproj"), true); + + TI.UnifiedTestConfig project = new TI.UnifiedTestConfig (tmpDir) { ProjectName = "UnifiedExample.csproj" }; + project.TestCode = "MyClass.Go ();"; + + if (useProjectReference) + project.References = $@""; + else + project.References = $@"{Path.Combine (tmpDir, "bin/Debug", "UnifiedLibrary.dll")}"; + + TI.GenerateUnifiedExecutableProject (project); + TI.BuildProject (Path.Combine (tmpDir, "UnifiedExample.csproj"), true); + }); + } + + [Test] + public void CleanShouldRemoveBundle () + { + MMPTests.RunMMPTest (tmpDir => { + var projects = BindingProjectTests.GenerateTestProject (BindingProjectType.Modern, tmpDir); + BindingProjectTests.SetNoEmbedding (projects.Item1); + + string libBuildLog = BindingProjectTests.SetupAndBuildBindingProject (projects.Item1, true); + + TI.CleanUnifiedProject (Path.Combine (tmpDir, projects.Item1.ProjectName)); + Assert.False (Directory.Exists (Path.Combine (tmpDir, "bin/Debug/MobileBinding.resources")), "Resource bundle was not cleaned up"); + }); + } + } +} diff --git a/tests/mmptest/src/BindingProjectTests.cs b/tests/mmptest/src/BindingProjectTests.cs index 208d877597..33277f555a 100644 --- a/tests/mmptest/src/BindingProjectTests.cs +++ b/tests/mmptest/src/BindingProjectTests.cs @@ -1,27 +1,38 @@ using System; using System.IO; using System.Linq; +using System.Collections.Generic; using System.Text; using NUnit.Framework; using Xamarin.Utils; namespace Xamarin.MMP.Tests { + // There are a mess of different binding project configurations in the wild + public enum BindingProjectType + { + Modern, // The ideal Modern - Sets TargetFrameworkVersion and TargetFrameworkIdentifier correclty + ModernNoTag, // Sets neither TargetFrameworkVersion nor TargetFrameworkIdentifier + Full, // Sets both TargetFrameworkVersion and UseXamMacFullFramework + FullTVF, // Sets just TargetFrameworkVersion to 4.5 or later + FullXamMacTag, // Sets just UseXamMacFullFramework + } + public class BindingProjectTests { - static string RemoveCSProj (string s) => s.Remove (s.IndexOf (".csproj", StringComparison.InvariantCulture)); - - static Tuple BuildLinkedTestProjects (TI.UnifiedTestConfig binding, TI.UnifiedTestConfig project, string tmpDir) - { - binding.ItemGroup = NativeReferenceTests.CreateSingleNativeRef (Path.GetFullPath (NativeReferenceTests.SimpleDylibPath), "Dynamic"); - binding.StructsAndEnumsConfig = "public class UnifiedWithDepNativeRefLibTestClass {}"; + internal static string RemoveCSProj (string s) => s.Remove (s.IndexOf (".csproj", StringComparison.InvariantCulture)); - string projectPath = TI.GenerateBindingLibraryProject (binding); - string bindingBuildLog = TI.BuildProject (projectPath, true); + internal static Tuple SetupAndBuildLinkedTestProjects (TI.UnifiedTestConfig binding, TI.UnifiedTestConfig project, string tmpDir, bool useProjectReference, bool setupDefaultNativeReference) + { + string bindingBuildLog = SetupAndBuildBindingProject (binding, setupDefaultNativeReference); string bindingName = RemoveCSProj (binding.ProjectName); - project.References = string.Format (@"{1}", bindingName, Path.Combine (tmpDir, "bin/Debug", bindingName + ".dll")); + if (useProjectReference) + project.References = $@""; + else + project.References = $@"{Path.Combine (tmpDir, "bin/Debug", bindingName + ".dll")}"; + project.TestCode = "System.Console.WriteLine (typeof (ExampleBinding.UnifiedWithDepNativeRefLibTestClass));"; string appBuildLog = TI.TestUnifiedExecutable (project).BuildOutput; @@ -29,40 +40,42 @@ namespace Xamarin.MMP.Tests return new Tuple (bindingBuildLog, appBuildLog); } - // There are a mess of different binding project configurations in the wild - public enum ProjectType { - Modern, // The ideal Modern - Sets TargetFrameworkVersion and TargetFrameworkIdentifier correclty - ModernNoTag, // Sets neither TargetFrameworkVersion nor TargetFrameworkIdentifier - Full, // Sets both TargetFrameworkVersion and UseXamMacFullFramework - FullTVF, // Sets just TargetFrameworkVersion to 4.5 or later - FullXamMacTag, // Sets just UseXamMacFullFramework + internal static string SetupAndBuildBindingProject (TI.UnifiedTestConfig binding, bool setupDefaultNativeReference, bool shouldFail = false) + { + if (setupDefaultNativeReference) + binding.ItemGroup += NativeReferenceTests.CreateSingleNativeRef (Path.GetFullPath (NativeReferenceTests.SimpleDylibPath), "Dynamic"); + + binding.StructsAndEnumsConfig = "public class UnifiedWithDepNativeRefLibTestClass {}"; + + string projectPath = TI.GenerateBindingLibraryProject (binding); + return TI.BuildProject (projectPath, true, shouldFail: shouldFail); } - Tuple GenerateTestProject (ProjectType type, string tmpDir) + internal static Tuple GenerateTestProject (BindingProjectType type, string tmpDir) { TI.UnifiedTestConfig binding = new TI.UnifiedTestConfig (tmpDir); TI.UnifiedTestConfig project = new TI.UnifiedTestConfig (tmpDir); switch (type) { - case ProjectType.Modern: + case BindingProjectType.Modern: binding.ProjectName = "MobileBinding.csproj"; project.XM45 = false; break; - case ProjectType.ModernNoTag: + case BindingProjectType.ModernNoTag: binding.ProjectName = "BindingProjectWithNoTag.csproj"; project.XM45 = false; break; - case ProjectType.Full: + case BindingProjectType.Full: binding.ProjectName = "XM45Binding.csproj"; binding.CustomProjectReplacement = new Tuple ( "v4.5", "true4.5"); project.XM45 = true; break; - case ProjectType.FullTVF: + case BindingProjectType.FullTVF: binding.ProjectName = "XM45Binding.csproj"; project.XM45 = true; break; - case ProjectType.FullXamMacTag: + case BindingProjectType.FullXamMacTag: binding.ProjectName = "XM45Binding.csproj"; binding.CustomProjectReplacement = new Tuple ( "v4.5", @@ -75,16 +88,21 @@ namespace Xamarin.MMP.Tests return new Tuple (binding, project); } - [TestCase (ProjectType.Modern)] - [TestCase (ProjectType.ModernNoTag)] - [TestCase (ProjectType.Full)] - [TestCase (ProjectType.FullTVF)] - [TestCase (ProjectType.FullXamMacTag)] - public void ShouldRemovePackagedLibrary_OnceInBundle (ProjectType type) + internal static void SetNoEmbedding (TI.UnifiedTestConfig project) + { + project.CSProjConfig = "true"; + } + + [TestCase (BindingProjectType.Modern)] + [TestCase (BindingProjectType.ModernNoTag)] + [TestCase (BindingProjectType.Full)] + [TestCase (BindingProjectType.FullTVF)] + [TestCase (BindingProjectType.FullXamMacTag)] + public void ShouldRemovePackagedLibrary_OnceInBundle (BindingProjectType type) { MMPTests.RunMMPTest (tmpDir => { var projects = GenerateTestProject (type, tmpDir); - BuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir); + SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference: false, setupDefaultNativeReference: false); string bindingName = RemoveCSProj (projects.Item1.ProjectName); string appName = RemoveCSProj (projects.Item2.ProjectName); @@ -96,16 +114,21 @@ namespace Xamarin.MMP.Tests }); } - [TestCase (ProjectType.Modern)] - [TestCase (ProjectType.ModernNoTag)] - [TestCase (ProjectType.Full)] - [TestCase (ProjectType.FullTVF)] - [TestCase (ProjectType.FullXamMacTag)] - public void ShouldBuildWithoutErrors_AndLinkCorrectFramework (ProjectType type) + [TestCase (BindingProjectType.Modern)] + [TestCase (BindingProjectType.Modern, true)] + [TestCase (BindingProjectType.ModernNoTag)] + [TestCase (BindingProjectType.Full)] + [TestCase (BindingProjectType.Full, true)] + [TestCase (BindingProjectType.FullTVF)] + [TestCase (BindingProjectType.FullXamMacTag)] + public void ShouldBuildWithoutErrors_AndLinkCorrectFramework (BindingProjectType type, bool noEmbedding = false) { MMPTests.RunMMPTest (tmpDir => { var projects = GenerateTestProject (type, tmpDir); - var logs = BuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir); + if (noEmbedding) + SetNoEmbedding (projects.Item1); + + var logs = SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference: false, setupDefaultNativeReference: noEmbedding); Assert.False (logs.Item1.Contains ("mcs"), "Bindings project must not use mcs:\n" + logs.Item1); Assert.True (logs.Item1.Contains ("csc"), "Bindings project must use csc:\n" + logs.Item1); @@ -116,14 +139,14 @@ namespace Xamarin.MMP.Tests var system = bgenParts.First (x => x.Contains ("System.dll")); switch (type) { - case ProjectType.Modern: - case ProjectType.ModernNoTag: + case BindingProjectType.Modern: + case BindingProjectType.ModernNoTag: Assert.True (mscorlib.EndsWith ("lib/mono/Xamarin.Mac/mscorlib.dll", StringComparison.Ordinal), "mscorlib not found in expected Modern location: " + mscorlib); Assert.True (system.EndsWith ("lib/mono/Xamarin.Mac/System.dll", StringComparison.Ordinal), "system not found in expected Modern location: " + system); break; - case ProjectType.Full: - case ProjectType.FullTVF: - case ProjectType.FullXamMacTag: + case BindingProjectType.Full: + case BindingProjectType.FullTVF: + case BindingProjectType.FullXamMacTag: Assert.True (mscorlib.EndsWith ("lib/mono/4.5/mscorlib.dll", StringComparison.Ordinal), "mscorlib not found in expected Full location: " + mscorlib); Assert.True (system.EndsWith ("lib/mono/4.5/System.dll", StringComparison.Ordinal), "system not found in expected Full location: " + system); break; @@ -146,15 +169,15 @@ namespace Xamarin.MMP.Tests }); } - static string GetExpectedBCLVersion (ProjectType type) + static string GetExpectedBCLVersion (BindingProjectType type) { switch (type) { - case ProjectType.Modern: - case ProjectType.ModernNoTag: + case BindingProjectType.Modern: + case BindingProjectType.ModernNoTag: return "2.0.5.0"; - case ProjectType.Full: - case ProjectType.FullTVF: - case ProjectType.FullXamMacTag: + case BindingProjectType.Full: + case BindingProjectType.FullTVF: + case BindingProjectType.FullXamMacTag: return "4.0.0.0"; default: throw new NotImplementedException (); diff --git a/tests/xharness/AppRunner.cs b/tests/xharness/AppRunner.cs index 765ee9269f..f6f7f529d4 100644 --- a/tests/xharness/AppRunner.cs +++ b/tests/xharness/AppRunner.cs @@ -10,6 +10,7 @@ using System.Threading; using System.Threading.Tasks; using System.Xml; using System.Xml.Xsl; +using Xamarin; using Xamarin.Utils; namespace xharness diff --git a/tests/xharness/BCLTestInfo.cs b/tests/xharness/BCLTestInfo.cs index c6e377e339..7030db1736 100644 --- a/tests/xharness/BCLTestInfo.cs +++ b/tests/xharness/BCLTestInfo.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Text; using System.Xml; +using Xamarin; namespace xharness { diff --git a/tests/xharness/GitHub.cs b/tests/xharness/GitHub.cs index 40990fc509..d766053a72 100644 --- a/tests/xharness/GitHub.cs +++ b/tests/xharness/GitHub.cs @@ -7,6 +7,7 @@ using System.Net; using System.Runtime.Serialization.Json; using System.Xml; using System.Text; +using Xamarin; namespace xharness { diff --git a/tests/xharness/Jenkins.cs b/tests/xharness/Jenkins.cs index 22c89d3706..9c028e6c30 100644 --- a/tests/xharness/Jenkins.cs +++ b/tests/xharness/Jenkins.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Net; using System.Threading.Tasks; using System.Text; +using Xamarin; using Xamarin.Utils; namespace xharness diff --git a/tests/xharness/Simulators.cs b/tests/xharness/Simulators.cs index f121ef2394..deb9557625 100644 --- a/tests/xharness/Simulators.cs +++ b/tests/xharness/Simulators.cs @@ -8,6 +8,7 @@ using System.Text; using System.Threading; using System.Threading.Tasks; using System.Xml; +using Xamarin; using Xamarin.Utils; namespace xharness diff --git a/tests/xharness/SolutionGenerator.cs b/tests/xharness/SolutionGenerator.cs index 2416c9750c..d1867e264f 100644 --- a/tests/xharness/SolutionGenerator.cs +++ b/tests/xharness/SolutionGenerator.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Xml; using System.Text; +using Xamarin; namespace xharness { diff --git a/tests/xharness/TVOSTarget.cs b/tests/xharness/TVOSTarget.cs index d60de127e2..7618ed99cd 100644 --- a/tests/xharness/TVOSTarget.cs +++ b/tests/xharness/TVOSTarget.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Xml; +using Xamarin; namespace xharness { diff --git a/tests/xharness/Target.cs b/tests/xharness/Target.cs index 1561d04f69..9f7d3b4373 100644 --- a/tests/xharness/Target.cs +++ b/tests/xharness/Target.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; using System.Xml; +using Xamarin; namespace xharness { diff --git a/tests/xharness/TestProject.cs b/tests/xharness/TestProject.cs index b9bdc123fa..fa87acc818 100644 --- a/tests/xharness/TestProject.cs +++ b/tests/xharness/TestProject.cs @@ -4,6 +4,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; using System.Xml; +using Xamarin; namespace xharness { diff --git a/tests/xharness/TodayExtensionTarget.cs b/tests/xharness/TodayExtensionTarget.cs index cefa3eeaae..1c7232c2e4 100644 --- a/tests/xharness/TodayExtensionTarget.cs +++ b/tests/xharness/TodayExtensionTarget.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Xml; +using Xamarin; namespace xharness { diff --git a/tests/xharness/WatchOSTarget.cs b/tests/xharness/WatchOSTarget.cs index 6cb67e0638..b765bd504d 100644 --- a/tests/xharness/WatchOSTarget.cs +++ b/tests/xharness/WatchOSTarget.cs @@ -2,6 +2,7 @@ using System.Collections.Generic; using System.IO; using System.Xml; +using Xamarin; namespace xharness { diff --git a/tests/xharness/xharness.csproj b/tests/xharness/xharness.csproj index 9efb5edb66..86d81dafb4 100644 --- a/tests/xharness/xharness.csproj +++ b/tests/xharness/xharness.csproj @@ -76,7 +76,9 @@ - + + PListExtensions.cs + diff --git a/tools/common/Application.cs b/tools/common/Application.cs index 0f32c8ef45..d0e3dc207d 100644 --- a/tools/common/Application.cs +++ b/tools/common/Application.cs @@ -126,47 +126,10 @@ namespace Xamarin.Bundler { } } } - - // Checks if the source file has a time stamp later than the target file. - // - // Optionally check if the contents of the files are different after checking the timestamp. - // - // If check_stamp is true, the function will use the timestamp of a "target".stamp file - // if it's later than the timestamp of the "target" file itself. + public static bool IsUptodate (string source, string target, bool check_contents = false, bool check_stamp = true) { - if (Driver.Force) - return false; - - var tfi = new FileInfo (target); - - if (!tfi.Exists) { - Driver.Log (3, "Target '{0}' does not exist.", target); - return false; - } - - if (check_stamp) { - var tfi_stamp = new FileInfo (target + ".stamp"); - if (tfi_stamp.Exists && tfi_stamp.LastWriteTimeUtc > tfi.LastWriteTimeUtc) { - Driver.Log (3, "Target '{0}' has a stamp file with newer timestamp ({1} > {2}), using the stamp file's timestamp", target, tfi_stamp.LastWriteTimeUtc, tfi.LastWriteTimeUtc); - tfi = tfi_stamp; - } - } - - var sfi = new FileInfo (source); - - if (sfi.LastWriteTimeUtc <= tfi.LastWriteTimeUtc) { - Driver.Log (3, "Prerequisite '{0}' is older than the target '{1}'.", source, target); - return true; - } - - if (check_contents && Cache.CompareFiles (source, target)) { - Driver.Log (3, "Prerequisite '{0}' is newer than the target '{1}', but the contents are identical.", source, target); - return true; - } - - Driver.Log (3, "Prerequisite '{0}' is newer than the target '{1}'.", source, target); - return false; + return FileCopier.IsUptodate (source, target, check_contents, check_stamp); } public static void RemoveResource (ModuleDefinition module, string name) @@ -229,107 +192,6 @@ namespace Xamarin.Bundler { } } - enum CopyFileFlags : uint { - ACL = 1 << 0, - Stat = 1 << 1, - Xattr = 1 << 2, - Data = 1 << 3, - Security = Stat | ACL, - Metadata = Security | Xattr, - All = Metadata | Data, - - Recursive = 1 << 15, - NoFollow_Src = 1 << 18, - NoFollow_Dst = 1 << 19, - Unlink = 1 << 21, - Nofollow = NoFollow_Src | NoFollow_Dst, - Clone = 1 << 24, - } - - enum CopyFileState : uint { - StatusCB = 6, - } - - enum CopyFileStep { - Start = 1, - Finish = 2, - Err = 3, - Progress = 4, - } - - enum CopyFileResult { - Continue = 0, - Skip = 1, - Quit = 2, - } - - enum CopyFileWhat { - Error = 0, - File = 1, - Dir = 2, - DirCleanup = 3, - CopyData = 4, - CopyXattr = 5, - } - - [DllImport (Constants.libSystemLibrary)] - static extern IntPtr copyfile_state_alloc (); - - [DllImport (Constants.libSystemLibrary)] - static extern int copyfile_state_free (IntPtr state); - - [DllImport (Constants.libSystemLibrary)] - static extern int copyfile_state_set (IntPtr state, CopyFileState flag, IntPtr value); - - delegate CopyFileResult CopyFileCallbackDelegate (CopyFileWhat what, CopyFileStep stage, IntPtr state, string src, string dst, IntPtr ctx); - - [DllImport (Constants.libSystemLibrary, SetLastError = true)] - static extern int copyfile (string @from, string @to, IntPtr state, CopyFileFlags flags); - - public static void UpdateDirectory (string source, string target) - { - if (!Directory.Exists (target)) - Directory.CreateDirectory (target); - - // Mono's File.Copy can't handle symlinks (the symlinks are followed instead of copied), - // so we need to use native functions directly. Luckily OSX provides exactly what we need. - IntPtr state = copyfile_state_alloc (); - try { - CopyFileCallbackDelegate del = CopyFileCallback; - copyfile_state_set (state, CopyFileState.StatusCB, Marshal.GetFunctionPointerForDelegate (del)); - int rv = copyfile (source, target, state, CopyFileFlags.Data | CopyFileFlags.Recursive | CopyFileFlags.Nofollow | CopyFileFlags.Clone); - if (rv != 0) - throw ErrorHelper.CreateError (1022, "Could not copy the directory '{0}' to '{1}': {2}", source, target, Target.strerror (Marshal.GetLastWin32Error ())); - } finally { - copyfile_state_free (state); - } - } - - static CopyFileResult CopyFileCallback (CopyFileWhat what, CopyFileStep stage, IntPtr state, string source, string target, IntPtr ctx) - { -// Console.WriteLine ("CopyFileCallback ({0}, {1}, 0x{2}, {3}, {4}, 0x{5})", what, stage, state.ToString ("x"), source, target, ctx.ToString ("x")); - switch (what) { - case CopyFileWhat.File: - if (!IsUptodate (source, target)) { - if (stage == CopyFileStep.Finish) - Driver.Log (1, "Copied {0} to {1}", source, target); - return CopyFileResult.Continue; - } else { - Driver.Log (3, "Target '{0}' is up-to-date", target); - return CopyFileResult.Skip; - } - case CopyFileWhat.Dir: - case CopyFileWhat.DirCleanup: - case CopyFileWhat.CopyData: - case CopyFileWhat.CopyXattr: - return CopyFileResult.Continue; - case CopyFileWhat.Error: - throw ErrorHelper.CreateError (1021, "Could not copy the file '{0}' to '{1}': {2}", source, target, Target.strerror (Marshal.GetLastWin32Error ())); - default: - return CopyFileResult.Continue; - } - } - public static void UpdateFile (string source, string target, bool check_contents = false) { if (!Application.IsUptodate (source, target, check_contents)) @@ -394,6 +256,11 @@ namespace Xamarin.Bundler { return true; } + + public static void UpdateDirectory (string source, string target) + { + FileCopier.UpdateDirectory (source, target); + } [DllImport (Constants.libSystemLibrary)] static extern int readlink (string path, IntPtr buf, int len); diff --git a/tools/common/Assembly.cs b/tools/common/Assembly.cs index 8cb805bf21..06680f6621 100644 --- a/tools/common/Assembly.cs +++ b/tools/common/Assembly.cs @@ -4,10 +4,11 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; - +using System.Xml; using Mono.Cecil; using MonoTouch.Tuner; using ObjCRuntime; +using Xamarin; using Xamarin.Utils; #if MONOTOUCH @@ -18,6 +19,39 @@ using PlatformException = Xamarin.Bundler.MonoMacException; namespace Xamarin.Bundler { + + struct NativeReferenceMetadata + { + public bool ForceLoad; + public string Frameworks; + public string WeakFrameworks; + public string LibraryName; + public string LinkerFlags; + public LinkTarget LinkTarget; + public bool NeedsGccExceptionHandling; + public bool IsCxx; + public bool SmartLink; + public DlsymOption Dlsym; + + // Optional + public LinkWithAttribute Attribute; + + public NativeReferenceMetadata (LinkWithAttribute attribute) + { + ForceLoad = attribute.ForceLoad; + Frameworks = attribute.Frameworks; + WeakFrameworks = attribute.WeakFrameworks; + LibraryName = attribute.LibraryName; + LinkerFlags = attribute.LinkerFlags; + LinkTarget = attribute.LinkTarget; + NeedsGccExceptionHandling = attribute.NeedsGccExceptionHandling; + IsCxx = attribute.IsCxx; + SmartLink = attribute.SmartLink; + Dlsym = attribute.Dlsym; + Attribute = attribute; + } + } + public partial class Assembly { public List Satellites; @@ -112,138 +146,35 @@ namespace Xamarin.Bundler { // ignore framework assemblies, they won't have any LinkWith attributes if (IsFrameworkAssembly) return; - + var assembly = AssemblyDefinition; if (!assembly.HasCustomAttributes) return; - var exceptions = new List (); - string path; - - // - // Tasks: - // * Remove LinkWith attribute: this is done in the linker. - // * Remove embedded resources related to LinkWith attribute from assembly: this is done at a later stage, - // here we just compile a list of resources to remove. - // * Extract embedded resources related to LinkWith attribute to a file - // * Modify the linker flags used to build/link the dylib (if fastdev) or the main binary (if !fastdev) - // + string resourceBundlePath = Path.ChangeExtension (FullPath, ".resources"); + string manifestPath = Path.Combine (resourceBundlePath, "manifest"); + if (File.Exists (manifestPath)) { + foreach (NativeReferenceMetadata metadata in ReadManifest (manifestPath)) { + LogNativeReference (metadata); + ProcessNativeReferenceOptions (metadata); - for (int i = 0; i < assembly.CustomAttributes.Count; i++) { - CustomAttribute attr = assembly.CustomAttributes[i]; - - if (attr.Constructor == null) - continue; - - TypeReference type = attr.Constructor.DeclaringType; - if (!type.IsPlatformType ("ObjCRuntime", "LinkWithAttribute")) - continue; - - // Let the linker remove it the attribute from the assembly - HasLinkWithAttributes = true; - - LinkWithAttribute linkWith = GetLinkWithAttribute (attr); - string libraryName = linkWith.LibraryName; - - // Remove the resource from the assembly at a later stage. - if (!string.IsNullOrEmpty (libraryName)) - AddResourceToBeRemoved (libraryName); - - // We can't add -dead_strip if there are any LinkWith attributes where smart linking is disabled. - if (!linkWith.SmartLink) - App.DeadStrip = false; - - // Don't add -force_load if the binding's SmartLink value is set and the static registrar is being used. - if (linkWith.ForceLoad && !(linkWith.SmartLink && App.Registrar == RegistrarMode.Static)) - ForceLoad = true; - - if (!string.IsNullOrEmpty (linkWith.LinkerFlags)) { - if (LinkerFlags == null) - LinkerFlags = new List (); - LinkerFlags.Add (linkWith.LinkerFlags); - } - - if (!string.IsNullOrEmpty (linkWith.Frameworks)) { - foreach (var f in linkWith.Frameworks.Split (new char[] { ' ' })) { - if (Frameworks == null) - Frameworks = new HashSet (); - Frameworks.Add (f); - } - } - - if (!string.IsNullOrEmpty (linkWith.WeakFrameworks)) { - foreach (var f in linkWith.WeakFrameworks.Split (new char[] { ' ' })) { - if (WeakFrameworks == null) - WeakFrameworks = new HashSet (); - WeakFrameworks.Add (f); - } - } - - if (linkWith.NeedsGccExceptionHandling) - NeedsGccExceptionHandling = true; - - if (linkWith.IsCxx) - EnableCxx = true; - -#if MONOTOUCH - if (linkWith.Dlsym != DlsymOption.Default) - App.SetDlsymOption (FullPath, linkWith.Dlsym == DlsymOption.Required); + if (metadata.LibraryName.EndsWith (".framework", StringComparison.OrdinalIgnoreCase)) { + AssertiOSVersionSupportsUserFrameworks (metadata.LibraryName); + Frameworks.Add (metadata.LibraryName); +#if MMP // HACK - MMP currently doesn't respect Frameworks on non-App - https://github.com/xamarin/xamarin-macios/issues/5203 + App.Frameworks.Add (metadata.LibraryName); #endif - if (!string.IsNullOrEmpty (libraryName)) { - path = Path.Combine (App.Cache.Location, libraryName); - if (path.EndsWith (".framework", StringComparison.Ordinal)) { -#if MONOTOUCH - if (App.Platform == Xamarin.Utils.ApplePlatform.iOS && App.DeploymentTarget.Major < 8) { - throw ErrorHelper.CreateError (1305, "The binding library '{0}' contains a user framework ({0}), but embedded user frameworks require iOS 8.0 (the deployment target is {1}). Please set the deployment target in the Info.plist file to at least 8.0.", - FileName, Path.GetFileName (path), App.DeploymentTarget); - } -#endif - var zipPath = path + ".zip"; - if (!Application.IsUptodate (FullPath, zipPath)) { - Application.ExtractResource (assembly.MainModule, libraryName, zipPath, false); - Driver.Log (3, "Extracted third-party framework '{0}' from '{1}' to '{2}'", libraryName, FullPath, zipPath); - LogLinkWithAttribute (linkWith); - } else { - Driver.Log (3, "Target '{0}' is up-to-date.", path); - } - - if (!File.Exists (zipPath)) { - ErrorHelper.Warning (1302, "Could not extract the native framework '{0}' from '{1}'. " + - "Please ensure the native framework was properly embedded in the managed assembly " + - "(if the assembly was built using a binding project, the native framework must be included in the project, and its Build Action must be 'ObjcBindingNativeFramework').", - libraryName, zipPath); - } else { - if (!Directory.Exists (path)) - Directory.CreateDirectory (path); - - if (Driver.RunCommand ("/usr/bin/unzip", string.Format ("-u -o -d {0} {1}", StringUtils.Quote (path), StringUtils.Quote (zipPath))) != 0) - throw ErrorHelper.CreateError (1303, "Could not decompress the native framework '{0}' from '{1}'. Please review the build log for more information from the native 'unzip' command.", libraryName, zipPath); - } - - Frameworks.Add (path); } else { - if (!Application.IsUptodate (FullPath, path)) { - Application.ExtractResource (assembly.MainModule, libraryName, path, false); - Driver.Log (3, "Extracted third-party binding '{0}' from '{1}' to '{2}'", libraryName, FullPath, path); - LogLinkWithAttribute (linkWith); - } else { - Driver.Log (3, "Target '{0}' is up-to-date.", path); - } - - if (!File.Exists (path)) - ErrorHelper.Warning (1302, "Could not extract the native library '{0}' from '{1}'. " + - "Please ensure the native library was properly embedded in the managed assembly " + - "(if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').", - libraryName, path); - - LinkWith.Add (path); +#if MMP // HACK - MMP currently doesn't respect LinkWith - https://github.com/xamarin/xamarin-macios/issues/5203 + Driver.native_references.Add (metadata.LibraryName); +#endif + LinkWith.Add (metadata.LibraryName); } } } - if (exceptions != null && exceptions.Count > 0) - throw new AggregateException (exceptions); + ProcessLinkWithAttributes (assembly); // Make sure there are no duplicates between frameworks and weak frameworks. // Keep the weak ones. @@ -258,16 +189,202 @@ namespace Xamarin.Bundler { } - static void LogLinkWithAttribute (LinkWithAttribute linkWith) + IEnumerable ReadManifest (string manifestPath) { - Driver.Log (3, " ForceLoad: {0}", linkWith.ForceLoad); - Driver.Log (3, " Frameworks: {0}", linkWith.Frameworks); - Driver.Log (3, " IsCxx: {0}", linkWith.IsCxx); - Driver.Log (3, " LinkerFlags: {0}", linkWith.LinkerFlags); - Driver.Log (3, " LinkTarget: {0}", linkWith.LinkTarget); - Driver.Log (3, " NeedsGccExceptionHandling: {0}", linkWith.NeedsGccExceptionHandling); - Driver.Log (3, " SmartLink: {0}", linkWith.SmartLink); - Driver.Log (3, " WeakFrameworks: {0}", linkWith.WeakFrameworks); + XmlDocument document = new XmlDocument (); + document.LoadWithoutNetworkAccess (manifestPath); + + foreach (XmlNode referenceNode in document.GetElementsByTagName ("NativeReference")) { + + NativeReferenceMetadata metadata = new NativeReferenceMetadata (); + metadata.LibraryName = Path.Combine (Path.GetDirectoryName (manifestPath), referenceNode.Attributes ["Name"].Value); + + var attributes = new Dictionary (); + foreach (XmlNode attribute in referenceNode.ChildNodes) + attributes [attribute.Name] = attribute.InnerText; + + metadata.ForceLoad = ParseAttributeWithDefault (attributes ["ForceLoad"], false); + metadata.Frameworks = attributes ["Frameworks"]; + metadata.WeakFrameworks = attributes ["WeakFrameworks"]; + metadata.LinkerFlags = attributes ["LinkerFlags"]; + metadata.NeedsGccExceptionHandling = ParseAttributeWithDefault (attributes ["NeedsGccExceptionHandling"], false); + metadata.IsCxx = ParseAttributeWithDefault (attributes ["IsCxx"], false); + metadata.SmartLink = ParseAttributeWithDefault (attributes ["SmartLink"], true); + + // TODO - The project attributes do not contain these bits, is that OK? + //metadata.LinkTarget = (LinkTarget) Enum.Parse (typeof (LinkTarget), attributes ["LinkTarget"]); + //metadata.Dlsym = (DlsymOption)Enum.Parse (typeof (DlsymOption), attributes ["Dlsym"]); + yield return metadata; + } + } + + static bool ParseAttributeWithDefault (string attribute, bool defaultValue) => string.IsNullOrEmpty (attribute) ? defaultValue : bool.Parse (attribute); + + void ProcessLinkWithAttributes (AssemblyDefinition assembly) + { + // + // Tasks: + // * Remove LinkWith attribute: this is done in the linker. + // * Remove embedded resources related to LinkWith attribute from assembly: this is done at a later stage, + // here we just compile a list of resources to remove. + // * Extract embedded resources related to LinkWith attribute to a file + // * Modify the linker flags used to build/link the dylib (if fastdev) or the main binary (if !fastdev) + // + + for (int i = 0; i < assembly.CustomAttributes.Count; i++) { + CustomAttribute attr = assembly.CustomAttributes [i]; + + if (attr.Constructor == null) + continue; + + TypeReference type = attr.Constructor.DeclaringType; + if (!type.IsPlatformType ("ObjCRuntime", "LinkWithAttribute")) + continue; + + // Let the linker remove it the attribute from the assembly + HasLinkWithAttributes = true; + + LinkWithAttribute linkWith = GetLinkWithAttribute (attr); + NativeReferenceMetadata metadata = new NativeReferenceMetadata (linkWith); + + // If we've already processed this native library, skip it + if (LinkWith.Any (x => Path.GetFileName (x) == metadata.LibraryName) || Frameworks.Any (x => Path.GetFileName (x) == metadata.LibraryName)) + continue; + + // Remove the resource from the assembly at a later stage. + if (!string.IsNullOrEmpty (metadata.LibraryName)) + AddResourceToBeRemoved (metadata.LibraryName); + + ProcessNativeReferenceOptions (metadata); + + if (!string.IsNullOrEmpty (linkWith.LibraryName)) { + if (linkWith.LibraryName.EndsWith (".framework", StringComparison.OrdinalIgnoreCase)) { + AssertiOSVersionSupportsUserFrameworks (linkWith.LibraryName); + + Frameworks.Add (ExtractFramework (assembly, metadata)); + } else { + LinkWith.Add (ExtractNativeLibrary (assembly, metadata)); + } + } + } + } + + void AssertiOSVersionSupportsUserFrameworks (string path) + { +#if MONOTOUCH + if (App.Platform == Xamarin.Utils.ApplePlatform.iOS && App.DeploymentTarget.Major < 8) { + throw ErrorHelper.CreateError (1305, "The binding library '{0}' contains a user framework ({0}), but embedded user frameworks require iOS 8.0 (the deployment target is {1}). Please set the deployment target in the Info.plist file to at least 8.0.", + FileName, Path.GetFileName (path), App.DeploymentTarget); + } +#endif + } + + void ProcessNativeReferenceOptions (NativeReferenceMetadata metadata) + { + // We can't add -dead_strip if there are any LinkWith attributes where smart linking is disabled. + if (!metadata.SmartLink) + App.DeadStrip = false; + + // Don't add -force_load if the binding's SmartLink value is set and the static registrar is being used. + if (metadata.ForceLoad && !(metadata.SmartLink && App.Registrar == RegistrarMode.Static)) + ForceLoad = true; + + if (!string.IsNullOrEmpty (metadata.LinkerFlags)) { + if (LinkerFlags == null) + LinkerFlags = new List (); + LinkerFlags.Add (metadata.LinkerFlags); + } + + if (!string.IsNullOrEmpty (metadata.Frameworks)) { + foreach (var f in metadata.Frameworks.Split (new char [] { ' ' })) { + if (Frameworks == null) + Frameworks = new HashSet (); + Frameworks.Add (f); + } + } + + if (!string.IsNullOrEmpty (metadata.WeakFrameworks)) { + foreach (var f in metadata.WeakFrameworks.Split (new char [] { ' ' })) { + if (WeakFrameworks == null) + WeakFrameworks = new HashSet (); + WeakFrameworks.Add (f); + } + } + + if (metadata.NeedsGccExceptionHandling) + NeedsGccExceptionHandling = true; + + if (metadata.IsCxx) + EnableCxx = true; + +#if MONOTOUCH + if (metadata.Dlsym != DlsymOption.Default) + App.SetDlsymOption (FullPath, metadata.Dlsym == DlsymOption.Required); +#endif + } + + string ExtractNativeLibrary (AssemblyDefinition assembly, NativeReferenceMetadata metadata) + { + string path = Path.Combine (App.Cache.Location, metadata.LibraryName); + + if (!Application.IsUptodate (FullPath, path)) { + Application.ExtractResource (assembly.MainModule, metadata.LibraryName, path, false); + Driver.Log (3, "Extracted third-party binding '{0}' from '{1}' to '{2}'", metadata.LibraryName, FullPath, path); + LogNativeReference (metadata); + } else { + Driver.Log (3, "Target '{0}' is up-to-date.", path); + } + + if (!File.Exists (path)) + ErrorHelper.Warning (1302, "Could not extract the native library '{0}' from '{1}'. " + + "Please ensure the native library was properly embedded in the managed assembly " + + "(if the assembly was built using a binding project, the native library must be included in the project, and its Build Action must be 'ObjcBindingNativeLibrary').", + metadata.LibraryName, path); + + return path; + } + + string ExtractFramework (AssemblyDefinition assembly, NativeReferenceMetadata metadata) + { + string path = Path.Combine (App.Cache.Location, metadata.LibraryName); + + var zipPath = path + ".zip"; + if (!Application.IsUptodate (FullPath, zipPath)) { + Application.ExtractResource (assembly.MainModule, metadata.LibraryName, zipPath, false); + Driver.Log (3, "Extracted third-party framework '{0}' from '{1}' to '{2}'", metadata.LibraryName, FullPath, zipPath); + LogNativeReference (metadata); + } else { + Driver.Log (3, "Target '{0}' is up-to-date.", path); + } + + if (!File.Exists (zipPath)) { + ErrorHelper.Warning (1302, "Could not extract the native framework '{0}' from '{1}'. " + + "Please ensure the native framework was properly embedded in the managed assembly " + + "(if the assembly was built using a binding project, the native framework must be included in the project, and its Build Action must be 'ObjcBindingNativeFramework').", + metadata.LibraryName, zipPath); + } else { + if (!Directory.Exists (path)) + Directory.CreateDirectory (path); + + if (Driver.RunCommand ("/usr/bin/unzip", string.Format ("-u -o -d {0} {1}", StringUtils.Quote (path), StringUtils.Quote (zipPath))) != 0) + throw ErrorHelper.CreateError (1303, "Could not decompress the native framework '{0}' from '{1}'. Please review the build log for more information from the native 'unzip' command.", metadata.LibraryName, zipPath); + } + + return path; + } + + static void LogNativeReference (NativeReferenceMetadata metadata) + { + Driver.Log (3, " LibraryName: {0}", metadata.LibraryName); + Driver.Log (3, " From: {0}", metadata.Attribute != null ? "LinkWith" : "Binding Manifest"); + Driver.Log (3, " ForceLoad: {0}", metadata.ForceLoad); + Driver.Log (3, " Frameworks: {0}", metadata.Frameworks); + Driver.Log (3, " IsCxx: {0}", metadata.IsCxx); + Driver.Log (3, " LinkerFlags: {0}", metadata.LinkerFlags); + Driver.Log (3, " LinkTarget: {0}", metadata.LinkTarget); + Driver.Log (3, " NeedsGccExceptionHandling: {0}", metadata.NeedsGccExceptionHandling); + Driver.Log (3, " SmartLink: {0}", metadata.SmartLink); + Driver.Log (3, " WeakFrameworks: {0}", metadata.WeakFrameworks); } public static LinkWithAttribute GetLinkWithAttribute (CustomAttribute attr) diff --git a/tools/common/FileCopier.cs b/tools/common/FileCopier.cs new file mode 100644 index 0000000000..fee6e2176e --- /dev/null +++ b/tools/common/FileCopier.cs @@ -0,0 +1,179 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; + +namespace Xamarin.Bundler { + public static class FileCopier + { + enum CopyFileFlags : uint { + ACL = 1 << 0, + Stat = 1 << 1, + Xattr = 1 << 2, + Data = 1 << 3, + Security = Stat | ACL, + Metadata = Security | Xattr, + All = Metadata | Data, + + Recursive = 1 << 15, + NoFollow_Src = 1 << 18, + NoFollow_Dst = 1 << 19, + Unlink = 1 << 21, + Nofollow = NoFollow_Src | NoFollow_Dst, + Clone = 1 << 24, + } + + enum CopyFileState : uint { + StatusCB = 6, + } + + enum CopyFileStep { + Start = 1, + Finish = 2, + Err = 3, + Progress = 4, + } + + enum CopyFileResult { + Continue = 0, + Skip = 1, + Quit = 2, + } + + enum CopyFileWhat { + Error = 0, + File = 1, + Dir = 2, + DirCleanup = 3, + CopyData = 4, + CopyXattr = 5, + } + + [DllImport ("/usr/lib/libSystem.dylib")] + static extern IntPtr copyfile_state_alloc (); + + [DllImport ("/usr/lib/libSystem.dylib")] + static extern int copyfile_state_free (IntPtr state); + + [DllImport ("/usr/lib/libSystem.dylib")] + static extern int copyfile_state_set (IntPtr state, CopyFileState flag, IntPtr value); + + delegate CopyFileResult CopyFileCallbackDelegate (CopyFileWhat what, CopyFileStep stage, IntPtr state, string src, string dst, IntPtr ctx); + + [DllImport ("/usr/lib/libSystem.dylib", SetLastError = true)] + static extern int copyfile (string @from, string @to, IntPtr state, CopyFileFlags flags); + + // This code is shared between our packaging tools (mmp\mtouch) and msbuild tasks +#if MMP || MTOUCH + public static void Log (int min_verbosity, string format, params object[] args) => Driver.Log (min_verbosity, format, args); + public static Exception CreateError (int code, string message, params object[] args) => ErrorHelper.CreateError (code, message, args); +#else + // LogMessage and LogError are instance objects on the tasks themselves and bubbling an event up is not ideal + // msbuild handles uncaught exceptions as a task error + public static void Log (int min_verbosity, string format, params object[] args) => Console.WriteLine (format, args); + public static Exception CreateError (int code, string message, params object[] args) => throw new Exception ($"{code} {string.Format (message, args)}"); +#endif + + public static void UpdateDirectory (string source, string target) + { + if (!Directory.Exists (target)) + Directory.CreateDirectory (target); + + // Mono's File.Copy can't handle symlinks (the symlinks are followed instead of copied), + // so we need to use native functions directly. Luckily OSX provides exactly what we need. + IntPtr state = copyfile_state_alloc (); + try { + CopyFileCallbackDelegate del = CopyFileCallback; + copyfile_state_set (state, CopyFileState.StatusCB, Marshal.GetFunctionPointerForDelegate (del)); + int rv = copyfile (source, target, state, CopyFileFlags.Data | CopyFileFlags.Recursive | CopyFileFlags.Nofollow | CopyFileFlags.Clone); + if (rv != 0) + throw CreateError (1022, "Could not copy the directory '{0}' to '{1}': {2}", source, target, strerror (Marshal.GetLastWin32Error ())); + } finally { + copyfile_state_free (state); + } + } + + static CopyFileResult CopyFileCallback (CopyFileWhat what, CopyFileStep stage, IntPtr state, string source, string target, IntPtr ctx) + { +// Console.WriteLine ("CopyFileCallback ({0}, {1}, 0x{2}, {3}, {4}, 0x{5})", what, stage, state.ToString ("x"), source, target, ctx.ToString ("x")); + switch (what) { + case CopyFileWhat.File: + if (!IsUptodate (source, target)) { + if (stage == CopyFileStep.Finish) + Log (1, "Copied {0} to {1}", source, target); + return CopyFileResult.Continue; + } else { + Log (3, "Target '{0}' is up-to-date", target); + return CopyFileResult.Skip; + } + case CopyFileWhat.Dir: + case CopyFileWhat.DirCleanup: + case CopyFileWhat.CopyData: + case CopyFileWhat.CopyXattr: + return CopyFileResult.Continue; + case CopyFileWhat.Error: + throw CreateError (1021, "Could not copy the file '{0}' to '{1}': {2}", source, target, strerror (Marshal.GetLastWin32Error ())); + default: + return CopyFileResult.Continue; + } + } + + // Checks if the source file has a time stamp later than the target file. + // + // Optionally check if the contents of the files are different after checking the timestamp. + // + // If check_stamp is true, the function will use the timestamp of a "target".stamp file + // if it's later than the timestamp of the "target" file itself. + public static bool IsUptodate (string source, string target, bool check_contents = false, bool check_stamp = true) + { +#if MMP || MTOUCH // msbuild does not have force + if (Driver.Force) + return false; +#endif + + var tfi = new FileInfo (target); + + if (!tfi.Exists) { + Log (3, "Target '{0}' does not exist.", target); + return false; + } + + if (check_stamp) { + var tfi_stamp = new FileInfo (target + ".stamp"); + if (tfi_stamp.Exists && tfi_stamp.LastWriteTimeUtc > tfi.LastWriteTimeUtc) { + Log (3, "Target '{0}' has a stamp file with newer timestamp ({1} > {2}), using the stamp file's timestamp", target, tfi_stamp.LastWriteTimeUtc, tfi.LastWriteTimeUtc); + tfi = tfi_stamp; + } + } + + var sfi = new FileInfo (source); + + if (sfi.LastWriteTimeUtc <= tfi.LastWriteTimeUtc) { + Log (3, "Prerequisite '{0}' is older than the target '{1}'.", source, target); + return true; + } + +#if MMP || MTOUCH // msbuild usages do not require CompareFiles optimization + if (check_contents && Cache.CompareFiles (source, target)) { + Log (3, "Prerequisite '{0}' is newer than the target '{1}', but the contents are identical.", source, target); + return true; + } +#else + if (check_contents) + throw new NotImplementedException ("Checking file contents is not supported"); +#endif + + Log (3, "Prerequisite '{0}' is newer than the target '{1}'.", source, target); + return false; + } + + [DllImport ("/usr/lib/libSystem.dylib", SetLastError = true, EntryPoint = "strerror")] + static extern IntPtr _strerror (int errno); + + internal static string strerror (int errno) + { + return Marshal.PtrToStringAuto (_strerror (errno)); + } + } +} diff --git a/tests/xharness/PListExtensions.cs b/tools/common/PListExtensions.cs similarity index 99% rename from tests/xharness/PListExtensions.cs rename to tools/common/PListExtensions.cs index 9b0c70548e..cf07ec270d 100644 --- a/tests/xharness/PListExtensions.cs +++ b/tools/common/PListExtensions.cs @@ -2,7 +2,7 @@ using System.IO; using System.Xml; -namespace xharness +namespace Xamarin { static class PListExtensions { diff --git a/tools/common/Target.cs b/tools/common/Target.cs index 976ea464c0..84ca4d1b12 100644 --- a/tools/common/Target.cs +++ b/tools/common/Target.cs @@ -98,14 +98,6 @@ namespace Xamarin.Bundler { #endif } - [DllImport (Constants.libSystemLibrary, SetLastError = true, EntryPoint = "strerror")] - static extern IntPtr _strerror (int errno); - - internal static string strerror (int errno) - { - return Marshal.PtrToStringAuto (_strerror (errno)); - } - [DllImport (Constants.libSystemLibrary, SetLastError = true)] static extern string realpath (string path, IntPtr zero); @@ -116,7 +108,7 @@ namespace Xamarin.Bundler { return rv; var errno = Marshal.GetLastWin32Error (); - ErrorHelper.Warning (54, "Unable to canonicalize the path '{0}': {1} ({2}).", path, strerror (errno), errno); + ErrorHelper.Warning (54, "Unable to canonicalize the path '{0}': {1} ({2}).", path, FileCopier.strerror (errno), errno); return path; } diff --git a/tools/mmp/driver.cs b/tools/mmp/driver.cs index 8bbc02f63b..693a35e6d6 100644 --- a/tools/mmp/driver.cs +++ b/tools/mmp/driver.cs @@ -75,7 +75,7 @@ namespace Xamarin.Bundler { static List resources = new List (); static List resolved_assemblies = new List (); static List ignored_assemblies = new List (); - static List native_references = new List (); + public static List native_references = new List (); static List native_libraries_copied_in = new List (); static Action action; diff --git a/tools/mmp/mmp.csproj b/tools/mmp/mmp.csproj index 165046195d..30a89bf1cc 100644 --- a/tools/mmp/mmp.csproj +++ b/tools/mmp/mmp.csproj @@ -289,6 +289,9 @@ external\Registrar.cs + + external\PListExtensions.cs + external\TargetFramework.cs @@ -361,6 +364,9 @@ MonoMac.Tuner\MacBaseProfile.cs + + external\FileCopier.cs + external\Symbols.cs diff --git a/tools/mtouch/mtouch.csproj b/tools/mtouch/mtouch.csproj index 984e25d5c3..12f8a5f809 100644 --- a/tools/mtouch/mtouch.csproj +++ b/tools/mtouch/mtouch.csproj @@ -49,6 +49,9 @@ external\Constants.cs + + external\PListExtensions.cs + external\cache.cs @@ -368,6 +371,9 @@ external\Optimizations.cs + + external\FileCopier.cs + external\maccore\BindingImplAttribute.cs From f77b1b712eedc1072d2f31e8ac68fc60d12cee17 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 12 Dec 2018 19:15:45 +0000 Subject: [PATCH 17/23] Remove unused and obsolete OverrideRetainAndRelease method. (#5263) --- src/Foundation/NSObject.mac.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Foundation/NSObject.mac.cs b/src/Foundation/NSObject.mac.cs index 439841862c..f4808bc363 100644 --- a/src/Foundation/NSObject.mac.cs +++ b/src/Foundation/NSObject.mac.cs @@ -118,12 +118,6 @@ namespace Foundation { public static readonly Assembly MonoMacAssembly = typeof (NSObject).Assembly; #endif - static internal void OverrideRetainAndRelease (IntPtr @class) - { - Class.class_addMethod (@class, Selector.RetainHandle, Method.RetainTrampoline, "@@:"); - Class.class_addMethod (@class, Selector.ReleaseHandle, Method.ReleaseTrampoline, "v@:"); - } - internal void SetAsProxy () { IsDirectBinding = true; } From e154556e16abe9dccae1c996a3045f27356a1ccc Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Thu, 13 Dec 2018 08:52:02 -0500 Subject: [PATCH 18/23] [tests] fix symbols test for interpreter (#5264) `ves_pinvoke_method` / `do_icall` moved a frame up, so make the check more flexible. --- tests/monotouch-test/mono/Symbols.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/tests/monotouch-test/mono/Symbols.cs b/tests/monotouch-test/mono/Symbols.cs index 87c73a63e1..4db416d79c 100644 --- a/tests/monotouch-test/mono/Symbols.cs +++ b/tests/monotouch-test/mono/Symbols.cs @@ -27,10 +27,16 @@ namespace MonoTouchFixtures { Collect (); bool aot = symbols [1].Contains ("MonoTouchFixtures_Symbols_Collect"); - /* ves_pinvoke_method (slow path) and do_icall (fast path) are - * MONO_NEVER_INLINE, so they should show up in the backtrace - * reliably */ - bool interp = symbols [1].Contains ("ves_pinvoke_method") || symbols [1].Contains ("do_icall"); + bool interp = false; + + if (!aot) { + for (int i = 0; i < 4 && !interp; i++) { + /* ves_pinvoke_method (slow path) and do_icall (fast path) are + * MONO_NEVER_INLINE, so they should show up in the backtrace + * reliably */ + interp |= symbols [i].Contains ("ves_pinvoke_method") || symbols [i].Contains ("do_icall"); + } + } Assert.IsTrue (aot || interp, "#1"); } From 7360d4f7a780945be6d4722b3e6621493a21f637 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Thu, 13 Dec 2018 16:38:08 +0100 Subject: [PATCH 19/23] [jenkins] Specify repo manually for GitHub statuses to fix maccore#898. (#5269) Fixes https://github.com/xamarin/maccore/issues/898. --- jenkins/utils.groovy | 1 + 1 file changed, 1 insertion(+) diff --git a/jenkins/utils.groovy b/jenkins/utils.groovy index 813c7253d3..7fbee4d951 100644 --- a/jenkins/utils.groovy +++ b/jenkins/utils.groovy @@ -1,6 +1,7 @@ def reportGitHubStatus(commitHash, context, backref, statusResult, statusResultMessage) { step([ $class: 'GitHubCommitStatusSetter', + reposSource: [$class: "ManuallyEnteredRepositorySource", url: "https://github.com/xamarin/xamarin-macios"], commitShaSource: [$class: "ManuallyEnteredShaSource", sha: commitHash], contextSource: [$class: 'ManuallyEnteredCommitContextSource', context: context], statusBackrefSource: [$class: 'ManuallyEnteredBackrefSource', backref: backref], From 20328ca84bcdd8188698a3551bf2ff0adf5badbb Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Date: Thu, 13 Dec 2018 18:04:17 +0100 Subject: [PATCH 20/23] [XHarness] Add filtering support to the NUnit and xUnit runners. (#5262) First step to get to the point in which we can filter the execution of the bcl tests via filters. This commit adds the filtering support to the runners, which later will be used by xharness to pass those tests filtered. The end goal is to not skip a complete assembly but just those failing tests. --- .../bcl-test/BCLTests/BCLTests-mac.csproj.in | 9 ++ tests/bcl-test/BCLTests/BCLTests-tv.csproj.in | 9 ++ .../BCLTests-watchos-extension.csproj.in | 9 ++ tests/bcl-test/BCLTests/BCLTests.csproj.in | 9 ++ .../common/TestRunner.Core/TestRunSelector.cs | 12 ++ .../TestRunner.Core/TestRunSelectorType.cs | 12 ++ .../common/TestRunner.Core/TestRunner.cs | 2 + .../ClassOrNamespaceFilter.cs | 79 +++++++++++ .../TestRunner.NUnit/NUnitTestRunner.cs | 61 +++++++- .../common/TestRunner.xUnit/XUnitFilter.cs | 132 +++++++++++++++--- .../TestRunner.xUnit/XUnitFilterType.cs | 7 +- .../TestRunner.xUnit/XUnitTestRunner.cs | 131 +++++++++++++++-- 12 files changed, 434 insertions(+), 38 deletions(-) create mode 100644 tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunSelector.cs create mode 100644 tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunSelectorType.cs create mode 100644 tests/bcl-test/BCLTests/templates/common/TestRunner.NUnit/ClassOrNamespaceFilter.cs diff --git a/tests/bcl-test/BCLTests/BCLTests-mac.csproj.in b/tests/bcl-test/BCLTests/BCLTests-mac.csproj.in index 55e151b5cf..a18b749a96 100644 --- a/tests/bcl-test/BCLTests/BCLTests-mac.csproj.in +++ b/tests/bcl-test/BCLTests/BCLTests-mac.csproj.in @@ -139,6 +139,9 @@ TestRunner.NUnit\NUnitTestRunner.cs + + TestRunner.NUnit\ClassOrNamespaceFilter.cs + TestRunner.Core\Extensions.Bool.cs @@ -166,6 +169,12 @@ TestRunner.Core\TestRunner.cs + + TestRunner.Core\TestRunSelector.cs + + + TestRunner.Core\TestRunSelectorType.cs + TestRunner.xUnit\XUnitFilter.cs diff --git a/tests/bcl-test/BCLTests/BCLTests-tv.csproj.in b/tests/bcl-test/BCLTests/BCLTests-tv.csproj.in index 3194f9b064..9b5e3e2db5 100644 --- a/tests/bcl-test/BCLTests/BCLTests-tv.csproj.in +++ b/tests/bcl-test/BCLTests/BCLTests-tv.csproj.in @@ -210,6 +210,9 @@ TestRunner.NUnit\NUnitTestRunner.cs + + TestRunner.NUnit\ClassOrNamespaceFilter.cs + TestRunner.Core\Extensions.Bool.cs @@ -237,6 +240,12 @@ TestRunner.Core\TestRunner.cs + + TestRunner.Core\TestRunSelector.cs + + + TestRunner.Core\TestRunSelectorType.cs + TestRunner.xUnit\XUnitFilter.cs diff --git a/tests/bcl-test/BCLTests/BCLTests-watchos-extension.csproj.in b/tests/bcl-test/BCLTests/BCLTests-watchos-extension.csproj.in index 3b20fdcd2a..713e59941e 100644 --- a/tests/bcl-test/BCLTests/BCLTests-watchos-extension.csproj.in +++ b/tests/bcl-test/BCLTests/BCLTests-watchos-extension.csproj.in @@ -184,9 +184,18 @@ TestRunner.Core\TestRunner.cs + + TestRunner.Core\TestRunSelector.cs + + + TestRunner.Core\TestRunSelectorType.cs + TestRunner.NUnit\NUnitTestRunner.cs + + TestRunner.NUnit\ClassOrNamespaceFilter.cs + TestRunner.xUnit\XUnitFilter.cs diff --git a/tests/bcl-test/BCLTests/BCLTests.csproj.in b/tests/bcl-test/BCLTests/BCLTests.csproj.in index c11614cc13..62b25cd06c 100644 --- a/tests/bcl-test/BCLTests/BCLTests.csproj.in +++ b/tests/bcl-test/BCLTests/BCLTests.csproj.in @@ -222,6 +222,9 @@ TestRunner.NUnit\NUnitTestRunner.cs + + TestRunner.NUnit\ClassOrNamespaceFilter.cs + TestRunner.Core\Extensions.Bool.cs @@ -249,6 +252,12 @@ TestRunner.Core\TestRunner.cs + + TestRunner.Core\TestRunSelector.cs + + + TestRunner.Core\TestRunSelectorType.cs + TestRunner.xUnit\XUnitFilter.cs diff --git a/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunSelector.cs b/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunSelector.cs new file mode 100644 index 0000000000..f371375d49 --- /dev/null +++ b/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunSelector.cs @@ -0,0 +1,12 @@ +using System; + +namespace Xamarin.iOS.UnitTests +{ + public class TestRunSelector + { + public string Assembly { get; set; } + public string Value { get; set; } + public TestRunSelectorType Type { get; set; } + public bool Include { get; set; } + } +} diff --git a/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunSelectorType.cs b/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunSelectorType.cs new file mode 100644 index 0000000000..67180421c0 --- /dev/null +++ b/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunSelectorType.cs @@ -0,0 +1,12 @@ +using System; + +namespace Xamarin.iOS.UnitTests +{ + public enum TestRunSelectorType + { + Assembly, + Namespace, + Class, + Single, + } +} diff --git a/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunner.cs b/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunner.cs index c080ab2ac0..02372bbd7c 100644 --- a/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunner.cs +++ b/tests/bcl-test/BCLTests/templates/common/TestRunner.Core/TestRunner.cs @@ -17,6 +17,8 @@ namespace Xamarin.iOS.UnitTests public long FilteredTests { get; protected set; } = 0; public bool RunInParallel { get; set; } = false; public string TestsRootDirectory { get; set; } + public bool RunAllTestsByDefault { get; set; } = true; + public bool LogExcludedTests { get; set; } public TextWriter Writer { get; set; } public List FailureInfos { get; } = new List (); diff --git a/tests/bcl-test/BCLTests/templates/common/TestRunner.NUnit/ClassOrNamespaceFilter.cs b/tests/bcl-test/BCLTests/templates/common/TestRunner.NUnit/ClassOrNamespaceFilter.cs new file mode 100644 index 0000000000..7e5552f2ee --- /dev/null +++ b/tests/bcl-test/BCLTests/templates/common/TestRunner.NUnit/ClassOrNamespaceFilter.cs @@ -0,0 +1,79 @@ +using System; +using System.Collections.Generic; + +using NUnit.Framework.Api; +using NUnit.Framework.Internal; +using NUnit.Framework.Internal.Filters; + +namespace Xamarin.iOS.UnitTests.NUnit +{ + public class ClassOrNamespaceFilter : TestFilter + { + bool isClassFilter; + List names; + + public ClassOrNamespaceFilter (string name, bool isClassFilter) + { + AddName (name); + this.isClassFilter = isClassFilter; + } + + public ClassOrNamespaceFilter (IEnumerable names, bool isClassFilter) + { + if (names == null) + throw new ArgumentNullException (nameof (names)); + + this.isClassFilter = isClassFilter; + foreach (string n in names) { + string name = n?.Trim (); + if (String.IsNullOrEmpty (name)) + continue; + + AddName (name); + } + } + + public void AddName (string name) + { + if (String.IsNullOrEmpty (name)) + throw new ArgumentException ("must not be null or empty", nameof (name)); + + if (names == null) + names = new List (); + if (names.Contains (name)) + return; + + names.Add (name); + } + + public override bool Match (ITest test) + { + if (test == null || names == null || names.Count == 0) + return false; + + if (test.FixtureType == null) + return false; // It's probably an assembly name, all tests will have a fixture + + if (isClassFilter) + return NameMatches (test.FixtureType.FullName); + + int dot = test.FixtureType.FullName.LastIndexOf ('.'); + if (dot < 1) + return false; + + return NameMatches (test.FixtureType.FullName.Substring (0, dot)); + } + + bool NameMatches (string name) + { + foreach (string n in names) { + if (n == null) + continue; + if (String.Compare (name, n, StringComparison.Ordinal) == 0) + return true; + } + + return false; + } + } +} diff --git a/tests/bcl-test/BCLTests/templates/common/TestRunner.NUnit/NUnitTestRunner.cs b/tests/bcl-test/BCLTests/templates/common/TestRunner.NUnit/NUnitTestRunner.cs index 6f57573f7d..0f8ccf75d4 100644 --- a/tests/bcl-test/BCLTests/templates/common/TestRunner.NUnit/NUnitTestRunner.cs +++ b/tests/bcl-test/BCLTests/templates/common/TestRunner.NUnit/NUnitTestRunner.cs @@ -1,7 +1,8 @@ -using System; -using System.IO; +using System; using System.Collections; using System.Collections.Generic; +using System.IO; +using System.Linq; using System.Reflection; using System.Text; @@ -21,9 +22,11 @@ namespace Xamarin.iOS.UnitTests.NUnit { Dictionary builderSettings; TestSuiteResult results; + bool runAssemblyByDefault; public ITestFilter Filter { get; set; } = TestFilter.Empty; public bool GCAfterEachFixture { get; set; } + public Dictionary AssemblyFilters { get; set; } protected override string ResultsFileName { get; set; } = "TestResults.NUnit.xml"; @@ -36,23 +39,31 @@ namespace Xamarin.iOS.UnitTests.NUnit { if (testAssemblies == null) throw new ArgumentNullException (nameof (testAssemblies)); - + + if (AssemblyFilters == null || AssemblyFilters.Count == 0) + runAssemblyByDefault = true; + else + runAssemblyByDefault = AssemblyFilters.Values.Any (v => !v); + var builder = new NUnitLiteTestAssemblyBuilder (); var runner = new NUnitLiteTestAssemblyRunner (builder, new FinallyDelegate ()); var testSuite = new TestSuite (NSBundle.MainBundle.BundleIdentifier); results = new TestSuiteResult (testSuite); + TotalTests = 0; foreach (TestAssemblyInfo assemblyInfo in testAssemblies) { - if (assemblyInfo == null || assemblyInfo.Assembly == null) + if (assemblyInfo == null || assemblyInfo.Assembly == null || !ShouldRunAssembly (assemblyInfo)) continue; - + if (!runner.Load (assemblyInfo.Assembly, builderSettings)) { OnWarning ($"Failed to load tests from assembly '{assemblyInfo.Assembly}"); continue; } - if (runner.LoadedTest is NUnitTest tests) + if (runner.LoadedTest is NUnitTest tests) { + TotalTests += tests.TestCaseCount; testSuite.Add (tests); - + } + // Messy API. .Run returns ITestResult which is, in reality, an instance of TestResult since that's // what WorkItem returns and we need an instance of TestResult to add it to TestSuiteResult. So, cast // the return to TestResult and hope for the best. @@ -73,9 +84,45 @@ namespace Xamarin.iOS.UnitTests.NUnit results.AddResult (testResult); } + // NUnitLite doesn't report filtered tests at all, but we can calculate here + FilteredTests = TotalTests - ExecutedTests; LogFailureSummary (); } + bool ShouldRunAssembly (TestAssemblyInfo assemblyInfo) + { + if (assemblyInfo == null) + return false; + + if (AssemblyFilters == null || AssemblyFilters.Count == 0) + return true; + + bool include; + if (AssemblyFilters.TryGetValue (assemblyInfo.FullPath, out include)) + return ReportFilteredAssembly (assemblyInfo, include); + + string fileName = Path.GetFileName (assemblyInfo.FullPath); + if (AssemblyFilters.TryGetValue (fileName, out include)) + return ReportFilteredAssembly (assemblyInfo, include); + + fileName = Path.GetFileNameWithoutExtension (assemblyInfo.FullPath); + if (AssemblyFilters.TryGetValue (fileName, out include)) + return ReportFilteredAssembly (assemblyInfo, include); + + return runAssemblyByDefault; + } + + bool ReportFilteredAssembly (TestAssemblyInfo assemblyInfo, bool include) + { + if (LogExcludedTests) { + const string included = "Included"; + const string excluded = "Excluded"; + + OnInfo ($"[FILTER] {(include ? included : excluded)} assembly: {assemblyInfo.FullPath}"); + } + return include; + } + public bool Pass (ITest test) { return true; diff --git a/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitFilter.cs b/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitFilter.cs index 48e1337479..e4731e453d 100644 --- a/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitFilter.cs +++ b/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitFilter.cs @@ -1,28 +1,128 @@ -using System; +using System; +using System.Text; namespace Xamarin.iOS.UnitTests.XUnit { public class XUnitFilter { - public string TraitName { get; } - public string TraitValue { get; } - public string TestCaseName { get; } - public bool Exclude { get; } - public XUnitFilterType FilterType { get; } + public string AssemblyName { get; private set; } + public string SelectorName { get; private set; } + public string SelectorValue { get; private set; } - public XUnitFilter (string testCaseName, bool exclude) + public bool Exclude { get; private set; } + public XUnitFilterType FilterType { get; private set; } + + public static XUnitFilter CreateSingleFilter (string singleTestName, bool exclude, string assemblyName = null) { - FilterType = XUnitFilterType.TypeName; - TestCaseName = testCaseName; - Exclude = exclude; + if (String.IsNullOrEmpty (singleTestName)) + throw new ArgumentException("must not be null or empty", nameof (singleTestName)); + + return new XUnitFilter { + AssemblyName = assemblyName, + SelectorValue = singleTestName, + FilterType = XUnitFilterType.Single, + Exclude = exclude + }; } - public XUnitFilter (string traitName, string traitValue, bool exclude) + public static XUnitFilter CreateAssemblyFilter (string assemblyName, bool exclude) { - FilterType = XUnitFilterType.Trait; - TraitName = traitName; - TraitValue = traitValue; - Exclude = exclude; + if (String.IsNullOrEmpty (assemblyName)) + throw new ArgumentException("must not be null or empty", nameof (assemblyName)); + + return new XUnitFilter { + AssemblyName = assemblyName, + FilterType = XUnitFilterType.Assembly, + Exclude = exclude + }; + } + + public static XUnitFilter CreateNamespaceFilter (string namespaceName, bool exclude, string assemblyName = null) + { + if (String.IsNullOrEmpty (namespaceName)) + throw new ArgumentException("must not be null or empty", nameof (namespaceName)); + + return new XUnitFilter { + AssemblyName = assemblyName, + SelectorValue = namespaceName, + FilterType = XUnitFilterType.Namespace, + Exclude = exclude + }; + } + + public static XUnitFilter CreateClassFilter (string className, bool exclude, string assemblyName = null) + { + if (String.IsNullOrEmpty (className)) + throw new ArgumentException("must not be null or empty", nameof (className)); + + return new XUnitFilter { + AssemblyName = assemblyName, + SelectorValue = className, + FilterType = XUnitFilterType.TypeName, + Exclude = exclude + }; + } + + public static XUnitFilter CreateTraitFilter (string traitName, string traitValue, bool exclude) + { + if (String.IsNullOrEmpty (traitName)) + throw new ArgumentException("must not be null or empty", nameof (traitName)); + + return new XUnitFilter { + AssemblyName = null, + SelectorName = traitName, + SelectorValue = traitValue ?? String.Empty, + FilterType = XUnitFilterType.Trait, + Exclude = exclude + }; + } + + public override string ToString () + { + var sb = new StringBuilder ("XUnitFilter ["); + + sb.Append ($"Type: {FilterType}; "); + sb.Append (Exclude ? "exclude" : "include"); + + if (!String.IsNullOrEmpty (AssemblyName)) + sb.Append ($"; AssemblyName: {AssemblyName}"); + + switch (FilterType) { + case XUnitFilterType.Assembly: + break; + + case XUnitFilterType.Namespace: + AppendDesc ("Namespace", SelectorValue); + break; + + case XUnitFilterType.Single: + AppendDesc ("Method", SelectorValue); + break; + + case XUnitFilterType.Trait: + AppendDesc ("Trait name", SelectorName); + AppendDesc ("Trait value", SelectorValue); + break; + + case XUnitFilterType.TypeName: + AppendDesc ("Class", SelectorValue); + break; + + default: + sb.Append ("; Unknown filter type"); + break; + } + sb.Append (']'); + + return sb.ToString (); + + void AppendDesc (string name, string value) + { + if (String.IsNullOrEmpty (value)) + return; + + sb.Append ($"; {name}: {value}"); + } } } -} \ No newline at end of file +} diff --git a/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitFilterType.cs b/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitFilterType.cs index 2d1d7070ea..4cd3021208 100644 --- a/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitFilterType.cs +++ b/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitFilterType.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace Xamarin.iOS.UnitTests.XUnit { @@ -6,5 +6,8 @@ namespace Xamarin.iOS.UnitTests.XUnit { Trait, TypeName, + Assembly, + Single, + Namespace, } -} \ No newline at end of file +} diff --git a/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitTestRunner.cs b/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitTestRunner.cs index 37e44a8295..b84f69df41 100644 --- a/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitTestRunner.cs +++ b/tests/bcl-test/BCLTests/templates/common/TestRunner.xUnit/XUnitTestRunner.cs @@ -19,6 +19,7 @@ namespace Xamarin.iOS.UnitTests.XUnit XElement assembliesElement; List filters; + bool runAssemblyByDefault; public XUnitResultFileFormat ResultFileFormat { get; set; } = XUnitResultFileFormat.NUnit; public AppDomainSupport AppDomainSupport { get; set; } = AppDomainSupport.Denied; @@ -677,9 +678,23 @@ namespace Xamarin.iOS.UnitTests.XUnit if (testAssemblies == null) throw new ArgumentNullException (nameof (testAssemblies)); + if (filters != null && filters.Count > 0) { + do_log ("Configured filters:"); + foreach (XUnitFilter filter in filters) { + do_log ($" {filter}"); + } + } + + List assemblyFilters = filters?.Where (sel => sel != null && sel.FilterType == XUnitFilterType.Assembly)?.ToList (); + if (assemblyFilters == null || assemblyFilters.Count == 0) { + runAssemblyByDefault = true; + assemblyFilters = null; + } else + runAssemblyByDefault = assemblyFilters.Any (f => f != null && f.Exclude); + assembliesElement = new XElement ("assemblies"); foreach (TestAssemblyInfo assemblyInfo in testAssemblies) { - if (assemblyInfo == null || assemblyInfo.Assembly == null) + if (assemblyInfo == null || assemblyInfo.Assembly == null || !ShouldRunAssembly (assemblyInfo)) continue; if (String.IsNullOrEmpty (assemblyInfo.FullPath)) { @@ -703,6 +718,50 @@ namespace Xamarin.iOS.UnitTests.XUnit } LogFailureSummary (); + + bool ShouldRunAssembly (TestAssemblyInfo assemblyInfo) + { + if (assemblyInfo == null) + return false; + + if (assemblyFilters == null) + return true; + + foreach (XUnitFilter filter in assemblyFilters) { + if (String.Compare (filter.AssemblyName, assemblyInfo.FullPath, StringComparison.Ordinal) == 0) + return ReportFilteredAssembly (assemblyInfo, filter); + + string fileName = Path.GetFileName (assemblyInfo.FullPath); + if (String.Compare (fileName, filter.AssemblyName, StringComparison.Ordinal) == 0) + return ReportFilteredAssembly (assemblyInfo, filter); + + string filterExtension = Path.GetExtension (filter.AssemblyName); + if (String.IsNullOrEmpty (filterExtension) || + (String.Compare (filterExtension, ".exe", StringComparison.OrdinalIgnoreCase) != 0 && + String.Compare (filterExtension, ".dll", StringComparison.OrdinalIgnoreCase) != 0)) { + string asmName = $"{filter.AssemblyName}.dll"; + if (String.Compare (asmName, fileName, StringComparison.Ordinal) == 0) + return ReportFilteredAssembly (assemblyInfo, filter); + + asmName = $"{filter.AssemblyName}.exe"; + if (String.Compare (asmName, fileName, StringComparison.Ordinal) == 0) + return ReportFilteredAssembly (assemblyInfo, filter); + } + } + + return runAssemblyByDefault; + } + + bool ReportFilteredAssembly (TestAssemblyInfo assemblyInfo, XUnitFilter filter) + { + if (LogExcludedTests) { + const string included = "Included"; + const string excluded = "Excluded"; + + OnInfo ($"[FILTER] {(filter.Exclude ? excluded : included)} assembly: {assemblyInfo.FullPath}"); + } + return !filter.Exclude; + } } public override string WriteResultsToFile () @@ -863,42 +922,88 @@ namespace Xamarin.iOS.UnitTests.XUnit bool IsIncluded (ITestCase testCase) { - if (testCase.Traits == null || testCase.Traits.Count == 0) - return true; - + if (testCase == null) + return false; + + bool haveTraits = testCase.Traits != null && testCase.Traits.Count > 0; foreach (XUnitFilter filter in filters) { List values; if (filter == null) continue; if (filter.FilterType == XUnitFilterType.Trait) { - if (!testCase.Traits.TryGetValue (filter.TraitName, out values)) + if (!haveTraits || !testCase.Traits.TryGetValue (filter.SelectorName, out values)) continue; if (values == null || values.Count == 0) { // We have no values and the filter doesn't specify one - that means we match on // the trait name only. - if (String.IsNullOrEmpty (filter.TraitValue)) - return !filter.Exclude; + if (String.IsNullOrEmpty (filter.SelectorValue)) + return ReportFilteredTest (filter); continue; } - if (values.Contains (filter.TraitValue, StringComparer.OrdinalIgnoreCase)) - return !filter.Exclude; + if (values.Contains (filter.SelectorValue, StringComparer.OrdinalIgnoreCase)) + return ReportFilteredTest (filter); continue; } if (filter.FilterType == XUnitFilterType.TypeName) { - Logger.Info ($"IsIncluded: filter: '{filter.TestCaseName}', test case name: {testCase.DisplayName}"); - if (String.Compare (testCase.DisplayName, filter.TestCaseName, StringComparison.OrdinalIgnoreCase) == 0) - return !filter.Exclude; + string testClassName = testCase.TestMethod?.TestClass?.Class?.Name?.Trim (); + if (String.IsNullOrEmpty (testClassName)) + continue; + + if (String.Compare (testClassName, filter.SelectorValue, StringComparison.OrdinalIgnoreCase) == 0) + return ReportFilteredTest (filter); continue; } + if (filter.FilterType == XUnitFilterType.Single) { + if (String.Compare (testCase.DisplayName, filter.SelectorValue, StringComparison.OrdinalIgnoreCase) == 0) + return ReportFilteredTest (filter); + continue; + } + + if (filter.FilterType == XUnitFilterType.Namespace) { + string testClassName = testCase.TestMethod?.TestClass?.Class?.Name?.Trim (); + if (String.IsNullOrEmpty (testClassName)) + continue; + + int dot = testClassName.LastIndexOf ('.'); + if (dot <= 0) + continue; + + string testClassNamespace = testClassName.Substring (0, dot); + if (String.Compare (testClassNamespace, filter.SelectorValue, StringComparison.OrdinalIgnoreCase) == 0) + return ReportFilteredTest (filter); + continue; + } + + if (filter.FilterType == XUnitFilterType.Assembly) { + continue; // Ignored: handled elsewhere + } + throw new InvalidOperationException ($"Unsupported filter type {filter.FilterType}"); } - return true; + return RunAllTestsByDefault; + + bool ReportFilteredTest (XUnitFilter filter) + { + if (LogExcludedTests) { + const string included = "Included"; + const string excluded = "Excluded"; + + string selector; + if (filter.FilterType == XUnitFilterType.Trait) + selector = $"'{filter.SelectorName}':'{filter.SelectorValue}'"; + else + selector = $"'{filter.SelectorValue}'"; + + do_log ($"[FILTER] {(filter.Exclude ? excluded : included)} test (filtered by {filter.FilterType}; {selector}): {testCase.DisplayName}"); + } + return !filter.Exclude; + } } } } From b51e8ecfc8bfb8713559c70072a167800819aa8f Mon Sep 17 00:00:00 2001 From: Manuel de la Pena Date: Fri, 14 Dec 2018 11:31:35 +0100 Subject: [PATCH 21/23] [CFNetwork] Fix CVE 2018-8292 on Mac OS X. (#5271) The MessageHandler class suffers from the CVE 2018-8292. this commit fixes the issue by ensuring that the we donot use autoredirect from CFNetwork and perform the first request. If the response is a redirect, follow it wihout the Autherization headers. --- src/CFNetwork/MessageHandler.cs | 51 ++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 11 deletions(-) diff --git a/src/CFNetwork/MessageHandler.cs b/src/CFNetwork/MessageHandler.cs index da0275d347..7e4faeb715 100644 --- a/src/CFNetwork/MessageHandler.cs +++ b/src/CFNetwork/MessageHandler.cs @@ -41,6 +41,7 @@ using Foundation; namespace CFNetwork { + [Obsolete ("Use 'System.Net.Http.CFNetworkHandler' or the more recent 'Foundation.NSUrlSessionHandler' instead.")] public class MessageHandler : HttpClientHandler { public MessageHandler () { @@ -86,19 +87,19 @@ namespace CFNetwork { if (!request.RequestUri.IsAbsoluteUri) throw new InvalidOperationException (); - using (var message = CreateRequest (request)) { + using (var message = CreateRequest (request, true)) { var body = await CreateBody (request, message, cancellationToken); - return await ProcessRequest (request, message, body, true, cancellationToken); + return await ProcessRequest (request, message, body, true, cancellationToken, true); } } #endregion - CFHTTPMessage CreateRequest (HttpRequestMessage request) + CFHTTPMessage CreateRequest (HttpRequestMessage request, bool isFirstRequest) { var message = CFHTTPMessage.CreateRequest ( request.RequestUri, request.Method.Method, request.Version); - SetupRequest (request, message); + SetupRequest (request, message, isFirstRequest); if ((auth == null) || (Credentials == null) || !PreAuthenticate) return message; @@ -111,11 +112,12 @@ namespace CFNetwork { if (credential == null) return message; - message.ApplyCredentials (auth, credential); + if (isFirstRequest) + message.ApplyCredentials (auth, credential); return message; } - void SetupRequest (HttpRequestMessage request, CFHTTPMessage message) + void SetupRequest (HttpRequestMessage request, CFHTTPMessage message, bool isFirstRequest) { string accept_encoding = null; if ((AutomaticDecompression & DecompressionMethods.GZip) != 0) @@ -127,6 +129,8 @@ namespace CFNetwork { if (request.Content != null) { foreach (var header in request.Content.Headers) { + if (!isFirstRequest && header.Key == "Authorization") + continue; var value = string.Join (",", header.Value); message.SetHeaderFieldValue (header.Key, value); } @@ -190,12 +194,23 @@ namespace CFNetwork { return request.Headers.Contains ("Keep-Alive"); } + + // Decide if we redirect or not, similar to what is done in the managed handler + // https://github.com/mono/mono/blob/eca15996c7163f331c9f2cd0a17b63e8f92b1d55/mcs/class/referencesource/System/net/System/Net/HttpWebRequest.cs#L5681 + static bool IsRedirect (HttpStatusCode status) + { + return status == HttpStatusCode.Ambiguous || // 300 + status == HttpStatusCode.Moved || // 301 + status == HttpStatusCode.Redirect || // 302 + status == HttpStatusCode.RedirectMethod || // 303 + status == HttpStatusCode.RedirectKeepVerb; // 307 + } async Task ProcessRequest (HttpRequestMessage request, CFHTTPMessage message, WebRequestStream body, bool retryWithCredentials, - CancellationToken cancellationToken) + CancellationToken cancellationToken, bool isFirstRequest) { cancellationToken.ThrowIfCancellationRequested (); @@ -210,21 +225,35 @@ namespace CFNetwork { request.RequestUri) ); - stream.Stream.ShouldAutoredirect = AllowAutoRedirect; + if (!isFirstRequest) + stream.Stream.ShouldAutoredirect = AllowAutoRedirect; stream.Stream.AttemptPersistentConnection = GetKeepAlive (request); var response = await stream.Open ( - WorkerThread, cancellationToken).ConfigureAwait (false); + WorkerThread, cancellationToken).ConfigureAwait (true); // with false, we will have a deadlock. var status = (HttpStatusCode)response.ResponseStatusCode; + if ( IsRedirect (status)) { + request.Headers.Authorization = null; + stream.Dispose (); + // we cannot reuse the message, will deadlock and also the message.ApplyCredentials (auth, credential); + // was called the first time + using (var retryMsg = CreateRequest (request, false)) { + return await ProcessRequest ( + request, retryMsg, null, false, cancellationToken, false); + } + + } if (retryWithCredentials && (body == null) && (status == HttpStatusCode.Unauthorized) || (status == HttpStatusCode.ProxyAuthenticationRequired)) { if (HandleAuthentication (request.RequestUri, message, response)) { stream.Dispose (); - return await ProcessRequest ( - request, message, null, false, cancellationToken); + using (var retryMsg = CreateRequest (request, true)) { // behave as if it was the first attempt + return await ProcessRequest ( + request, message, null, false, cancellationToken, true); // behave as if it was the first attempt + } } } From 68049f918097035c1e7d847fc7cd7c9e8fab96e4 Mon Sep 17 00:00:00 2001 From: Chris Hamons Date: Fri, 14 Dec 2018 09:37:58 -0500 Subject: [PATCH 22/23] [tests] Remove NoBindingEmbedding rebuild tests (#5274) - These tests failed randomly, especially on older macOS without APFS - They also were rather slow --- .../src/BindingProjectNoEmbeddingTests.cs | 91 ------------------- 1 file changed, 91 deletions(-) diff --git a/tests/mmptest/src/BindingProjectNoEmbeddingTests.cs b/tests/mmptest/src/BindingProjectNoEmbeddingTests.cs index b48f57fb62..fd491c77a1 100644 --- a/tests/mmptest/src/BindingProjectNoEmbeddingTests.cs +++ b/tests/mmptest/src/BindingProjectNoEmbeddingTests.cs @@ -75,97 +75,6 @@ namespace Xamarin.MMP.Tests }); } - [TestCase (true)] - [TestCase (false)] - public void ShouldNotUnnecessarilyRebuildBindingProject (bool framework) - { - MMPTests.RunMMPTest (tmpDir => { - var projects = BindingProjectTests.GenerateTestProject (BindingProjectType.Modern, tmpDir); - BindingProjectTests.SetNoEmbedding (projects.Item1); - - string projectPath = Path.Combine (tmpDir, "MobileBinding.csproj"); - string bindingFilePath = Path.Combine (tmpDir, "ApiDefinition.cs"); - const string CreatePackageString = "Creating binding resource package"; - - // First build should create a package - string frameworkPath = null; - - if (framework) { - frameworkPath = FrameworkBuilder.CreateThinFramework (tmpDir); - projects.Item1.ItemGroup += NativeReferenceTests.CreateSingleNativeRef (Path.GetFullPath (frameworkPath), "Framework"); - } - string libBuildLog = BindingProjectTests.SetupAndBuildBindingProject (projects.Item1, setupDefaultNativeReference: !framework); - - Assert.True (libBuildLog.Contains (CreatePackageString), $"First build did not create package? {TI.PrintRedirectIfLong (libBuildLog)}"); - - // No change build should not - libBuildLog = TI.BuildProject (projectPath, true); - Assert.False (libBuildLog.Contains (CreatePackageString), $"Rebuild build did create package? {TI.PrintRedirectIfLong (libBuildLog)}"); - - // Touching the binding project should - Touch (projectPath); - libBuildLog = TI.BuildProject (projectPath, true); - Assert.True (libBuildLog.Contains (CreatePackageString), $"Binding Project build did not create package? {TI.PrintRedirectIfLong (libBuildLog)}"); - - // Touching the binding file should - Touch (bindingFilePath); - libBuildLog = TI.BuildProject (projectPath, true); - Assert.True (libBuildLog.Contains (CreatePackageString), $"Binding File build did not create package? {TI.PrintRedirectIfLong (libBuildLog)}"); - - // No change build should not - libBuildLog = TI.BuildProject (projectPath, true); - Assert.False (libBuildLog.Contains (CreatePackageString), $"Second Rebuild build did create package? {TI.PrintRedirectIfLong (libBuildLog)}"); - - // Touching native library should - Touch (framework ? frameworkPath + "/Foo" : NativeReferenceTests.SimpleDylibPath); - libBuildLog = TI.BuildProject (projectPath, true); - Assert.True (libBuildLog.Contains (CreatePackageString), $"Native Library build did not create package? {TI.PrintRedirectIfLong (libBuildLog)}"); - }); - } - - [TestCase (true, true)] - [TestCase (true, false)] - [TestCase (false, true)] - [TestCase (false, false)] - public void ShouldNotUnnecessarilyRebuildFinalProject (bool useProjectReference, bool framework) - { - MMPTests.RunMMPTest (tmpDir => { - var projects = BindingProjectTests.GenerateTestProject (BindingProjectType.Modern, tmpDir); - BindingProjectTests.SetNoEmbedding (projects.Item1); - - const string BuildString = "xcrun -sdk macosx clang"; - - string frameworkPath = null; - if (framework) { - frameworkPath = FrameworkBuilder.CreateThinFramework (tmpDir); - projects.Item1.ItemGroup += NativeReferenceTests.CreateSingleNativeRef (Path.GetFullPath (frameworkPath), "Framework"); - } - string appBuildLog = BindingProjectTests.SetupAndBuildLinkedTestProjects (projects.Item1, projects.Item2, tmpDir, useProjectReference, setupDefaultNativeReference: !framework).Item2; - - Assert.True (appBuildLog.Contains (BuildString), $"First build did not run mmp? {TI.PrintRedirectIfLong (appBuildLog)}"); - - string projectPath = Path.Combine (tmpDir, "UnifiedExample.csproj"); - string mainPath = Path.Combine (tmpDir, "Main.cs"); - - // No change build should not - string buildLog = TI.BuildProject (projectPath, true); - Assert.False (buildLog.Contains (BuildString), $"Rebuild ran mmp again? {TI.PrintRedirectIfLong (buildLog)}"); - - if (useProjectReference) { - // Touching the binding definition should - Touch (Path.Combine (tmpDir, "ApiDefinition.cs")); - buildLog = TI.BuildProject (projectPath, true); - Assert.True (buildLog.Contains (BuildString), $"Binding definition build did not run mmp again? {TI.PrintRedirectIfLong (buildLog)}"); - } - else { - // Touching the binding assembly should - Touch (Path.Combine (tmpDir, "bin/Debug/MobileBinding.dll")); - buildLog = TI.BuildProject (projectPath, true); - Assert.True (buildLog.Contains (BuildString), $"Binding build did not run mmp again? {TI.PrintRedirectIfLong (buildLog)}"); - } - }); - } - [TestCase (true)] [TestCase (false)] public void MultipleNativeReferences (bool useProjectReference) From d205f2215b3529d05ae4ef24b82c2df35f8efe06 Mon Sep 17 00:00:00 2001 From: Rolf Bjarne Kvinge Date: Mon, 17 Dec 2018 10:22:54 +0100 Subject: [PATCH 23/23] [builds] Consume llvm + cross compilers from mono's package. (#5254) * [builds] Consume LLVM from mono's package. * Fix mono sdk paths in makefile to be relative to the top. * [builds] Make curl verbose if V=1. * [builds] Improve llvm build targets. * Fix dependencies so that 'make -j llvm' (and other variations of the same target) work properly. * Rename things a bit to make it clear there are 32-bit and 64-bit llvm targets. * [builds] Consume cross compilers from mono's package as well. Compiling the cross compilers while using LLVM from mono's package becomes complicated, so just go ahead and get the cross compilers from the mono package as well. * Make llvm rules symmetric between llvm32 and llvm64. --- Make.config | 4 ++-- builds/Makefile | 63 +++++++++++++++++++++++++++---------------------- 2 files changed, 37 insertions(+), 30 deletions(-) diff --git a/Make.config b/Make.config index aba0452797..16f352f5ec 100644 --- a/Make.config +++ b/Make.config @@ -331,8 +331,8 @@ ifeq ($(MONO_BUILD_FROM_SOURCE),) MONO_HASH:=$(shell git --git-dir=$(abspath $(TOP)/.git) --work-tree=$(abspath $(TOP)) ls-tree HEAD --full-tree -- external/mono | awk -F' ' '{printf "%s",$$3}') MONO_FILENAME:=ios-release-Darwin-$(MONO_HASH).zip MONO_URL:=https://xamjenkinsartifact.azureedge.net/mono-sdks/$(MONO_FILENAME) -MONO_SDK_BUILDDIR:=$(abspath builds/downloads/$(basename $(MONO_FILENAME))) -MONO_SDK_DESTDIR:=$(abspath builds/downloads/$(basename $(MONO_FILENAME))) +MONO_SDK_BUILDDIR:=$(abspath $(TOP)/builds/downloads/$(basename $(MONO_FILENAME))) +MONO_SDK_DESTDIR:=$(abspath $(TOP)/builds/downloads/$(basename $(MONO_FILENAME))) MONO_BUILD_MODE=download else MONO_SDK_BUILDDIR:=$(abspath $(MONO_PATH)/sdks/builds) diff --git a/builds/Makefile b/builds/Makefile index 1b583ca20e..bbfd80aeb9 100644 --- a/builds/Makefile +++ b/builds/Makefile @@ -8,7 +8,7 @@ download: downloads/$(basename $(MONO_FILENAME)) downloads/$(MONO_FILENAME): $(Q) mkdir -p downloads $(Q) echo "Downloading $(MONO_URL)..." - $(Q) curl -s -f -L $(MONO_URL) --output $@.tmp + $(Q) curl -f -L $(if $(V),-v,-s) $(MONO_URL) --output $@.tmp $(Q) mv $@.tmp $@ $(Q) echo "Downloaded $(MONO_URL)" @@ -1429,48 +1429,53 @@ ifdef INCLUDE_DEVICE clean-local:: clean-llvm endif -build-llvm32: .stamp-build-llvm .stamp-build-llvm32 -build-llvm64: .stamp-build-llvm .stamp-build-llvm32 +build-llvm32: .stamp-build-llvm32 +build-llvm64: .stamp-build-llvm64 -.stamp-build-llvm: $(SDK_CONFIG) - $(MAKE) -C $(SDK_BUILDDIR) provision-llvm-llvm64 $(SDK_ARGS) +.stamp-compile-llvm64: $(SDK_CONFIG) + $(MAKE) -C $(MONO_SDK_BUILDDIR) provision-llvm-llvm64 $(SDK_ARGS) $(Q) touch $@ -.stamp-build-llvm32: $(SDK_CONFIG) - $(MAKE) -C $(SDK_BUILDDIR) provision-llvm36-llvm32 $(SDK32_ARGS) +.stamp-compile-llvm32: $(SDK_CONFIG) + $(MAKE) -C $(MONO_SDK_BUILDDIR) provision-llvm36-llvm32 $(SDK32_ARGS) $(Q) touch $@ +.stamp-build-llvm64: .stamp-$(MONO_BUILD_MODE)-llvm64 +.stamp-build-llvm32: .stamp-$(MONO_BUILD_MODE)-llvm32 + clean-llvm: $(SDK_CONFIG) - $(MAKE) -C $(SDK_BUILDDIR) clean-llvm36-llvm32 clean-llvm-llvm64 $(SDK_ARGS) + $(MAKE) -C $(MONO_SDK_BUILDDIR) clean-llvm36-llvm32 clean-llvm-llvm64 $(SDK_ARGS) $(RM) .stamp-*-llvm* -.PHONY: install-llvm64 llvm llvm64 +.PHONY: install-llvm64 install-llvm32 llvm32 llvm64 -install-llvm: install-llvm32 install-llvm64 - -LLVM_TARGETS = \ +LLVM64_TARGETS = \ $(PREFIX)/LLVM/bin/opt \ $(PREFIX)/LLVM/bin/llc \ + +LLVM32_TARGETS = \ $(PREFIX)/LLVM36/bin/opt \ - $(PREFIX)/LLVM36/bin/llc + $(PREFIX)/LLVM36/bin/llc \ -$(PREFIX)/LLVM/bin/%: $(SDK_DESTDIR)/llvm-llvm64/bin/% | $(PREFIX)/LLVM/bin +$(MONO_SDK_DESTDIR)/llvm-llvm64/bin/%: .stamp-build-llvm64; @true +$(MONO_SDK_DESTDIR)/llvm36-llvm32/bin/%: .stamp-build-llvm32; @true + +$(PREFIX)/LLVM/bin/%: $(MONO_SDK_DESTDIR)/llvm-llvm64/bin/% | $(PREFIX)/LLVM/bin $(call Q_2,INSTALL ,[LLVM64]) install -c -m 0755 $(INSTALL_STRIP_FLAG) $^ $@ -$(PREFIX)/LLVM36/bin/%: $(SDK_DESTDIR)/llvm36-llvm32/bin/% | $(PREFIX)/LLVM36/bin - $(call Q_2,INSTALL ,[LLVM64]) install -c -m 0755 $(INSTALL_STRIP_FLAG) $^ $@ +$(PREFIX)/LLVM36/bin/%: $(MONO_SDK_DESTDIR)/llvm36-llvm32/bin/% | $(PREFIX)/LLVM36/bin + $(call Q_2,INSTALL ,[LLVM32]) install -c -m 0755 $(INSTALL_STRIP_FLAG) $^ $@ -$(PREFIX)/LLVM/bin: +$(PREFIX)/LLVM/bin $(PREFIX)/LLVM36/bin: $(Q) mkdir -p $@ -$(PREFIX)/LLVM36/bin: - $(Q) mkdir -p $@ +install-llvm: install-llvm32 install-llvm64 +install-llvm32: $(LLVM32_TARGETS) +install-llvm64: $(LLVM64_TARGETS) -install-llvm32:.stamp-build-llvm .stamp-build-llvm32 $(LLVM_TARGETS) -install-llvm64: .stamp-build-llvm .stamp-build-llvm32 $(LLVM_TARGETS) - -llvm: build-llvm64 install-llvm +llvm: install-llvm llvm64: install-llvm64 +llvm32: install-llvm32 $(MONO_PATH)/tools/offsets-tool/MonoAotOffsetsDumper.exe: $(MONO_PATH)/configure $(wildcard $(MONO_PATH)/tools/offsets-tool/*.cs) $(Q) $(MAKE) -C $(dir $@) MonoAotOffsetsDumper.exe @@ -1504,10 +1509,12 @@ build:: build-$(1) install-local:: install-$(1) clean-local:: clean-$(1) -.stamp-build-$(1): .stamp-build-llvm .stamp-build-llvm32 $(MONO_PATH)/configure $(MONO_PATH)/tools/offsets-tool/MonoAotOffsetsDumper.exe $(MONO_DEPENDENCIES) $(SDK_CONFIG) - $(MAKE) -C $(SDK_BUILDDIR) package-ios-$(1) $(SDK_ARGS) $(if $(5), XCODE_DIR=$(5)) +.stamp-compile-$(1): .stamp-build-llvm64 .stamp-build-llvm32 $(MONO_PATH)/configure $(MONO_PATH)/tools/offsets-tool/MonoAotOffsetsDumper.exe $(MONO_DEPENDENCIES) $(SDK_CONFIG) + $(MAKE) -C $(MONO_SDK_BUILDDIR) package-ios-$(1) $(SDK_ARGS) $(if $(5), XCODE_DIR=$(5)) $(Q) touch $$@ +.stamp-build-$(1): .stamp-$(MONO_BUILD_MODE)-$(1) + build-$(1): .stamp-build-$(1) _$(1)_CROSS_TARGETS = \ @@ -1515,14 +1522,14 @@ _$(1)_CROSS_TARGETS = \ $(SDK_DESTDIR)/ios-$(1)/bin/$(4): .stamp-build-$(1) -$(PREFIX)/bin/$(3): $(SDK_DESTDIR)/ios-$(1)-release/bin/$(4) | $(PREFIX)/bin +$(PREFIX)/bin/$(3): $(MONO_SDK_DESTDIR)/ios-$(1)-release/bin/$(4) | $(PREFIX)/bin $(call Q_2,INSTALL ,[CROSS]) install -c -m 0755 $(INSTALL_STRIP_FLAG) $$< $$@ install-$(1): install-$(2) $$(_$(1)_CROSS_TARGETS) clean-$(1): $(SDK_CONFIG) - $(MAKE) -C $(SDK_BUILDDIR) clean-ios-$(1) $(SDK_ARGS) - -rm -rf $(SDK_DESTDIR)/$(1) .stamp-build-$(1) + $(MAKE) -C $(MONO_SDK_BUILDDIR) clean-ios-$(1) $(SDK_ARGS) + -rm -rf $(MONO_SDK_DESTDIR)/$(1) .stamp-build-$(1) endef