Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 11 additions & 6 deletions docs/building-apps/build-properties.md
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,9 @@ This can be overriden by setting the `BundleCreateDump` property:

Note: the `createdump` tool does currently not work for sandboxed apps ([#18961](https://github.com/dotnet/macios/issues/18961));

Only applicable to projects that use the CoreCLR runtime (which, at the moment
of this writing, is only macOS projects).
Note: an alternative option is to enable the in-process crash reporter (see [EnableCrashReport](#enablecrashreport)). The in-process crash reporter also works for sandboxed apps.

Only applicable to macOS projects.

[createdump]: https://github.com/dotnet/runtime/blob/3b63eb1346f1ddbc921374a5108d025662fb5ffd/docs/design/coreclr/botr/xplat-minidump-generation.md

Expand Down Expand Up @@ -599,10 +600,6 @@ The crash reports are written to a subdirectory of the app's caches directory.

See also: [Collect crash dumps](https://learn.microsoft.com/en-us/dotnet/core/diagnostics/collect-dumps-crash).

The in-process crash reporter is only available in the mobile CoreCLR runtime
(iOS, tvOS and Mac Catalyst); the desktop macOS runtime relies on the
[`createdump`](#bundlecreatedump) tool instead.

## EnableDefaultCodesignEntitlements

See [CodesignEntitlements](#codesignentitlements).
Expand Down Expand Up @@ -1412,6 +1409,14 @@ The product definition template (`.plist`) to be used when creating the product

Only applicable to macOS and Mac Catalyst apps.

## PublishReadyToRunComposite

Specifies whether ReadyToRun (R2R) compilation produces a single composite image containing all the assemblies, or one image per assembly.

Only composite ReadyToRun compilation is supported for iOS, tvOS and Mac Catalyst apps, because the ReadyToRun code is embedded in the app bundle as native Mach-O code, and the runtime only knows how to locate such code for a composite image. Setting this property to `false` will produce a build error; set [PublishReadyToRun](https://learn.microsoft.com/dotnet/core/deploying/ready-to-run) to `false` to turn off ReadyToRun compilation completely instead.
Comment thread
rolfbjarne marked this conversation as resolved.

Default: `true` (when `PublishReadyToRun` is `true`).

## RecommendedXcodeVersion

The version of Xcode recommended for use with this version of .NET for iOS, tvOS, macOS and Mac Catalyst.
Expand Down
12 changes: 12 additions & 0 deletions dotnet/targets/Microsoft.Sdk.R2R.targets
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,18 @@
<UsingTask Runtime="$(_TaskRuntime)" TaskName="Xamarin.MacDev.Tasks.ComputeInstructionSet" AssemblyFile="$(_TaskAssemblyName)" />
<UsingTask Runtime="$(_TaskRuntime)" TaskName="Xamarin.MacDev.Tasks.GenerateR2RModuleRegistration" AssemblyFile="$(_TaskAssemblyName)" />

<!--
Only composite ReadyToRun compilation is supported with the 'macho' container format: crossgen2
emits a Mach-O object file per assembly, but it doesn't emit the corresponding component assemblies,
and the runtime only knows how to locate platform-native ReadyToRun code for a composite image.
See https://github.com/dotnet/runtime/blob/main/docs/design/coreclr/botr/readytorun-platform-native-envelope.md
-->
<Target Name="_ValidateReadyToRunComposite"
Condition="'$(PublishReadyToRun)' == 'true' And '$(PublishReadyToRunContainerFormat)' == 'macho' And '$(PublishReadyToRunComposite)' != 'true' And '$(_CanOutputAppBundle)' == 'true'"
BeforeTargets="_PrepareForReadyToRunCompilation">
<Error Text="Setting 'PublishReadyToRunComposite' to '$(PublishReadyToRunComposite)' isn't supported for $(_PlatformName) projects, only composite ReadyToRun compilation is supported. Either remove the 'PublishReadyToRunComposite' property, or set 'PublishReadyToRun=false' to turn off ReadyToRun compilation completely." />
</Target>

<!-- Set per-module R2R header symbol names so each .o file exports a unique symbol directly,
avoiding the need for post-link symbol aliasing. -->
<Target Name="_SetR2RHeaderSymbolNames"
Expand Down
9 changes: 8 additions & 1 deletion dotnet/targets/Xamarin.Shared.Sdk.targets
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,15 @@
<!-- Verify DI trimmability at development-time, but turn the validation off for production/trimmed builds. -->
<VerifyDependencyInjectionOpenGenericServiceTrimmability Condition="'$(VerifyDependencyInjectionOpenGenericServiceTrimmability)' == '' And '$(_BundlerDebug)' != 'true'">false</VerifyDependencyInjectionOpenGenericServiceTrimmability>
<VerifyDependencyInjectionOpenGenericServiceTrimmability Condition="'$(VerifyDependencyInjectionOpenGenericServiceTrimmability)' == ''">true</VerifyDependencyInjectionOpenGenericServiceTrimmability>
<!--
Neither NativeAOT nor Mono without the interpreter support dynamic code, because everything is
AOT-compiled ahead of time. Everything else (CoreCLR, and Mono with the interpreter) does support
dynamic code, in which case we leave the property alone and let dotnet/sdk pick the default
(which is 'true').
-->
<!-- This should be set by dotnet/sdk instead, once https://github.com/dotnet/sdk/issues/25392 gets resolved. -->
<DynamicCodeSupport Condition="'$(DynamicCodeSupport)' == '' And ( '$(MtouchInterpreter)' == '' And '$(UseInterpreter)' != 'true' ) And ('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'MacCatalyst')">false</DynamicCodeSupport>
<DynamicCodeSupport Condition="'$(DynamicCodeSupport)' == '' And '$(_UseNativeAot)' == 'true'">false</DynamicCodeSupport>
<DynamicCodeSupport Condition="'$(DynamicCodeSupport)' == '' And '$(UseMonoRuntime)' == 'true' And ( '$(MtouchInterpreter)' == '' And '$(UseInterpreter)' != 'true' ) And ('$(_PlatformName)' == 'iOS' Or '$(_PlatformName)' == 'tvOS' Or '$(_PlatformName)' == 'MacCatalyst')">false</DynamicCodeSupport>
<_ComObjectDescriptorSupport Condition="'$(_ComObjectDescriptorSupport)' == ''">false</_ComObjectDescriptorSupport>

<!-- StartupHookSupport is used for Hot Reload, so we enable it unless the Optimize flag is set. -->
Expand Down
78 changes: 44 additions & 34 deletions src/AppKit/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,15 @@

namespace AppKit {

/// <summary>Specifies a return response from an application modal session.</summary>
[NoMacCatalyst]
[Native]
public enum NSRunResponse : long {
/// <summary>To be added.</summary>
/// <summary>Indicates that the modal session stopped.</summary>
Stopped = -1000,
/// <summary>To be added.</summary>
/// <summary>Indicates that the modal session was aborted.</summary>
Aborted = -1001,
/// <summary>To be added.</summary>
/// <summary>Indicates that the modal session should continue.</summary>
Continues = -1002,
}

Expand Down Expand Up @@ -342,16 +343,17 @@ public enum NSColorSpaceModel : long {
#endregion

#region NSParagraphStyle
/// <summary>Specifies the alignment of text at a tab stop.</summary>
[NoMacCatalyst]
[Native]
public enum NSTextTabType : ulong {
/// <summary>To be added.</summary>
/// <summary>Left-aligns text at the tab stop.</summary>
Left,
/// <summary>To be added.</summary>
/// <summary>Right-aligns text at the tab stop.</summary>
Right,
/// <summary>To be added.</summary>
/// <summary>Centers text at the tab stop.</summary>
Center,
/// <summary>To be added.</summary>
/// <summary>Aligns decimal characters at the tab stop.</summary>
Decimal,
}

Expand Down Expand Up @@ -1431,24 +1433,26 @@ public enum NSWindowCollectionBehavior : ulong {
CanJoinAllApplications = 1 << 18,
}

/// <summary>Specifies which windows to include in a window-number list.</summary>
[NoMacCatalyst]
[Flags]
[Native]
public enum NSWindowNumberListOptions : ulong {
/// <summary>To be added.</summary>
/// <summary>Includes windows from all applications, instead of only the calling application.</summary>
AllApplication = 1 << 0,
/// <summary>To be added.</summary>
/// <summary>Includes windows from all spaces, instead of only the active space.</summary>
AllSpaces = 1 << 4,
}

/// <summary>Specifies the direction in which a window traverses its key-view loop.</summary>
[NoMacCatalyst]
[Native]
public enum NSSelectionDirection : ulong {
/// <summary>To be added.</summary>
/// <summary>Indicates that the window is not traversing the key-view loop.</summary>
Direct = 0,
/// <summary>To be added.</summary>
/// <summary>Proceeds to the next valid key view.</summary>
Next,
/// <summary>To be added.</summary>
/// <summary>Proceeds to the previous valid key view.</summary>
Previous,
}

Expand Down Expand Up @@ -2629,14 +2633,15 @@ public enum NSTableViewColumnAutoresizingStyle : ulong {
FirstColumnOnly,
}

/// <summary>Specifies how a table view highlights selected rows.</summary>
[NoMacCatalyst]
[Native]
public enum NSTableViewSelectionHighlightStyle : long {
/// <summary>To be added.</summary>
/// <summary>Does not highlight selected rows.</summary>
None = -1,
/// <summary>To be added.</summary>
/// <summary>Uses the regular selection highlight style.</summary>
Regular = 0,
/// <summary>To be added.</summary>
/// <summary>Uses the source-list selection highlight style.</summary>
[Deprecated (PlatformName.MacOSX, 11, 0, message: "Set 'NSTableView.Style' to 'NSTableViewStyle.SourceList' instead.")]
SourceList = 1,
}
Expand Down Expand Up @@ -2676,17 +2681,18 @@ public enum NSTableColumnResizing : long {
UserResizingMask = (1 << 1),
}

/// <summary>Specifies which grid lines a table view draws.</summary>
[NoMacCatalyst]
[Flags]
[Native]
public enum NSTableViewGridStyle : ulong {
/// <summary>To be added.</summary>
/// <summary>Does not draw grid lines.</summary>
None = 0,
/// <summary>To be added.</summary>
/// <summary>Draws solid vertical grid lines.</summary>
SolidVerticalLine = 1 << 0,
/// <summary>To be added.</summary>
/// <summary>Draws solid horizontal grid lines.</summary>
SolidHorizontalLine = 1 << 1,
/// <summary>To be added.</summary>
/// <summary>Draws dashed horizontal grid lines.</summary>
DashedHorizontalGridLine = 1 << 3,
}

Expand Down Expand Up @@ -2726,40 +2732,43 @@ public enum NSImageAlignment : ulong {
Right,
}

/// <summary>Specifies the frame drawn around an image.</summary>
[NoMacCatalyst]
[Native]
public enum NSImageFrameStyle : ulong {
/// <summary>To be added.</summary>
/// <summary>Draws no frame.</summary>
None = 0,
/// <summary>To be added.</summary>
/// <summary>Draws a frame suitable for a photograph.</summary>
Photo,
/// <summary>To be added.</summary>
/// <summary>Draws a gray bezel frame.</summary>
GrayBezel,
/// <summary>To be added.</summary>
/// <summary>Draws a grooved frame.</summary>
Groove,
/// <summary>To be added.</summary>
/// <summary>Draws a button-style frame.</summary>
Button,
}

/// <summary>Specifies when a speech synthesizer pauses or stops speaking.</summary>
[NoMacCatalyst]
[Native]
public enum NSSpeechBoundary : ulong {
/// <summary>To be added.</summary>
/// <summary>Pauses or stops speaking immediately.</summary>
Immediate = 0,
/// <summary>To be added.</summary>
/// <summary>Pauses or stops speaking at the next word boundary.</summary>
Word = 1,
/// <summary>To be added.</summary>
/// <summary>Pauses or stops speaking at the next sentence boundary.</summary>
Sentence,
}

/// <summary>Specifies the visual style of a split view divider.</summary>
[NoMacCatalyst]
[Native]
public enum NSSplitViewDividerStyle : long {
/// <summary>To be added.</summary>
/// <summary>Uses a thick divider.</summary>
Thick = 1,
/// <summary>To be added.</summary>
/// <summary>Uses a thin divider.</summary>
Thin = 2,
/// <summary>To be added.</summary>
/// <summary>Uses a pane-splitter divider.</summary>
PaneSplitter = 3,
}

Expand All @@ -2775,16 +2784,17 @@ public enum NSSplitViewItemBehavior : long {
Inspector,
}

/// <summary>Specifies how an image is scaled to fit its frame.</summary>
[NoMacCatalyst]
[Native]
public enum NSImageScaling : ulong {
/// <summary>To be added.</summary>
/// <summary>Scales the image down proportionally when it is larger than the frame.</summary>
ProportionallyDown = 0,
/// <summary>To be added.</summary>
/// <summary>Scales the image independently along each axis to fill the frame.</summary>
AxesIndependently,
/// <summary>To be added.</summary>
/// <summary>Does not scale the image.</summary>
None,
/// <summary>To be added.</summary>
/// <summary>Scales the image proportionally up or down to fit the frame.</summary>
ProportionallyUpOrDown,
}

Expand Down
5 changes: 5 additions & 0 deletions src/ObjCRuntime/DynamicRegistrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -708,6 +708,11 @@ protected override Type GetGenericTypeDefinition (Type type)
return type.GetGenericTypeDefinition ();
}

protected override IEnumerable<Type> GetGenericArguments (Type type)
{
return type.GetGenericArguments ();
}

protected override bool IsDelegate (Type type)
{
return type.IsSubclassOf (typeof (System.Delegate));
Expand Down
15 changes: 15 additions & 0 deletions src/ObjCRuntime/Registrar.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1154,6 +1154,7 @@ protected virtual void OnRegisterCategory (ObjCType type, [NotNullIfNotNull (nam
protected abstract bool IsAbstract (TType type);
protected abstract bool IsPointer (TType type);
protected abstract TType GetGenericTypeDefinition (TType type);
protected abstract IEnumerable<TType> GetGenericArguments (TType type);
public abstract bool VerifyIsConstrainedToNSObject (TType type, out TType? constrained_type);
protected abstract TType? GetEnumUnderlyingType (TType type);
protected abstract bool TryGetEnumUnderlyingType ([NotNullWhen (true)] TType? tr, [NotNullWhen (true)] out TType? underlyingType);
Expand Down Expand Up @@ -2779,6 +2780,9 @@ protected string ToSignature (TType type, ObjCMember? member, ref bool success,
return "#";

if (IsINativeObject (type)) {
if (IsGenericType (type))
VerifyGenericArguments (type, member);

if (!IsGenericType (type) && !IsInterface (type) && !IsNSObject (type) && IsAbstract (type)) {
ReportWarning (4179, Errors.MT4179, type.FullName, member?.FullName);
}
Expand Down Expand Up @@ -2810,6 +2814,17 @@ protected string ToSignature (TType type, ObjCMember? member, ref bool success,
return string.Empty;
}

void VerifyGenericArguments (TType type, ObjCMember? member)
{
foreach (var argument in GetGenericArguments (type)) {
if (HasModelAttribute (argument))
throw CreateException (4192, member, Errors.MT4192, GetTypeFullName (argument), GetTypeFullName (type));

if (IsGenericType (argument))
VerifyGenericArguments (argument, member);
}
}

string ValueTypeSignature (TType type, ObjCMember member)
{
bool success = true;
Expand Down
5 changes: 2 additions & 3 deletions tests/assembly-preparer/PreserveBlockCodeHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,8 @@ static internal void Invoke (IntPtr block, int magic_number)
Assert.That ((string) attribs [0].ConstructorArguments [1].Value, Is.EqualTo ("ObjCRuntime.Trampolines.SDInnerBlock"), "First attribute's second argument");
Assert.That ((string) attribs [0].ConstructorArguments [2].Value, Is.EqualTo ("Test"), "First attribute's third argument");

// Invoke method: DDA(string memberSignature) - same declaring type, so simpler constructor.
// The signature doesn't include the parameter list, because there's only one method named 'Invoke'.
// Invoke method: DDA(string memberSignature) - same declaring type, so simpler constructor
Assert.That (attribs [1].ConstructorArguments.Count, Is.EqualTo (1), "Second attribute's argument count");
Assert.That ((string) attribs [1].ConstructorArguments [0].Value, Is.EqualTo ("Invoke"), "Second attribute's first argument");
Assert.That ((string) attribs [1].ConstructorArguments [0].Value, Is.EqualTo ("Invoke(System.IntPtr,System.Int32)"), "Second attribute's first argument");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,8 +108,7 @@ void AssertHasDynamicDependency (ICustomAttributeProvider provider, string membe

void AssertMethodHasDynamicDependencies (ICustomAttributeProvider provider)
{
// 'GetConstant' has no parameter list, because it's the only method with that name (unlike 'GetValue').
AssertHasDynamicDependency (provider, "GetConstant", "CoreAnimation.CAToneMapModeExtensions", $"Microsoft.{platform.AsString ()}");
AssertHasDynamicDependency (provider, "GetConstant(CoreAnimation.CAToneMapMode)", "CoreAnimation.CAToneMapModeExtensions", $"Microsoft.{platform.AsString ()}");
AssertHasDynamicDependency (provider, "GetValue(Foundation.NSString)", "CoreAnimation.CAToneMapModeExtensions", $"Microsoft.{platform.AsString ()}");
}

Expand Down
49 changes: 49 additions & 0 deletions tests/assembly-preparer/RegistrarTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace AssemblyPreparerTests;

public class RegistrarTests : BaseClass {
[Test]
public void ModelClassAsGenericArgument ()
{
var code = @"
using Foundation;
using ObjCRuntime;

class MyClass : NSObject {
[Export (""sessionOptions"")]
public NSDictionary<NSString, NSFileManagerDelegate> GetSessionOptions ()
{
throw new System.NotImplementedException ();
}
}
";

using var preparer = CreatePreparer (ApplePlatform.iOS, false, p => p.Registrar = RegistrarMode.ManagedStatic, code, out _);
preparer.Prepare (out _);

var logger = (TestLogger) preparer.Configuration.Logger;
var exception = logger.Errors.Single (v => v.Code == 4192);
Assert.That (exception.Message, Is.EqualTo ("The registrar cannot use the model class 'Foundation.NSFileManagerDelegate' as a generic type argument in the generic type 'Foundation.NSDictionary`2<Foundation.NSString,Foundation.NSFileManagerDelegate>'. Use the protocol interface instead of the model class."));
}

[Test]
public void ProtocolInterfaceAsGenericArgument ()
{
var code = @"
using Foundation;
using ObjCRuntime;

class MyClass : NSObject {
[Export (""sessionOptions"")]
public NSDictionary<NSString, INSFileManagerDelegate> GetSessionOptions ()
{
throw new System.NotImplementedException ();
}
}
";

AssertPrepare (ApplePlatform.iOS, false, RegistrarMode.ManagedStatic, code, out _);
}
}
Loading
Loading