diff --git a/Make.config b/Make.config
index 04aa7864c017..e158d3bcad78 100644
--- a/Make.config
+++ b/Make.config
@@ -260,8 +260,20 @@ MACCATALYST_SDK_VERSION=$(word 1, $(subst ., ,$(MACCATALYST_NUGET_VERSION))).$(w
MAX_IOS_DEPLOYMENT_TARGET=$(IOS_SDK_VERSION)
MAX_TVOS_DEPLOYMENT_TARGET=$(TVOS_SDK_VERSION)
+# Decide which OS version we should run the simulator tests in.
+# Note that this may not necessarily match the SDK version, if there are OS releases with no API changes, then there wouldn't necessarily be a corresponding SDK version.
+# If the errors below trigger, update the hardcoded Xcode version check (currently 26.3) to use the current Xcode version, and assign the corresponding max simulator versions.
+ifeq ($(XCODE_VERSION),26.3)
+MAX_IOS_SIMULATOR_VERSION=26.3
+MAX_TVOS_SIMULATOR_VERSION=26.2
+else ifneq ($(XCODE_VERSION),$(IOS_SDK_VERSION))
+$(error Check if a max iOS simulator is different than the current SDK version (this happens when there's a new iOS release, with no API changes so no new SDK))
+else ifneq ($(XCODE_VERSION),$(TVOS_SDK_VERSION))
+$(error Check if a max tvOS simulator is different than the current SDK version (this happens when there's a new tvOS release, with no API changes so no new SDK))
+else
MAX_IOS_SIMULATOR_VERSION=$(IOS_SDK_VERSION)
MAX_TVOS_SIMULATOR_VERSION=$(TVOS_SDK_VERSION)
+endif
# Minimum OS versions for running XI/XM apps.
MIN_IOS_SDK_VERSION=12.2
diff --git a/NuGet.config b/NuGet.config
index 5f5f6bd5b5c6..4b471bb7657b 100644
--- a/NuGet.config
+++ b/NuGet.config
@@ -12,7 +12,7 @@
-
+
diff --git a/eng/Version.Details.props b/eng/Version.Details.props
index d7cdbae3ff52..a006a9da313a 100644
--- a/eng/Version.Details.props
+++ b/eng/Version.Details.props
@@ -5,41 +5,41 @@ This file should be imported by eng/Versions.props
-->
-
- 10.0.0-beta.26153.116
- 10.0.0-beta.26153.116
+
+ 10.0.0-beta.26160.113
+ 10.0.0-beta.26160.113
0.11.5-alpha.26070.104
- 10.0.0-beta.26153.116
+ 10.0.0-beta.26160.113
10.0.3-servicing.26070.104
10.0.3
10.0.3
- 10.0.300-preview.26153.116
+ 10.0.300-preview.26160.113
10.0.3
- 10.0.300-preview.26153.116
-
+ 10.0.300-preview.26160.113
+
26.0.11017
18.5.9227
- 26.2.9001
+ 26.2.9002
26.0.11017
18.5.9227
- 26.2.9001
+ 26.2.9002
26.0.11017
15.5.9227
- 26.2.9001
+ 26.2.9002
26.0.11017
18.5.9227
- 26.2.9001
-
+ 26.2.9002
+
+ 11.0.0-prerelease.26160.2
+
18.0.9617
18.0.9617
15.0.9617
18.0.9617
-
- 11.0.0-prerelease.26117.1
-
+
$(MicrosoftDotNetArcadeSdkPackageVersion)
$(MicrosoftDotNetBuildTasksFeedPackageVersion)
$(MicrosoftDotNetCecilPackageVersion)
@@ -50,7 +50,7 @@ This file should be imported by eng/Versions.props
$(MicrosoftNETSdkPackageVersion)
$(MicrosoftNETCoreAppRefPackageVersion)
$(MicrosoftTemplateEngineAuthoringTasksPackageVersion)
-
+
$(MicrosoftiOSSdknet100_260PackageVersion)
$(MicrosoftiOSSdknet90_185PackageVersion)
$(MicrosoftiOSSdknet90_262PackageVersion)
@@ -63,12 +63,12 @@ This file should be imported by eng/Versions.props
$(MicrosofttvOSSdknet100_260PackageVersion)
$(MicrosofttvOSSdknet90_185PackageVersion)
$(MicrosofttvOSSdknet90_262PackageVersion)
-
+
+ $(MicrosoftDotNetXHarnessiOSSharedPackageVersion)
+
$(MicrosoftiOSSdknet90_180PackageVersion)
$(MicrosoftMacCatalystSdknet90_180PackageVersion)
$(MicrosoftmacOSSdknet90_150PackageVersion)
$(MicrosofttvOSSdknet90_180PackageVersion)
-
- $(MicrosoftDotNetXHarnessiOSSharedPackageVersion)
diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml
index 12505a21d9dd..2b020df7cab8 100644
--- a/eng/Version.Details.xml
+++ b/eng/Version.Details.xml
@@ -1,8 +1,8 @@
-
+
https://github.com/dotnet/dotnet
- cdfa38403fbb85d0c2f582b8dbc522c1df9a9b83
+ 37ac471dd9cf9b9b784497fa71dcce9045eb1a78
https://github.com/dotnet/dotnet
@@ -60,21 +60,21 @@
797d30720e5e629d23eb146935da94cb1b61047e
-
+
https://github.com/dotnet/macios
- 42038e186c8e8d9ce0f4a4ff0961bb2b061a35eb
+ b34b8d33dfd662493a68b1e443fa04071eebe2b6
-
+
https://github.com/dotnet/macios
- 42038e186c8e8d9ce0f4a4ff0961bb2b061a35eb
+ b34b8d33dfd662493a68b1e443fa04071eebe2b6
-
+
https://github.com/dotnet/macios
- 42038e186c8e8d9ce0f4a4ff0961bb2b061a35eb
+ b34b8d33dfd662493a68b1e443fa04071eebe2b6
-
+
https://github.com/dotnet/macios
- 42038e186c8e8d9ce0f4a4ff0961bb2b061a35eb
+ b34b8d33dfd662493a68b1e443fa04071eebe2b6
@@ -95,25 +95,25 @@
-
+
https://github.com/dotnet/dotnet
- cdfa38403fbb85d0c2f582b8dbc522c1df9a9b83
+ 37ac471dd9cf9b9b784497fa71dcce9045eb1a78
-
+
https://github.com/dotnet/dotnet
- cdfa38403fbb85d0c2f582b8dbc522c1df9a9b83
+ 37ac471dd9cf9b9b784497fa71dcce9045eb1a78
-
+
https://github.com/dotnet/dotnet
- cdfa38403fbb85d0c2f582b8dbc522c1df9a9b83
+ 37ac471dd9cf9b9b784497fa71dcce9045eb1a78
-
+
https://github.com/dotnet/xharness
- 0eeaa60169fe6a95932d29d822e20eb225ce0143
+ c32a7777a0f8f7a4fc8d9920d445f5f4b5658d38
-
+
https://github.com/dotnet/dotnet
- cdfa38403fbb85d0c2f582b8dbc522c1df9a9b83
+ 37ac471dd9cf9b9b784497fa71dcce9045eb1a78
diff --git a/eng/common/core-templates/steps/publish-logs.yml b/eng/common/core-templates/steps/publish-logs.yml
index 5a927b4c7bcb..a9ea99ba6aaa 100644
--- a/eng/common/core-templates/steps/publish-logs.yml
+++ b/eng/common/core-templates/steps/publish-logs.yml
@@ -31,7 +31,6 @@ steps:
-runtimeSourceFeed https://ci.dot.net/internal
-runtimeSourceFeedKey '$(dotnetbuilds-internal-container-read-token-base64)'
'$(publishing-dnceng-devdiv-code-r-build-re)'
- '$(MaestroAccessToken)'
'$(dn-bot-all-orgs-artifact-feeds-rw)'
'$(akams-client-id)'
'$(microsoft-symbol-server-pat)'
diff --git a/global.json b/global.json
index fe860c6840a9..e36f010b667e 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "10.0.300-preview.26153.116",
+ "version": "10.0.300-preview.26160.113",
"paths": [
"builds/downloads/dotnet",
"$host$"
@@ -8,9 +8,9 @@
"errorMessage": "The .NET SDK could not be found, please run 'make dotnet -C builds'."
},
"tools": {
- "dotnet": "10.0.300-preview.26153.116"
+ "dotnet": "10.0.300-preview.26160.113"
},
"msbuild-sdks": {
- "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26153.116"
+ "Microsoft.DotNet.Arcade.Sdk": "10.0.0-beta.26160.113"
}
}
diff --git a/src/CoreGraphics/CGFont.cs b/src/CoreGraphics/CGFont.cs
index b286fe47dd04..71ab4c33e784 100644
--- a/src/CoreGraphics/CGFont.cs
+++ b/src/CoreGraphics/CGFont.cs
@@ -48,10 +48,10 @@ internal CGFont (NativeHandle handle, bool owns)
{
}
- static CGFont Create (IntPtr handle)
+ static CGFont? Create (IntPtr handle)
{
if (handle == IntPtr.Zero)
- ObjCRuntime.ThrowHelper.ThrowArgumentNullException (nameof (handle));
+ return null;
return new CGFont (handle, true);
}
@@ -74,29 +74,27 @@ protected internal override void Release ()
[DllImport (Constants.CoreGraphicsLibrary)]
extern static /* CGFontRef */ IntPtr CGFontCreateWithDataProvider (/* CGDataProviderRef __nullable */ IntPtr provider);
+ /// Creates a font from a data provider.
/// Data provider that wraps the font.
- /// Creates a font from a data provider.
- /// The constructed font.
- ///
- ///
- /// You can use this method to create CGFonts from an
- /// in-memory representation of the font (for example, to
- /// embed binary fonts into your application to prevent easy
- /// copying of licensed fonts, or when you fetch the font from
- /// a streaming source and do not want to store it on disk).
- ///
- ///
- ///
- /// The constructed font, or in case of failure.
+ ///
+ ///
+ /// You can use this method to create instances from an
+ /// in-memory representation of the font (for example, to
+ /// embed binary fonts into your application to prevent easy
+ /// copying of licensed fonts, or when you fetch the font from
+ /// a streaming source and do not want to store it on disk).
+ ///
+ ///
+ ///
- ///
- ///
+ ///
+ ///
public static CGFont? CreateFromProvider (CGDataProvider provider)
{
// the API accept a `nil` argument but returns `nil`, we take a shortcut (no native call)
@@ -111,22 +109,24 @@ protected internal override void Release ()
[DllImport (Constants.CoreGraphicsLibrary)]
extern static /* CGFontRef */ IntPtr CGFontCreateWithFontName (/* CFStringRef __nullable */ IntPtr name);
- /// To be added.
- /// Creates a new CGFont representing the specified PostScript or full name.
- /// To be added.
- /// To be added.
+ /// Creates a new representing the specified PostScript or full name.
+ /// The PostScript or full name of the font.
+ /// The new , or if is or no matching font is found.
+ ///
+ ///
+ /// This method looks up a font by its PostScript name or full
+ /// name. If no font matching is found,
+ /// the method returns .
+ ///
+ ///
public static CGFont? CreateWithFontName (string name)
{
// the API accept a `nil` argument but returns `nil`, we take a shortcut (no native call)
// and have a unit tests to make sure this behavior does not change over time
if (name is null)
return null;
- var nameHandle = CFString.CreateNative (name);
- try {
- return Create (CGFontCreateWithFontName (nameHandle));
- } finally {
- CFString.ReleaseNative (nameHandle);
- }
+ var nameHandle = new TransientCFString (name);
+ return Create (CGFontCreateWithFontName (nameHandle));
}
//[DllImport (Constants.CoreGraphicsLibrary)]
diff --git a/src/Foundation/NSArray.cs b/src/Foundation/NSArray.cs
index 236f64c43321..eb662f40be25 100644
--- a/src/Foundation/NSArray.cs
+++ b/src/Foundation/NSArray.cs
@@ -675,6 +675,17 @@ static bool TryGetItem (NativeHandle elementHandle, Converter (handle, createObject, NSNullBehavior.Drop, releaseHandle)!;
}
+ /// Returns a strongly-typed C# array from a handle to an NSArray, dropping null elements.
+ /// Parameter type, determines the kind of array returned.
+ /// Pointer (handle) to the unmanaged object.
+ /// How to handle null and NSNull elements in the native array.
+ /// Whether the native NSArray instance should be released before returning or not.
+ /// A C# array with the values (excluding null elements). Returns if the handle is .
+ internal static T []? ArrayFromHandleDropNullElements (NativeHandle handle, NSNullBehavior nsNullElementBehavior, bool releaseHandle = false) where T : class, INativeObject
+ {
+ return ArrayFromHandle (handle, (h) => Runtime.GetINativeObject (h, false)!, nsNullElementBehavior, releaseHandle)!;
+ }
+
/// Returns a strongly-typed C# array from a handle to an NSArray, dropping null elements and guaranteeing a non-null return value.
/// Parameter type, determines the kind of array returned.
/// Pointer (handle) to the unmanaged object.
@@ -722,55 +733,80 @@ internal static T [] NonNullArrayFromHandleDropNullElements (NativeHandle han
return rv!;
}
-#nullable disable
-
- static public T [] EnumsFromHandle (NativeHandle handle) where T : struct, IConvertible
+ /// Returns a C# array of enum values from a handle to an NSArray of NSNumber elements, dropping any null or NSNull elements.
+ /// The enum type to convert each NSNumber element to.
+ /// Pointer (handle) to the unmanaged object.
+ /// A C# array of enum values (excluding null elements), or if the handle is .
+#if XAMCORE_5_0
+ public static T []? EnumsFromHandle (NativeHandle handle) where T : System.Enum
+#else
+ public static T []? EnumsFromHandle (NativeHandle handle) where T : struct, IConvertible
+#endif
{
- if (handle == NativeHandle.Zero)
- return null;
+#if !XAMCORE_5_0
if (!typeof (T).IsEnum)
throw new ArgumentException ("T must be an enum");
+#endif
- var c = GetCount (handle);
- T [] ret = new T [c];
+ return ArrayFromHandleDropNullElements (handle, (element) => (T) Enum.ToObject (typeof (T), Runtime.GetNSObject (element)?.LongValue ?? 0));
+ }
- for (uint i = 0; i < c; i++) {
- ret [i] = (T) Convert.ChangeType (UnsafeGetItem (handle, i).LongValue, typeof (T));
- }
- return ret;
+ /// Returns a C# array of enum values from a handle to an NSArray of NSNumber elements, dropping null elements and guaranteeing a non-null return value.
+ /// The enum type to convert each NSNumber element to.
+ /// Pointer (handle) to the unmanaged object.
+ /// A C# array of enum values (excluding null elements). Returns an empty array if the handle is .
+ internal static T [] NonNullEnumsFromHandle (NativeHandle handle) where T : System.Enum
+ {
+ return NonNullArrayFromHandleDropNullElements (
+ handle,
+ (element) => (T) Enum.ToObject (typeof (T), Runtime.GetNSObject (element)?.LongValue ?? 0));
}
- /// Parameter type, determines the kind of
- /// array returned, limited to NSObject and subclasses of it.
- /// Handle to an weakly typed NSArray.
- /// Returns a strongly-typed C# array of the parametrized type from a weakly typed NSArray.
- /// An C# array with the values.
- ///
- /// Use this method to get a set of NSObject arrays from an NSArray.
- ///
- /// Creates a strongly-typed C# array from a weakly typed .
+ /// The element type for the returned array, limited to and subclasses.
+ /// A weakly typed to convert, or .
+ ///
+ /// A C# array of elements, or if
+ /// is or a conversion error occurs.
+ /// Elements that are or not compatible with are excluded.
+ ///
+ ///
+ ///
+ /// (someArray);
+ /// var values = NSArray.FromArray (someArray);
/// ]]>
- ///
- ///
- static public T [] FromArray (NSArray weakArray) where T : NSObject
+ ///
+ ///
+ public static T []? FromArray (NSArray? weakArray) where T : NSObject
{
- if (weakArray is null || weakArray.Handle == NativeHandle.Zero)
- return null;
try {
- nuint n = weakArray.Count;
- T [] ret = new T [n];
- for (nuint i = 0; i < n; i++) {
- ret [i] = Runtime.GetNSObject (weakArray.ValueAt (i));
- }
- return ret;
+ var rv = ArrayFromHandleDropNullElements (weakArray.GetHandle (), NSNullBehavior.DropIfIncompatible);
+ GC.KeepAlive (weakArray);
+ return rv;
} catch {
return null;
}
}
+ ///
+ /// Creates a strongly-typed C# array from a weakly typed ,
+ /// dropping null and elements and guaranteeing a non-null return value.
+ ///
+ /// The element type for the returned array, limited to and subclasses.
+ /// A weakly typed to convert, or .
+ ///
+ /// A C# array of elements (excluding null and elements).
+ /// Returns an empty array if is or empty.
+ ///
+ internal static T [] ToNonNullArrayDropNullElements (NSArray? weakArray) where T : NSObject
+ {
+ var rv = NSArray.NonNullArrayFromHandleDropNullElements (weakArray.GetHandle ());
+ GC.KeepAlive (weakArray);
+ return rv;
+ }
+#nullable disable
/// Parameter type, determines the kind of
/// array returned, can be either an NSObject, or other
/// CoreGraphics data types.
diff --git a/src/MetalKit/MTKMesh.cs b/src/MetalKit/MTKMesh.cs
index 6186cb436987..9eb1340ee9b0 100644
--- a/src/MetalKit/MTKMesh.cs
+++ b/src/MetalKit/MTKMesh.cs
@@ -16,7 +16,7 @@ public partial class MTKMesh {
/// Creates and returns a new Metal Kit mesh from the supplied Model IO asset.
/// To be added.
/// To be added.
- public static MTKMesh []? FromAsset (MDLAsset asset, IMTLDevice device, out MDLMesh [] sourceMeshes, out NSError error)
+ public static MTKMesh []? FromAsset (MDLAsset asset, IMTLDevice device, out MDLMesh []? sourceMeshes, out NSError error)
{
NSArray aret;
diff --git a/src/NetworkExtension/NEHotspotEapSettings.cs b/src/NetworkExtension/NEHotspotEapSettings.cs
index df97a29e37f7..c000556bea9b 100644
--- a/src/NetworkExtension/NEHotspotEapSettings.cs
+++ b/src/NetworkExtension/NEHotspotEapSettings.cs
@@ -22,7 +22,7 @@ public partial class NEHotspotEapSettings {
/// To be added.
public NEHotspotConfigurationEapType [] SupportedEapTypes {
get {
- return NSArray.EnumsFromHandle (_SupportedEapTypes)!;
+ return NSArray.NonNullEnumsFromHandle (_SupportedEapTypes);
}
set {
if (value is null)
diff --git a/src/UIKit/UIFontDescriptor.cs b/src/UIKit/UIFontDescriptor.cs
index 6dfea2f6e079..4b187981160c 100644
--- a/src/UIKit/UIFontDescriptor.cs
+++ b/src/UIKit/UIFontDescriptor.cs
@@ -532,9 +532,7 @@ public NSCharacterSet? CharacterSet {
public UIFontDescriptor [] CascadeList {
get {
var o = GetObject (UIFontDescriptor.CascadeListAttribute) as NSArray;
- if (o is null)
- return new UIFontDescriptor [0];
- return NSArray.FromArray (o);
+ return NSArray.ToNonNullArrayDropNullElements (o);
}
}
diff --git a/src/bgen/Generator.cs b/src/bgen/Generator.cs
index 8f49ea31dd29..914c35822046 100644
--- a/src/bgen/Generator.cs
+++ b/src/bgen/Generator.cs
@@ -4068,7 +4068,7 @@ void GenerateProperty (Type type, PropertyInfo pi, List instance_fields_
print ("return src is null ? null! : new {0}(src);", TypeManager.FormatType (pi.DeclaringType, pi.PropertyType));
} else {
if (TypeManager.IsArrayOfWrappedType (pi.PropertyType))
- print ("return NSArray.FromArray<{0}>({1} as NSArray);", TypeManager.FormatType (pi.DeclaringType, pi.PropertyType.GetElementType ()), wrap);
+ print ("return NSArray.FromArray<{0}>({1} as NSArray){2};", TypeManager.FormatType (pi.DeclaringType, pi.PropertyType.GetElementType ()), wrap, nullable ? "" : "!");
else if (pi.PropertyType.IsValueType)
print ("return ({0}) ({1});", TypeManager.FormatType (pi.DeclaringType, pi.PropertyType), wrap);
else
diff --git a/tests/cecil-tests/Documentation.KnownFailures.txt b/tests/cecil-tests/Documentation.KnownFailures.txt
index 267086a2c81b..cad51eed565b 100644
--- a/tests/cecil-tests/Documentation.KnownFailures.txt
+++ b/tests/cecil-tests/Documentation.KnownFailures.txt
@@ -11800,7 +11800,6 @@ M:Foundation.INSUrlSessionTaskDelegate.NeedNewBodyStream(Foundation.NSUrlSession
M:Foundation.INSUrlSessionWebSocketDelegate.DidClose(Foundation.NSUrlSession,Foundation.NSUrlSessionWebSocketTask,Foundation.NSUrlSessionWebSocketCloseCode,Foundation.NSData)
M:Foundation.INSUrlSessionWebSocketDelegate.DidOpen(Foundation.NSUrlSession,Foundation.NSUrlSessionWebSocketTask,System.String)
M:Foundation.INSXpcListenerDelegate.ShouldAcceptConnection(Foundation.NSXpcListener,Foundation.NSXpcConnection)
-M:Foundation.NSArray.EnumsFromHandle``1(ObjCRuntime.NativeHandle)
M:Foundation.NSArray.ToArray
M:Foundation.NSArray.ToArray``1
M:Foundation.NSArray`1.ToArray
diff --git a/tests/common/test-variations.csproj b/tests/common/test-variations.csproj
index 847d55dcbd18..6826b694f495 100644
--- a/tests/common/test-variations.csproj
+++ b/tests/common/test-variations.csproj
@@ -13,6 +13,7 @@
+
@@ -74,6 +75,11 @@
<_TestVariationApplied>true
+
+ static
+ <_TestVariationApplied>true
+
+
$(AppBundleExtraOptions) --optimize:all
static
diff --git a/tests/monotouch-test/CoreText/FontTest.cs b/tests/monotouch-test/CoreText/FontTest.cs
index ed4513a373d6..b8593972e5c1 100644
--- a/tests/monotouch-test/CoreText/FontTest.cs
+++ b/tests/monotouch-test/CoreText/FontTest.cs
@@ -7,6 +7,8 @@
// Copyright 2015 Xamarin Inc. All rights reserved.
//
+using System.Linq;
+
using CoreGraphics;
using CoreText;
#if MONOMAC
@@ -82,7 +84,7 @@ public void GetLocalizedName ()
[Test]
public void GetGlyphsForCharacters_35048 ()
{
- using (var font = CGFont.CreateWithFontName ("AppleColorEmoji"))
+ using (var font = CreateAppleColorEmojiFont ())
using (var ctfont = font.ToCTFont ((nfloat) 10.0)) {
ushort [] gid = new ushort [2];
Assert.True (ctfont.GetGlyphsForCharacters ("\ud83d\ude00".ToCharArray (), gid), "GetGlyphsForCharacters");
@@ -115,6 +117,14 @@ public void CTFontCreateForStringWithLanguage ()
}
}
+ static CGFont CreateAppleColorEmojiFont ()
+ {
+ var font = CGFont.CreateWithFontName ("AppleColorEmoji");
+ if (font is null)
+ Assert.Ignore ("Unable to create the 'AppleColorEmoji' font.");
+ return font;
+ }
+
[Test]
public void CTFontCopyNameForGlyph ()
{
@@ -123,7 +133,7 @@ public void CTFontCopyNameForGlyph ()
using (var ctfont = new CTFont ("HoeflerText-Regular", 10, CTFontOptions.Default))
Assert.That (ctfont.GetGlyphName ((ushort) 65), Is.EqualTo ("asciicircum"), "1");
- using (var font = CGFont.CreateWithFontName ("AppleColorEmoji"))
+ using (var font = CreateAppleColorEmojiFont ())
using (var ctfont = font.ToCTFont ((nfloat) 10.0))
Assert.Null (ctfont.GetGlyphName ('\ud83d'), "2");
}
@@ -149,7 +159,11 @@ public void GetTypographicBoundsForAdaptiveImageProvider ()
using var font = new CTFont ("HoeflerText-Regular", 10, CTFontOptions.Default);
using var provider = new AdaptiveImageProvider ();
var bounds = font.GetTypographicBoundsForAdaptiveImageProvider (provider);
- Assert.AreEqual (new CGRect (0, -3.90625, 13, 16.40625), bounds, "Bounds");
+ var candidates = new object [] {
+ new CGRect (0, -3.90625, 13, 16.40625),
+ new CGRect (0, -3.90625, 35, 16.40625)
+ };
+ Assert.That (bounds, Is.AnyOf (candidates).Using ((x, y) => x == y), "Bounds");
Assert.AreEqual (0, provider.Count, "#Count");
}
diff --git a/tests/monotouch-test/Foundation/NSArray1Test.cs b/tests/monotouch-test/Foundation/NSArray1Test.cs
index f58ba7d86c41..3163a6f2a33e 100644
--- a/tests/monotouch-test/Foundation/NSArray1Test.cs
+++ b/tests/monotouch-test/Foundation/NSArray1Test.cs
@@ -431,6 +431,37 @@ public void FromObjects_WithCount_Null ()
}
}
+ [Test]
+ public void EnumsFromHandle_ReturnsNullForZeroHandle ()
+ {
+ var result = NSArray.EnumsFromHandle (NativeHandle.Zero);
+ Assert.IsNull (result, "null for zero handle");
+ }
+
+ [Test]
+ public void EnumsFromHandle_Roundtrip ()
+ {
+ var expected = new [] {
+ NSComparisonResult.Ascending,
+ NSComparisonResult.Same,
+ NSComparisonResult.Descending,
+ };
+ using var n0 = NSNumber.FromNInt ((nint) (long) expected [0]);
+ using var n1 = NSNumber.FromNInt ((nint) (long) expected [1]);
+ using var n2 = NSNumber.FromNInt ((nint) (long) expected [2]);
+ using var array = NSArray.FromNSObjects (n0, n1, n2);
+ var actual = NSArray.EnumsFromHandle (array.Handle);
+ Assert.IsNotNull (actual, "not null");
+ Assert.That (actual!.Length, Is.EqualTo (3), "Length");
+ Assert.That (actual, Is.EqualTo (expected), "values");
+ }
+
+ [Test]
+ public void EnumsFromHandle_ThrowsForNonEnum ()
+ {
+ Assert.Throws (() => NSArray.EnumsFromHandle (NativeHandle.Zero), "non-enum should throw");
+ }
+
#if false // https://github.com/dotnet/macios/issues/15577
[Test]
public void GetDifferenceFromArrayTest ()
diff --git a/tests/monotouch-test/Metal/MTKMeshTest.cs b/tests/monotouch-test/Metal/MTKMeshTest.cs
new file mode 100644
index 000000000000..b1c54f52cd63
--- /dev/null
+++ b/tests/monotouch-test/Metal/MTKMeshTest.cs
@@ -0,0 +1,43 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+using System;
+using System.Numerics;
+
+using Foundation;
+using Metal;
+using MetalKit;
+using ModelIO;
+
+using NUnit.Framework;
+
+using Vector3i = global::CoreGraphics.NVector3i;
+
+namespace MonoTouchFixtures.MetalKit {
+
+ [TestFixture]
+ [Preserve (AllMembers = true)]
+ public class MTKMeshTest {
+
+ [Test]
+ public void FromAsset ()
+ {
+ var device = MTLDevice.SystemDefault;
+ if (device is null)
+ Assert.Inconclusive ("Metal is not supported on this device.");
+
+ using var allocator = new MTKMeshBufferAllocator (device);
+ using var mesh = MDLMesh.CreateBox (new Vector3 (1, 1, 1), new Vector3i (1, 1, 1), MDLGeometryType.Triangles, false, allocator);
+ using var asset = new MDLAsset ();
+ asset.AddObject (mesh);
+
+ var result = MTKMesh.FromAsset (asset, device, out var sourceMeshes, out var error);
+
+ Assert.IsNull (error, "error");
+ Assert.IsNotNull (result, "result");
+ Assert.That (result!.Length, Is.GreaterThan (0), "result length");
+ Assert.IsNotNull (sourceMeshes, "sourceMeshes");
+ Assert.AreEqual (result.Length, sourceMeshes!.Length, "sourceMeshes length");
+ }
+ }
+}
diff --git a/tests/monotouch-test/NetworkExtension/NEHotspotEapSettingsTest.cs b/tests/monotouch-test/NetworkExtension/NEHotspotEapSettingsTest.cs
new file mode 100644
index 000000000000..4609cc19862a
--- /dev/null
+++ b/tests/monotouch-test/NetworkExtension/NEHotspotEapSettingsTest.cs
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft Corporation.
+// Licensed under the MIT License.
+
+#if !__TVOS__ && !__MACOS__
+
+using NetworkExtension;
+
+namespace MonoTouchFixtures.NetworkExtension {
+
+ [TestFixture]
+ [Preserve (AllMembers = true)]
+ public class NEHotspotEapSettingsTest {
+
+ [Test]
+ public void SupportedEapTypes_Default ()
+ {
+ using var settings = new NEHotspotEapSettings ();
+ var types = settings.SupportedEapTypes;
+ Assert.IsNotNull (types, "Default value should not be null");
+ Assert.That (types.Length, Is.EqualTo (0), "Default length");
+ }
+
+ [Test]
+ public void SupportedEapTypes_Roundtrip ()
+ {
+ using var settings = new NEHotspotEapSettings ();
+ var expected = new [] {
+ NEHotspotConfigurationEapType.Tls,
+ NEHotspotConfigurationEapType.Peap,
+ };
+ settings.SupportedEapTypes = expected;
+ var actual = settings.SupportedEapTypes;
+ Assert.IsNotNull (actual, "not null");
+ Assert.That (actual.Length, Is.EqualTo (2), "Length");
+ Assert.That (actual [0], Is.EqualTo (NEHotspotConfigurationEapType.Tls), "[0]");
+ Assert.That (actual [1], Is.EqualTo (NEHotspotConfigurationEapType.Peap), "[1]");
+ }
+
+ [Test]
+ public void SupportedEapTypes_AllValues ()
+ {
+ using var settings = new NEHotspotEapSettings ();
+ var all = new [] {
+ NEHotspotConfigurationEapType.Tls,
+ NEHotspotConfigurationEapType.Ttls,
+ NEHotspotConfigurationEapType.Peap,
+ NEHotspotConfigurationEapType.Fast,
+ };
+ settings.SupportedEapTypes = all;
+ var actual = settings.SupportedEapTypes;
+ Assert.That (actual.Length, Is.EqualTo (4), "Length");
+ Assert.That (actual, Is.EqualTo (all), "All values roundtrip");
+ }
+
+ [Test]
+ public void SupportedEapTypes_SetNull ()
+ {
+ using var settings = new NEHotspotEapSettings ();
+ Assert.Throws (() => settings.SupportedEapTypes = null!, "null should throw");
+ }
+ }
+}
+
+#endif // !__TVOS__ && !__MACOS__
diff --git a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs
index 0df5e8bd75b3..b3ce5aadb8f3 100644
--- a/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs
+++ b/tests/monotouch-test/ObjCRuntime/RegistrarTest.cs
@@ -5720,13 +5720,13 @@ public void DecidePolicy (WKWebView webView, WKNavigationAction navigationAction
// These classes implement Metal* protocols, so that the generated registrar code includes the corresponding Metal* headers.
// https://github.com/dotnet/macios/issues/4422
- class MetalKitTypesInTheSimulator : NSObject, MetalKit.IMTKViewDelegate {
- public void Draw (MetalKit.MTKView view)
+ class MetalKitTypesInTheSimulator : NSObject, global::MetalKit.IMTKViewDelegate {
+ public void Draw (global::MetalKit.MTKView view)
{
throw new NotImplementedException ();
}
- public void DrawableSizeWillChange (MetalKit.MTKView view, CGSize size)
+ public void DrawableSizeWillChange (global::MetalKit.MTKView view, CGSize size)
{
throw new NotImplementedException ();
}
diff --git a/tests/monotouch-test/VideoToolbox/VTDecompressionSessionTests.cs b/tests/monotouch-test/VideoToolbox/VTDecompressionSessionTests.cs
index 9841fe1e8946..f6dae5da90b9 100644
--- a/tests/monotouch-test/VideoToolbox/VTDecompressionSessionTests.cs
+++ b/tests/monotouch-test/VideoToolbox/VTDecompressionSessionTests.cs
@@ -199,6 +199,7 @@ public void DecodeFrameTest ()
});
Assert.That (session.FinishDelayedFrames (), Is.EqualTo (VTStatus.Ok), "FinishDelayedFrames");
+ Assert.That (session.WaitForAsynchronousFrames (), Is.EqualTo (VTStatus.Ok), "WaitForAsynchronousFrames");
Assert.That (frameCallbackCounter, Is.GreaterThan (0), "Frame callback counter");
Assert.That (failures, Is.Empty, "Failures");
if (knownDecoderCallbackStatusCount > 0)
@@ -238,6 +239,7 @@ public void DecodeFrameMultiImageCallbackTest ()
});
Assert.That (session.FinishDelayedFrames (), Is.EqualTo (VTStatus.Ok), "FinishDelayedFrames");
+ Assert.That (session.WaitForAsynchronousFrames (), Is.EqualTo (VTStatus.Ok), "WaitForAsynchronousFrames");
Assert.That (frameCallbackCounter, Is.GreaterThan (0), "Frame callback counter 2");
Assert.That (failures, Is.Empty, "Failures");
}
@@ -288,6 +290,7 @@ public void DecodeFrameSetMultiImageCallbackTest ()
});
Assert.That (session.FinishDelayedFrames (), Is.EqualTo (VTStatus.Ok), "FinishDelayedFrames");
+ Assert.That (session.WaitForAsynchronousFrames (), Is.EqualTo (VTStatus.Ok), "WaitForAsynchronousFrames");
Assert.That (frameCallbackCounter, Is.GreaterThan (0), "Frame callback counter 2");
Assert.That (failures, Is.Empty, "Failures");
}
@@ -323,6 +326,7 @@ public void DecodeFrameCallbackTest ()
Assert.That (status, Is.EqualTo (VTStatus.Ok), "DecodeFrame");
});
Assert.That (session.FinishDelayedFrames (), Is.EqualTo (VTStatus.Ok), "FinishDelayedFrames");
+ Assert.That (session.WaitForAsynchronousFrames (), Is.EqualTo (VTStatus.Ok), "WaitForAsynchronousFrames");
Assert.That (frameCallbackCounter, Is.EqualTo (0), "Frame callback counter 3");
Assert.That (inlineCallback, Is.GreaterThan (0), "Frame callback counter 4");
diff --git a/tests/monotouch-test/xamvideotest.mp4 b/tests/monotouch-test/xamvideotest.mp4
index ce6a6378f25c..8478d85c03b9 100644
Binary files a/tests/monotouch-test/xamvideotest.mp4 and b/tests/monotouch-test/xamvideotest.mp4 differ
diff --git a/tests/sharpie/Sharpie.Bind.Tests/ObjectiveCClass.cs b/tests/sharpie/Sharpie.Bind.Tests/ObjectiveCClass.cs
index 3ef19a810e1b..06946f8eee59 100644
--- a/tests/sharpie/Sharpie.Bind.Tests/ObjectiveCClass.cs
+++ b/tests/sharpie/Sharpie.Bind.Tests/ObjectiveCClass.cs
@@ -456,4 +456,175 @@ public struct MyStruct {
Assert.That (bindings.AdditionalFiles ["ApiDefinition.cs"].Trim (), Is.EqualTo (expectedApiDefinitionBindings.Trim ()), "Api definition");
Assert.That (bindings.AdditionalFiles ["StructsAndEnums.cs"].Trim (), Is.EqualTo (expectedStructAndEnumsBindings.Trim ()), "Struct and enums");
}
+
+ [Test]
+ public void Scope_RelativePath ()
+ {
+ // Verify that --scope with a relative path works correctly
+ // (the relative path should be resolved to absolute before matching).
+ var binder = new BindTool ();
+ var tmpdir = Cache.CreateTemporaryDirectory ();
+ var subdir = Path.Combine (tmpdir, "headers");
+ Directory.CreateDirectory (subdir);
+
+ // Create a header in the scoped directory
+ var scopedHeader = Path.Combine (subdir, "InScope.h");
+ File.WriteAllText (scopedHeader,
+ """
+ @interface InScopeClass {
+ }
+ @property int Value;
+ @end
+ """);
+
+ // Create an umbrella header that includes both
+ var mainHeader = Path.Combine (tmpdir, "main.h");
+ File.WriteAllText (mainHeader, $"#import \"{scopedHeader}\"\n");
+
+ binder.SplitDocuments = false;
+ binder.SourceFile = mainHeader;
+ binder.OutputDirectory = tmpdir;
+
+ // Use a relative scope path (the bug was that this produced empty output)
+ var oldCwd = Environment.CurrentDirectory;
+ try {
+ Environment.CurrentDirectory = tmpdir;
+ binder.DirectoriesInScope.Add (Path.GetFullPath ("headers"));
+ } finally {
+ Environment.CurrentDirectory = oldCwd;
+ }
+
+ Configuration.IgnoreIfIgnoredPlatform (binder.Platform);
+ binder.PlatformAssembly = Extensions.GetPlatformAssemblyPath (binder.Platform);
+ binder.ClangResourceDirectory = Extensions.GetClangResourceDirectory ();
+ var bindings = binder.BindInOrOut ();
+ var expectedBindings =
+"""
+using Foundation;
+
+// @interface InScopeClass
+interface InScopeClass {
+ // @property int Value;
+ [Export ("Value")]
+ int Value { get; set; }
+}
+
+""";
+ bindings.AssertSuccess (expectedBindings);
+ }
+
+ [Test]
+ public void Scope_FiltersOutOfScopeDeclarations ()
+ {
+ // Verify that declarations from headers outside the scope directory are not bound.
+ var binder = new BindTool ();
+ var tmpdir = Cache.CreateTemporaryDirectory ();
+ var scopedDir = Path.Combine (tmpdir, "scoped");
+ var unscopedDir = Path.Combine (tmpdir, "unscoped");
+ Directory.CreateDirectory (scopedDir);
+ Directory.CreateDirectory (unscopedDir);
+
+ var scopedHeader = Path.Combine (scopedDir, "Scoped.h");
+ File.WriteAllText (scopedHeader,
+ """
+ @interface ScopedClass {
+ }
+ @property int A;
+ @end
+ """);
+
+ var unscopedHeader = Path.Combine (unscopedDir, "Unscoped.h");
+ File.WriteAllText (unscopedHeader,
+ """
+ @interface UnscopedClass {
+ }
+ @property int B;
+ @end
+ """);
+
+ var mainHeader = Path.Combine (tmpdir, "main.h");
+ File.WriteAllText (mainHeader, $"#import \"{scopedHeader}\"\n#import \"{unscopedHeader}\"\n");
+
+ binder.SplitDocuments = false;
+ binder.SourceFile = mainHeader;
+ binder.OutputDirectory = tmpdir;
+ binder.DirectoriesInScope.Add (scopedDir);
+ Configuration.IgnoreIfIgnoredPlatform (binder.Platform);
+ binder.PlatformAssembly = Extensions.GetPlatformAssemblyPath (binder.Platform);
+ binder.ClangResourceDirectory = Extensions.GetClangResourceDirectory ();
+ var bindings = binder.BindInOrOut ();
+
+ // Only ScopedClass should be in the output, not UnscopedClass
+ var expectedBindings =
+"""
+using Foundation;
+
+// @interface ScopedClass
+interface ScopedClass {
+ // @property int A;
+ [Export ("A")]
+ int A { get; set; }
+}
+
+""";
+ bindings.AssertSuccess (expectedBindings);
+ }
+
+ [Test]
+ public void Scope_PrefixDoesNotFalseMatch ()
+ {
+ // Verify that a scope of "/foo/bar" does not match "/foo/barbaz/header.h"
+ // (the scope must be a proper directory prefix with separator).
+ var binder = new BindTool ();
+ var tmpdir = Cache.CreateTemporaryDirectory ();
+ var scopedDir = Path.Combine (tmpdir, "scope");
+ var falseMatchDir = Path.Combine (tmpdir, "scopeextra");
+ Directory.CreateDirectory (scopedDir);
+ Directory.CreateDirectory (falseMatchDir);
+
+ var scopedHeader = Path.Combine (scopedDir, "Good.h");
+ File.WriteAllText (scopedHeader,
+ """
+ @interface GoodClass {
+ }
+ @property int X;
+ @end
+ """);
+
+ var falseMatchHeader = Path.Combine (falseMatchDir, "Bad.h");
+ File.WriteAllText (falseMatchHeader,
+ """
+ @interface BadClass {
+ }
+ @property int Y;
+ @end
+ """);
+
+ var mainHeader = Path.Combine (tmpdir, "main.h");
+ File.WriteAllText (mainHeader, $"#import \"{scopedHeader}\"\n#import \"{falseMatchHeader}\"\n");
+
+ binder.SplitDocuments = false;
+ binder.SourceFile = mainHeader;
+ binder.OutputDirectory = tmpdir;
+ binder.DirectoriesInScope.Add (scopedDir);
+ Configuration.IgnoreIfIgnoredPlatform (binder.Platform);
+ binder.PlatformAssembly = Extensions.GetPlatformAssemblyPath (binder.Platform);
+ binder.ClangResourceDirectory = Extensions.GetClangResourceDirectory ();
+ var bindings = binder.BindInOrOut ();
+
+ // Only GoodClass should appear (from "scope/"), not BadClass (from "scopeextra/")
+ var expectedBindings =
+"""
+using Foundation;
+
+// @interface GoodClass
+interface GoodClass {
+ // @property int X;
+ [Export ("X")]
+ int X { get; set; }
+}
+
+""";
+ bindings.AssertSuccess (expectedBindings);
+ }
}
diff --git a/tools/devops/automation/scripts/.gitignore b/tools/devops/automation/scripts/.gitignore
new file mode 100644
index 000000000000..89923e7760bc
--- /dev/null
+++ b/tools/devops/automation/scripts/.gitignore
@@ -0,0 +1,2 @@
+_provisionator
+
diff --git a/tools/devops/automation/scripts/provisionator-bootstrap.sh b/tools/devops/automation/scripts/provisionator-bootstrap.sh
new file mode 100755
index 000000000000..143cfa4bf75e
--- /dev/null
+++ b/tools/devops/automation/scripts/provisionator-bootstrap.sh
@@ -0,0 +1,131 @@
+#!/bin/bash -e
+# shellcheck disable=SC2220,SC2181
+#
+# Remove the following GUID if you do not wish for this script self-update:
+# D6F71FB5-F2A7-4A62-86D3-10DFE08301CC
+# https://github.com/xamarin/provisionator
+
+while getopts ":t:" opt; do
+ case "${opt}" in
+ t)
+ TOKEN=${OPTARG}
+ shift 2
+ ;;
+ esac
+done
+
+function selfdir { (cd "$(dirname "$1")"; echo "$PWD"; ) }
+
+selfdir=$(selfdir "$0")
+
+channel="${PROVISIONATOR_CHANNEL:-latest}"
+
+provisionator_sas_token=$AUTH_TOKEN_PROVISIONATOR
+if [[ -n $provisionator_sas_token ]]; then
+ echo "Downloading Provisionator directly from BosStorageMirror Azure blob storage"
+ base_url="https://bosstoragemirror.blob.core.windows.net/provisionator/664bd334021e3102cdef1af66c4fc9f1b2ecd2a21b47419e80d08da1f6c61c2a/${channel}"
+else
+ # Grab auth token from Environment first
+ # Otherwise set to provided option, if available
+ base_url="https://dl.internalx.com/provisionator/664bd334021e3102cdef1af66c4fc9f1b2ecd2a21b47419e80d08da1f6c61c2a/${channel}"
+ auth_token=$AUTH_TOKEN_GITHUB_COM
+ if [[ -z $auth_token ]]; then
+ echo "Setting auth_token to input token and not AUTH_TOKEN_GITHUB_COM"
+ auth_token=$TOKEN
+ fi
+ if [[ -z $auth_token ]]; then
+ echo "WARNING: Please set AUTH_TOKEN_GITHUB_COM to a GitHub PAT before running provisionator or run provisionator.sh -t ..."
+ echo "At a future point, Provisionator will not be able to bootstrap without the PAT set properly"
+ base_url="https://bosstoragemirror.blob.core.windows.net/provisionator/664bd334021e3102cdef1af66c4fc9f1b2ecd2a21b47419e80d08da1f6c61c2a/${channel}"
+ fi
+fi
+
+latest_version_url="${base_url}/version"
+
+if [[ -n $provisionator_sas_token ]]; then
+ echo "latest_version_url: Appending SAS token"
+ latest_version_url="${latest_version_url}?${provisionator_sas_token}"
+fi
+
+archive_name="provisionator.osx.10.11-x64.zip"
+archive_path="${selfdir}/${archive_name}"
+archive_extract_path="${selfdir}/_provisionator"
+archive_url="${base_url}/${archive_name}"
+if [[ -n $provisionator_sas_token ]]; then
+ echo "archive_url: Appending SAS token"
+ archive_url="${archive_url}?${provisionator_sas_token}"
+fi
+
+binary_path="${archive_extract_path}/provisionator"
+pk_path="${archive_extract_path}/pk"
+
+set +e
+
+# Double brackets are required for the following condition to evaulate as expected
+if [[ -z $auth_token ]] || [[ -n $provisionator_sas_token ]]; then
+ if [[ -n $provisionator_sas_token ]]; then
+ echo "Fetching latest version with SAS token"
+ else
+ echo "Fetching latest version without auth token"
+ fi
+ latest_version="$(curl -fsL "${latest_version_url}")"
+else
+ echo "Fetching latest version with auth token"
+ latest_version="$(curl -fsL -H "Authorization: token ${auth_token}" "${latest_version_url}")"
+fi
+if [[ $? != 0 ]]; then
+ echo "Unable to determine latest version from ${latest_version_url}"
+ echo "Please check to make sure a valid GitHub PAT was provided"
+ exit 1
+fi
+set -e
+
+function update_in_place {
+ echo "Downloading Provisionator $latest_version..."
+ local progress_type="-s"
+ tty -s && progress_type="-#"
+ if [[ -z $auth_token ]] || [[ -n $provisionator_sas_token ]]; then
+ curl -fL $progress_type -o "$archive_path" "$archive_url"
+ else
+ curl -fLH "Authorization: token ${auth_token}" $progress_type -o "$archive_path" "$archive_url"
+ fi
+ rm -rf "$archive_extract_path"
+ unzip -q -o -d "$archive_extract_path" "$archive_path"
+ rm -f "$archive_path"
+}
+
+if [[ -f "$binary_path" ]]; then
+ chmod +x "$binary_path"
+ current_version="$("$binary_path" -version 2>&1 || true)"
+ if [[ "$latest_version" != "$current_version" ]]; then
+ update_in_place
+ fi
+else
+ update_in_place
+fi
+
+# Check for the pk (PackageKitTool) binary, which should be included in the provisionator macOS ZIP package
+if [[ "$OSTYPE" == "darwin"* ]]; then
+ echo "Checking for PackageKitTool (pk) binary..."
+ if [[ -f "$pk_path" ]]; then
+ echo "PackageKitTool (pk) binary found: ${pk_path}"
+ echo "chmod +x ${pk_path}"
+ chmod +x "$pk_path"
+ else
+ echo "ERROR: pk file not found: ${pk_path}"
+ exit 5
+ fi
+fi
+
+# Opt out of macOS backward compat so correct Big Sur OS versions can be obtained.
+# More info https://github.com/ziglang/zig/issues/7569
+export SYSTEM_VERSION_COMPAT=0
+
+# TODO: The executable permission should be applied here. However, since this script is reflective of production scripts used by other clients/teams avoid modifying the executable permission here.
+# A reason to avoid this is that the executable permission is expected to be preserved in the ZIP file produced by the ClientTools.Provisionator build pipeline
+# CONSIDER: A possible follow up item would be to go update all the production scripts to apply the executable permission here to ensure the provisionator binary has the executable permission set
+# This may also involve updating the Provisionator Azure DevOps provisionator task to ensure it applies the executable attribute after ZIP extraction
+# https://devdiv.visualstudio.com/Engineering/_git/xamarin-azdev-extension?path=/provisionator-task
+# echo "Applying executable attribute: ${binary_path}"
+# chmod +x "$binary_path"
+exec caffeinate "$binary_path" "$@"
diff --git a/tools/devops/automation/templates/build/build.yml b/tools/devops/automation/templates/build/build.yml
index d3d9951de246..ae746a2d4776 100644
--- a/tools/devops/automation/templates/build/build.yml
+++ b/tools/devops/automation/templates/build/build.yml
@@ -85,14 +85,12 @@ steps:
make -C $(Build.SourcesDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops provisioning
displayName: 'Generate provisionator files.'
- - task: xamops.azdevex.provisionator-task.provisionator@2
- displayName: 'Provision Products & Frameworks'
- inputs:
+ - template: ../common/provision.yml
+ parameters:
provisioning_script: $(Build.SourcesDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops/build-provisioning.csx
- provisioning_extra_args: '-vvvv'
- github_token: ${{ parameters.gitHubToken }}
- timeoutInMinutes: 250
- retryCountOnTaskFailure: ${{ parameters.retryCount }} # mono does give issues sometimes to download, we will retry
+ displayName: 'Provision Products & Frameworks'
+ provisionatorChannel: $(PROVISIONATOR_CHANNEL)
+ retryCount: ${{ parameters.retryCount }} # mono does give issues sometimes to download, we will retry
- bash: |
set -x
diff --git a/tools/devops/automation/templates/common/provision.yml b/tools/devops/automation/templates/common/provision.yml
new file mode 100644
index 000000000000..6424ffd2103d
--- /dev/null
+++ b/tools/devops/automation/templates/common/provision.yml
@@ -0,0 +1,116 @@
+# yamllint disable rule:line-length
+# Template to run provisionator via the bootstrap script with BosStorageMirror SAS token auth.
+# This replaces the xamops.azdevex.provisionator-task.provisionator@3 task to avoid
+# dl.internalx.com timeout issues under concurrent load.
+
+parameters:
+ - name: provisioning_script
+ type: string
+
+ - name: displayName
+ type: string
+ default: 'Provisionator'
+
+ - name: provisionatorChannel
+ type: string
+ default: 'latest'
+
+ - name: provisioning_extra_args
+ type: string
+ default: '-vvvv'
+
+ - name: timeoutInMinutes
+ type: number
+ default: 250
+
+ - name: retryCount
+ type: number
+ default: 0
+
+ - name: enabled
+ type: boolean
+ default: true
+
+steps:
+ - task: AzureCLI@2
+ displayName: 'Generate BosStorageMirror SAS tokens'
+ condition: and(succeeded(), ${{ parameters.enabled }})
+ inputs:
+ azureSubscription: 'Xamarin - RelEng (BosStorageMirror-Contributor-MI)'
+ scriptType: 'bash'
+ scriptLocation: 'inlineScript'
+ failOnStandardError: true
+ inlineScript: |
+ set -euo pipefail
+
+ storage_account="bosstoragemirror"
+
+ # macOS/BSD date syntax for expiry calculation
+ start_time="$(date -u '+%Y-%m-%dT%H:%MZ')"
+ prov_expiry="$(date -u -v+20M '+%Y-%m-%dT%H:%MZ')"
+ files_expiry="$(date -u -v+3H '+%Y-%m-%dT%H:%MZ')"
+
+ echo "Generating provisionator SAS token (expires $prov_expiry)..."
+ sas_provisionator="$(az storage container generate-sas \
+ --account-name "$storage_account" \
+ --name provisionator \
+ --permissions r \
+ --start "$start_time" \
+ --expiry "$prov_expiry" \
+ --https-only \
+ --as-user \
+ --auth-mode login \
+ -o tsv)"
+
+ if [[ -z "$sas_provisionator" || ${#sas_provisionator} -le 16 ]]; then
+ echo "ERROR: Failed to generate SAS token for BosStorageMirror provisionator container"
+ exit 1
+ fi
+
+ echo "Generating internal-files SAS token (expires $files_expiry)..."
+ sas_internal_files="$(az storage container generate-sas \
+ --account-name "$storage_account" \
+ --name internal-files \
+ --permissions r \
+ --start "$start_time" \
+ --expiry "$files_expiry" \
+ --https-only \
+ --as-user \
+ --auth-mode login \
+ -o tsv)"
+
+ if [[ -z "$sas_internal_files" || ${#sas_internal_files} -le 16 ]]; then
+ echo "ERROR: Failed to generate SAS token for BosStorageMirror internal-files container"
+ exit 1
+ fi
+
+ prov_hint="${sas_provisionator:0:8}...${sas_provisionator: -8}"
+ files_hint="${sas_internal_files:0:8}...${sas_internal_files: -8}"
+
+ echo "sasTokenProvisionator [hint]: $prov_hint"
+ echo "sasToken [hint]: $files_hint"
+
+ echo "##vso[task.setvariable variable=Provisionator.SASToken;issecret=true]$sas_provisionator"
+ echo "##vso[task.setvariable variable=Provisionator.SASTokenHint]$prov_hint"
+ echo "##vso[task.setvariable variable=BosStorageMirror.SASToken;issecret=true]$sas_internal_files"
+ echo "##vso[task.setvariable variable=BosStorageMirror.SASTokenHint]$files_hint"
+
+ - bash: |
+ set -x
+ set -e
+
+ BOOTSTRAP_SCRIPT="$(Build.SourcesDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops/automation/scripts/provisionator-bootstrap.sh"
+ chmod +x "$BOOTSTRAP_SCRIPT"
+
+ echo "Provisionator channel: ${PROVISIONATOR_CHANNEL}"
+ echo "Provisioning script: ${{ parameters.provisioning_script }}"
+
+ "$BOOTSTRAP_SCRIPT" ${{ parameters.provisioning_script }} ${{ parameters.provisioning_extra_args }} || exit 2
+ displayName: '${{ parameters.displayName }}'
+ condition: and(succeeded(), ${{ parameters.enabled }})
+ env:
+ PROVISIONATOR_CHANNEL: ${{ parameters.provisionatorChannel }}
+ AUTH_TOKEN_PROVISIONATOR: $(Provisionator.SASToken)
+ AUTH_TOKEN_BOSSTORAGEMIRROR: $(BosStorageMirror.SASToken)
+ timeoutInMinutes: ${{ parameters.timeoutInMinutes }}
+ retryCountOnTaskFailure: ${{ parameters.retryCount }}
diff --git a/tools/devops/automation/templates/mac/build.yml b/tools/devops/automation/templates/mac/build.yml
index 12cd12a3d0b4..fd4bcfacc0c4 100644
--- a/tools/devops/automation/templates/mac/build.yml
+++ b/tools/devops/automation/templates/mac/build.yml
@@ -104,14 +104,13 @@ steps:
displayName: 'Set VM Vendor'
-- task: xamops.azdevex.provisionator-task.provisionator@2
- displayName: 'Provision Brew components'
- inputs:
+- template: ../common/provision.yml
+ parameters:
provisioning_script: $(Build.SourcesDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops/provision-brew-packages.csx
- provisioning_extra_args: '-vvvv'
- github_token: $(Github.Token)
- timeoutInMinutes: 30
- enabled: false
+ displayName: 'Provision Brew components'
+ provisionatorChannel: $(PROVISIONATOR_CHANNEL)
+ timeoutInMinutes: 30
+ enabled: false
- bash: |
sudo rm -Rf $(Build.SourcesDirectory)/package
diff --git a/tools/devops/automation/templates/tests/build.yml b/tools/devops/automation/templates/tests/build.yml
index 9d94572b96d0..1eacbac94c70 100644
--- a/tools/devops/automation/templates/tests/build.yml
+++ b/tools/devops/automation/templates/tests/build.yml
@@ -203,13 +203,11 @@ steps:
condition: ${{ parameters.clearProvisionatorCache }}
# Use the provisionator to install the test dependencies. Those have been generated in the 'Generate Provisionator csx file' step.
-- task: xamops.azdevex.provisionator-task.provisionator@2
- displayName: 'Provisionator dependencies'
- inputs:
+- template: ../common/provision.yml
+ parameters:
provisioning_script: $(System.DefaultWorkingDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops/build-provisioning.csx
- provisioning_extra_args: '-vvvv'
- github_token: ${{ parameters.gitHubToken }}
- timeoutInMinutes: 250
+ displayName: 'Provisionator dependencies'
+ provisionatorChannel: $(PROVISIONATOR_CHANNEL)
- bash: |
set -x
diff --git a/tools/devops/automation/templates/windows/reserve-mac.yml b/tools/devops/automation/templates/windows/reserve-mac.yml
index c0e2c9ae0ae8..9e24069e0af6 100644
--- a/tools/devops/automation/templates/windows/reserve-mac.yml
+++ b/tools/devops/automation/templates/windows/reserve-mac.yml
@@ -99,13 +99,11 @@ steps:
rm -f ~/Library/Preferences/Xamarin/Settings.plist
displayName: 'Clear old Xcode settings'
-- task: xamops.azdevex.provisionator-task.provisionator@2
- displayName: 'Provision Xcode'
- inputs:
+- template: ../common/provision.yml
+ parameters:
provisioning_script: $(System.DefaultWorkingDirectory)/$(BUILD_REPOSITORY_TITLE)/tools/devops/provision-xcode.csx
- provisioning_extra_args: '-vvvv'
- github_token: ${{ parameters.gitHubToken }}
- timeoutInMinutes: 250
+ displayName: 'Provision Xcode'
+ provisionatorChannel: $(PROVISIONATOR_CHANNEL)
- bash: $(Build.SourcesDirectory)/$(BUILD_REPOSITORY_TITLE)/system-dependencies.sh --ignore-visual-studio --ignore-shellcheck --ignore-yamllint --provision-simulators --ignore-xcode-components
displayName: 'Provision simulators'
diff --git a/tools/dotnet-linker/Makefile b/tools/dotnet-linker/Makefile
index 033e0b101db4..eaabacd81b23 100644
--- a/tools/dotnet-linker/Makefile
+++ b/tools/dotnet-linker/Makefile
@@ -16,6 +16,7 @@ DOTNET_DIRECTORIES += \
# dotnet-linker.csproj.inc contains the dotnet_linker_dependencies variable used to determine if mtouch needs to be rebuilt or not.
dotnet-linker.csproj.inc: export BUILD_VERBOSITY=$(DOTNET_BUILD_VERBOSITY)
+dotnet-linker.csproj.inc: export DOTNET:=$(DOTNET)
dotnet-linker.csproj.inc: dotnet-linker.csproj
-include dotnet-linker.csproj.inc
diff --git a/tools/sharpie/Sharpie.Bind/ObjectiveCBinder.cs b/tools/sharpie/Sharpie.Bind/ObjectiveCBinder.cs
index 8406602d1bcf..7e76452e4acd 100644
--- a/tools/sharpie/Sharpie.Bind/ObjectiveCBinder.cs
+++ b/tools/sharpie/Sharpie.Bind/ObjectiveCBinder.cs
@@ -154,7 +154,12 @@ bool IsInScope (Decl? decl)
if (string.IsNullOrEmpty (fn))
return true;
foreach (var dir in DirectoriesInScope) {
- if (fn.StartsWith (dir, StringComparison.Ordinal))
+ // Ensure the scope directory ends with a directory separator so that
+ // a scope of "/foo/bar" doesn't falsely match "/foo/barbaz/header.h".
+ var normalizedDir = dir.EndsWith (Path.DirectorySeparatorChar) || dir.EndsWith (Path.AltDirectorySeparatorChar)
+ ? dir
+ : dir + Path.DirectorySeparatorChar;
+ if (fn.StartsWith (normalizedDir, StringComparison.Ordinal))
return true;
}
diff --git a/tools/sharpie/Sharpie.Bind/Tools.cs b/tools/sharpie/Sharpie.Bind/Tools.cs
index 1fd06094bfb4..3381d62a0962 100644
--- a/tools/sharpie/Sharpie.Bind/Tools.cs
+++ b/tools/sharpie/Sharpie.Bind/Tools.cs
@@ -33,7 +33,7 @@ public static int Bind (string [] arguments)
{ "s|sdk=", "Target SDK.", v => binder.Sdk = v },
{ "f|framework=", "The input framework to bind. Implies setting the scope (--scope) to the framework, setting the namespace (--namespace) to the name of the framework, and no other sources/headers can be specified. If the framework provides an 'Info.plist' with SDK information (DTSDKName), the '-sdk' option will be implied as well (if not manually specified).", v => binder.SourceFramework = v },
{ "header=", "The input header file to bind. This can also be a .framework directory.", v => binder.SourceFile = v },
- { "scope=", "Restrict following #include and #import directives declared in header files to within the specified DIR directory.", v => binder.DirectoriesInScope.Add (v) },
+ { "scope=", "Restrict following #include and #import directives declared in header files to within the specified DIR directory.", v => binder.DirectoriesInScope.Add (Path.GetFullPath (v)) },
{ "c|clang", "All arguments after this argument are not processed by Objective Sharpie and are proxied directly to Clang.", v => { } },
{ "clang-resource-dir=", "Specify the Clang resource directory.", v => binder.ClangResourceDirectory = v },
{ "platform-assembly=", "Specify the platform assembly to use for binding.", v => binder.PlatformAssembly = v },