Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] Fix native code generation when marshal…
Browse files Browse the repository at this point in the history
… methods are disabled (#7899)

Disabling marshal method generation via
`$(AndroidEnableMarshalMethods)`=False turns off a lot of native code
generation in the `MarshalMethodsNativeAssemblyGenerator` class, but
the class is also responsible for outputting a correctly sized cache
area (an array of *X* pointers) to be used by the native runtime to
cache pointers to `MonoImage` instances.

`libmonodroid.so` trusts that `Xamarin.Android.Build.Tasks.dll` et al
will generate correct code, and thus does not verify the size of
generated array.  This trust, unfortunately, was broken because with
marshal methods disabled, the native code generator created an output
cache array that was 0 entries in size, thus leading to segfault when
attempting to run the application.

Fix the issue and also parametrize one of the on-device tests to be
built twice, with marshal methods explicitly disabled and explicitly
enabled.
  • Loading branch information
grendello authored Mar 23, 2023
1 parent 7da9e23 commit d2ade69
Show file tree
Hide file tree
Showing 5 changed files with 11 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ void AddEnvironment ()
Log
);
} else {
marshalMethodsAsmGen = new MarshalMethodsNativeAssemblyGenerator (uniqueAssemblyNames);
marshalMethodsAsmGen = new MarshalMethodsNativeAssemblyGenerator (assemblyCount, uniqueAssemblyNames);
}
marshalMethodsAsmGen.Init ();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ public static class KnownProperties
public const string AndroidUseLatestPlatformSdk = "AndroidUseLatestPlatformSdk";
public const string AndroidUseAapt2 = "AndroidUseAapt2";
public const string AndroidCreatePackagePerAbi = "AndroidCreatePackagePerAbi";
public const string AndroidEnableMarshalMethods = "AndroidEnableMarshalMethods";

public const string AndroidSupportedAbis = "AndroidSupportedAbis";
public const string RuntimeIdentifier = "RuntimeIdentifier";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,11 @@ public AndroidLinkMode AndroidLinkModeRelease {
set { SetProperty (ReleaseProperties, KnownProperties.AndroidLinkMode, value.ToString ()); }
}

public bool EnableMarshalMethods {
get { return string.Equals (GetProperty (KnownProperties.AndroidEnableMarshalMethods), "True", StringComparison.OrdinalIgnoreCase); }
set { SetProperty (KnownProperties.AndroidEnableMarshalMethods, value.ToString ()); }
}

public string AndroidManifest { get; set; }
public string LayoutMain { get; set; }
public string MainActivity { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,8 +204,9 @@ sealed class MarshalMethodName
/// <summary>
/// Constructor to be used ONLY when marshal methods are DISABLED
/// </summary>
public MarshalMethodsNativeAssemblyGenerator (ICollection<string> uniqueAssemblyNames)
public MarshalMethodsNativeAssemblyGenerator (int numberOfAssembliesInApk, ICollection<string> uniqueAssemblyNames)
{
this.numberOfAssembliesInApk = numberOfAssembliesInApk;
this.uniqueAssemblyNames = uniqueAssemblyNames ?? throw new ArgumentNullException (nameof (uniqueAssemblyNames));
generateEmptyCode = true;
}
Expand Down
3 changes: 2 additions & 1 deletion tests/MSBuildDeviceIntegration/Tests/InstallAndRunTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public void Teardown ()
}

[Test]
public void NativeAssemblyCacheWithSatelliteAssemblies ()
public void NativeAssemblyCacheWithSatelliteAssemblies ([Values (true, false)] bool enableMarshalMethods)
{
var path = Path.Combine ("temp", TestName);
var lib = new XamarinAndroidLibraryProject {
Expand All @@ -49,6 +49,7 @@ public void NativeAssemblyCacheWithSatelliteAssemblies ()

proj = new XamarinAndroidApplicationProject {
IsRelease = true,
EnableMarshalMethods = enableMarshalMethods,
};
proj.References.Add (new BuildItem.ProjectReference ($"..\\{lib.ProjectName}\\{lib.ProjectName}.csproj", lib.ProjectName, lib.ProjectGuid));
proj.SetAndroidSupportedAbis ("armeabi-v7a", "arm64-v8a", "x86", "x86_64");
Expand Down

0 comments on commit d2ade69

Please sign in to comment.