Skip to content

Commit

Permalink
Copy PR 7406 to test if it works for marshal methods
Browse files Browse the repository at this point in the history
  • Loading branch information
grendello committed Sep 27, 2022
1 parent 98655ea commit 5d138d0
Show file tree
Hide file tree
Showing 9 changed files with 69 additions and 61 deletions.
37 changes: 37 additions & 0 deletions Documentation/guides/messages/xa1030.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
---
title: Xamarin.Android error XA1030
description: XA1030 error code
ms.date: 09/26/2022
---
# Xamarin.Android error XA1030

## Example messages

```
The 'RunAOTCompilation' MSBuild property is only supported when trimming is enabled. Edit the project file in a text editor to set 'PublishTrimmed' to 'true' for this build configuration.
```

## Solution

Instead of using:

```xml
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<RunAOTCompilation>true</RunAOTCompilation>
<!-- Either of these disable the linker/trimmer -->
<PublishTrimmed>false</PublishTrimmed>
<AndroidLinkMode>None</AndroidLinkMode>
</PropertyGroup>
```

Use the default value for `$(PublishTrimmed)` and `$(AndroidLinkMode)`
instead:

```xml
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<RunAOTCompilation>true</RunAOTCompilation>
</PropertyGroup>
```

Additionally, as mentioned by [`XA0119`](xa0119.md), you should not
use `$(RunAOTCompilation)` in `Debug` configurations.
48 changes: 3 additions & 45 deletions src/Mono.Android/Android.Runtime/AndroidRuntime.cs
Original file line number Diff line number Diff line change
Expand Up @@ -464,32 +464,22 @@ static bool CallRegisterMethodByIndex (JniNativeMethodRegistrationArguments argu
public override void RegisterNativeMembers (JniType nativeClass, Type type, string? methods) =>
RegisterNativeMembers (nativeClass, type, methods.AsSpan ());

// Temporary hack, see comments in RegisterNativeMembers below
static readonly Dictionary<string, string[]> dynamicRegistrationMethods = new Dictionary<string, string[]> (StringComparer.Ordinal) {
// leaving it empty for now, until we're sure it's no longer needed (there are some test failures which may still require it to fix them)
};

public void RegisterNativeMembers (JniType nativeClass, Type type, ReadOnlySpan<char> methods)
{
RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, "AndroidTypeManager.RegisterNativeMembers called");
try {
if (methods.IsEmpty) {
if (jniAddNativeMethodRegistrationAttributePresent)
base.RegisterNativeMembers (nativeClass, type, methods.ToString ());
return;
} else if (FastRegisterNativeMembers (nativeClass, type, methods)) {
RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, " FastRegisterNativeMembers succeeded, returning");
return;
}

int methodCount = CountMethods (methods);
RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, $" methodCount: {methodCount}");
if (methodCount < 1) {
if (jniAddNativeMethodRegistrationAttributePresent) {
RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, $" calling base.RegisterNativeMembers");
base.RegisterNativeMembers (nativeClass, type, methods.ToString ());
}
RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, $" no methods to register??");
return;
}

Expand Down Expand Up @@ -527,7 +517,6 @@ public void RegisterNativeMembers (JniType nativeClass, Type type, ReadOnlySpan<
callback = CreateDynamicCallback (minfo);
needToRegisterNatives = true;
} else {
RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, $" normal registration for '{name.ToString ()}'");
Type callbackDeclaringType = type;
if (!callbackDeclaringTypeString.IsEmpty) {
callbackDeclaringType = Type.GetType (callbackDeclaringTypeString.ToString (), throwOnError: true)!;
Expand All @@ -536,40 +525,9 @@ public void RegisterNativeMembers (JniType nativeClass, Type type, ReadOnlySpan<
callbackDeclaringType = callbackDeclaringType.BaseType!;
}

// TODO: this is temporary hack, it needs a full fledged registration mechanism for methods like these (that is, ones which
// aren't registered with [Register] but are baked into Mono.Android's managed and Java code)
// bool createCallback;
// if (JNIEnvInit.MarshalMethodsEnabled) {
// RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, $" JNI marshal methods enabled, checking if we need to create the callback");
// string declaringTypeName = callbackDeclaringType.FullName;
// string callbackName = callbackString.ToString ();

// createCallback = false;
// foreach (var kvp in dynamicRegistrationMethods) {
// string dynamicTypeName = kvp.Key;

// foreach (string dynamicCallbackMethodName in kvp.Value) {
// if (ShouldRegisterDynamically (declaringTypeName, callbackName, dynamicTypeName, dynamicCallbackMethodName)) {
// createCallback = true;
// break;
// }
// }

// if (createCallback) {
// break;
// }
// }
// RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, $" createCallback after loop: {createCallback}");
// } else {
// createCallback = true;
// }

// if (createCallback) {
Logger.Log (LogLevel.Info, "monodroid-mm", $" creating delegate for: '{callbackString.ToString()}' in type {callbackDeclaringType.FullName}");
GetCallbackHandler connector = (GetCallbackHandler) Delegate.CreateDelegate (typeof (GetCallbackHandler),
callbackDeclaringType, callbackString.ToString ());
callback = connector ();
//}
GetCallbackHandler connector = (GetCallbackHandler) Delegate.CreateDelegate (typeof (GetCallbackHandler),
callbackDeclaringType, callbackString.ToString ());
callback = connector ();
}

if (callback != null) {
Expand Down
4 changes: 0 additions & 4 deletions src/Mono.Android/Android.Runtime/JNIEnvInit.cs
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,7 @@ internal struct JnienvInitializeArgs {
#endif
static unsafe void RegisterJniNatives (IntPtr typeName_ptr, int typeName_len, IntPtr jniClass, IntPtr methods_ptr, int methods_len)
{
RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, "JNIEnvInit.RegisterJniNatives called");
string typeName = new string ((char*) typeName_ptr, 0, typeName_len);
RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, $" typeName: '{typeName}'; methods_len: {methods_len}");
var type = Type.GetType (typeName);
if (type == null) {
RuntimeNativeMethods.monodroid_log (LogLevel.Error,
Expand All @@ -69,11 +67,9 @@ static unsafe void RegisterJniNatives (IntPtr typeName_ptr, int typeName_len, In

var className = Java.Interop.TypeManager.GetClassName (jniClass);
Java.Interop.TypeManager.RegisterType (className, type);
RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, $" className: '{className}'");

JniType? jniType = null;
JniType.GetCachedJniType (ref jniType, className);
RuntimeNativeMethods.monodroid_log (LogLevel.Warn, LogCategories.Default, $" jniType: '{jniType.Name}'");

ReadOnlySpan<char> methods = new ReadOnlySpan<char> ((void*) methods_ptr, methods_len);
((AndroidTypeManager)androidRuntime!.TypeManager).RegisterNativeMembers (jniType, type, methods);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@
<RunAOTCompilation Condition=" '$(RunAOTCompilation)' == '' and '$(AotAssemblies)' == 'true' ">true</RunAOTCompilation>
<RunAOTCompilation Condition=" '$(RunAOTCompilation)' == '' ">false</RunAOTCompilation>
<_AndroidXA1029 Condition=" '$(AotAssemblies)' != '' ">true</_AndroidXA1029>
<_AndroidXA1030 Condition=" '$(RunAOTCompilation)' == 'true' and '$(PublishTrimmed)' == 'false' ">true</_AndroidXA1030>
<AotAssemblies>$(RunAOTCompilation)</AotAssemblies>
<AndroidEnableProfiledAot Condition=" '$(AndroidEnableProfiledAot)' == '' and '$(RunAOTCompilation)' == 'true' ">true</AndroidEnableProfiledAot>

Expand Down
4 changes: 4 additions & 0 deletions src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,10 @@ In this message, the term "binding" means a piece of generated code that makes i
<value>The 'AotAssemblies' MSBuild property is deprecated. Edit the project file in a text editor to remove this property, and use the 'RunAOTCompilation' MSBuild property instead.</value>
<comment>The following are literal names and should not be translated: 'AotAssemblies', 'RunAOTCompilation'</comment>
</data>
<data name="XA1030" xml:space="preserve">
<value>The 'RunAOTCompilation' MSBuild property is only supported when trimming is enabled. Edit the project file in a text editor to set 'PublishTrimmed' to 'true' for this build configuration.</value>
<comment>The following are literal names and should not be translated: 'RunAOTCompilation', 'PublishTrimmed'</comment>
</data>
<data name="XA2000" xml:space="preserve">
<value>Use of AppDomain.CreateDomain() detected in assembly: {0}. .NET 6 and higher will only support a single AppDomain, so this API will no longer be available in Xamarin.Android once .NET 6 is released.</value>
<comment>The following are literal names and should not be translated: AppDomain.CreateDomain(), AppDomain
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1103,26 +1103,37 @@ public void BenchmarkDotNet ()
/* useInterpreter */ true,
/* publishTrimmed */ true,
/* aot */ true,
/* expected */ true,
},
// Debug + AOT
new object [] {
/* isRelease */ false,
/* useInterpreter */ false,
/* publishTrimmed */ true,
/* aot */ true,
/* expected */ true,
},
// Debug + PublishTrimmed
new object [] {
/* isRelease */ false,
/* useInterpreter */ false,
/* publishTrimmed */ true,
/* aot */ false,
/* expected */ true,
},
// AOT + PublishTrimmed=false
new object [] {
/* isRelease */ true,
/* useInterpreter */ false,
/* publishTrimmed */ false,
/* aot */ true,
/* expected */ false,
},
};

[Test]
[TestCaseSource (nameof (SettingCombinationsSource))]
public void SettingCombinations (bool isRelease, bool useInterpreter, bool publishTrimmed, bool aot)
public void SettingCombinations (bool isRelease, bool useInterpreter, bool publishTrimmed, bool aot, bool expected)
{
var proj = new XASdkProject {
IsRelease = isRelease,
Expand All @@ -1131,7 +1142,7 @@ public void SettingCombinations (bool isRelease, bool useInterpreter, bool publi
proj.SetProperty ("PublishTrimmed", publishTrimmed.ToString ());
proj.SetProperty ("RunAOTCompilation", aot.ToString ());
var builder = CreateDotNetBuilder (proj);
Assert.IsTrue (builder.Build (), $"{proj.ProjectName} should succeed");
Assert.AreEqual (expected, builder.Build (), $"{proj.ProjectName} should {(expected ? "succeed" : "fail")}");
}

DotNetCLI CreateDotNetBuilder (string relativeProjectDir = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,10 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
ResourceName="XA1029"
Condition=" $(_AndroidXA1029) == 'true' "
/>
<AndroidError Code="XA1030"
ResourceName="XA1030"
Condition=" $(_AndroidXA1030) == 'true' "
/>
<AndroidError Code="XA1011"
ResourceName="XA1011"
Condition=" '$(AndroidLinkTool)' == 'proguard' And '$(AndroidDexTool)' == 'd8' "
Expand Down
16 changes: 6 additions & 10 deletions tests/MSBuildDeviceIntegration/Tests/XASdkDeployTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,44 +23,43 @@ public class XASdkDeployTests : DeviceTest
new object[] {
/* isRelease */ false,
/* xamarinForms */ false,
/* publishTrimmed */ default (bool?),
/* targetFramework*/ "net7.0-android",
},
new object[] {
/* isRelease */ true,
/* xamarinForms */ false,
/* publishTrimmed */ default (bool?),
/* targetFramework*/ "net7.0-android",
},
new object[] {
/* isRelease */ false,
/* xamarinForms */ true,
/* publishTrimmed */ default (bool?),
/* targetFramework*/ "net7.0-android",
},
new object[] {
/* isRelease */ true,
/* xamarinForms */ true,
/* publishTrimmed */ default (bool?),
/* targetFramework*/ "net7.0-android",
},
new object[] {
/* isRelease */ true,
/* xamarinForms */ false,
/* publishTrimmed */ false,
/* targetFramework*/ "net7.0-android",
},
new object[] {
/* isRelease */ false,
/* xamarinForms */ true,
/* targetFramework*/ "net6.0-android",
},
new object[] {
/* isRelease */ true,
/* xamarinForms */ true,
/* publishTrimmed */ true,
/* targetFramework*/ "net6.0-android",
},
};

[Test]
[TestCaseSource (nameof (DotNetInstallAndRunSource))]
public void DotNetInstallAndRun (bool isRelease, bool xamarinForms, bool? publishTrimmed, string targetFramework)
public void DotNetInstallAndRun (bool isRelease, bool xamarinForms, string targetFramework)
{
AssertHasDevices ();

Expand All @@ -82,9 +81,6 @@ public void DotNetInstallAndRun (bool isRelease, bool xamarinForms, bool? publis
"https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json",
};
}
if (publishTrimmed != null) {
proj.SetProperty (KnownProperties.PublishTrimmed, publishTrimmed.ToString ());
}
proj.SetRuntimeIdentifier (DeviceAbi);

var relativeProjDir = Path.Combine ("temp", TestName);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

<PropertyGroup>
<TargetFramework>$(DotNetAndroidTargetFramework)</TargetFramework>
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
<RootNamespace>Xamarin.Android.RuntimeTests</RootNamespace>
<OutputType>Exe</OutputType>
<SignAssembly>true</SignAssembly>
Expand Down

0 comments on commit 5d138d0

Please sign in to comment.