From b2c73ff70858e83c0303ef0de614f51b8992c6d1 Mon Sep 17 00:00:00 2001 From: Jonathan Peppers Date: Mon, 24 Feb 2025 12:20:27 -0600 Subject: [PATCH] [NativeAOT] support multi-RID builds (#9826) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Context: https://github.com/dotnet/sdk/blob/68bf4cbabc023e5c2752ee4d5ce7e4a40929e748/src/Tasks/Microsoft.NET.Build.Tasks/targets/Microsoft.NET.RuntimeIdentifierInference.targets#L227-L229 The only blocker for supporting multi-targeted `$(RuntimeIdentifiers)=android-arm64;android-x64` builds is the error message: error NETSDK1191: A runtime identifier for the property 'PublishAot' couldn't be inferred. Specify a rid explicitly. We can set `$(AllowPublishAotWithoutRuntimeIdentifier)` by default, as this is not an error we'd ever want to show on Android. After this change I can see the MSBuild terminal logger shows the two RIDs building in parallel: NativeAOT IlcCompile (8.7s) NativeAOT IlcCompile (8.6s) And the resulting `.apk` has both `lib/arm64-v8a` and `lib/x86_64`. I also updated some of our MSBuild test infrastructure to make it easier to parameterize more MSBuild tests for `$(PublishAot)=true` in the future. We'll likely want to update tests like: [Test] public void SomeTest ([Values (true, false)] bool publishAot) { var proj = new XamarinAndroidApplicationProject (); proj.SetPublishAot (publishAot, AndroidNdkPath); // … } --- samples/NativeAOT/NativeAOT.csproj | 4 ---- .../Microsoft.Android.Sdk.NativeAOT.targets | 2 ++ .../Xamarin.Android.Build.Tests/BuildTest2.cs | 20 +++++++--------- .../Android/KnownProperties.cs | 1 + .../XamarinAndroidApplicationProject.cs | 24 +++++++++++++++++++ 5 files changed, 35 insertions(+), 16 deletions(-) diff --git a/samples/NativeAOT/NativeAOT.csproj b/samples/NativeAOT/NativeAOT.csproj index 8643c56ef1b..8b9148c5a88 100644 --- a/samples/NativeAOT/NativeAOT.csproj +++ b/samples/NativeAOT/NativeAOT.csproj @@ -9,16 +9,12 @@ 1 1.0 apk - - android-arm64 true - - android-x64 <_NuGetFolderOnCI>..\..\bin\Build$(Configuration)\nuget-unsigned $(_NuGetFolderOnCI) <_FastDeploymentDiagnosticLogging>true diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets index 0735371eacc..9dd225160fe 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.NativeAOT.targets @@ -13,6 +13,8 @@ This file contains the NativeAOT-specific MSBuild logic for .NET for Android. <_AndroidRuntimePackRuntime>NativeAOT JavaInterop1 + + true true diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs index e687e1e605d..1b52f3d9f9a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest2.cs @@ -125,15 +125,8 @@ public void NativeAOT () { var proj = new XamarinAndroidApplicationProject { ProjectName = "Hello", - IsRelease = true, - RuntimeIdentifier = "android-arm64", - // Add locally downloaded NativeAOT packs - ExtraNuGetConfigSources = { - Path.Combine (XABuildPaths.BuildOutputDirectory, "nuget-unsigned"), - } }; - proj.SetProperty ("PublishAot", "true"); - proj.SetProperty ("AndroidNdkDirectory", AndroidNdkPath); + proj.SetPublishAot (true, AndroidNdkPath); proj.SetProperty ("_ExtraTrimmerArgs", "--verbose"); // Required for java/util/ArrayList assertion below @@ -149,16 +142,19 @@ public void NativeAOT () ]; string[] mono_files = [ "lib/arm64-v8a/libmonosgen-2.0.so", + "lib/x86_64/libmonosgen-2.0.so", ]; string [] nativeaot_files = [ $"lib/arm64-v8a/lib{proj.ProjectName}.so", "lib/arm64-v8a/libc++_shared.so", + $"lib/x86_64/lib{proj.ProjectName}.so", + "lib/x86_64/libc++_shared.so", ]; - var intermediate = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, proj.RuntimeIdentifier); - var output = Path.Combine (Root, b.ProjectDirectory, proj.OutputPath, proj.RuntimeIdentifier); + var intermediate = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath); + var output = Path.Combine (Root, b.ProjectDirectory, proj.OutputPath); - var linkedMonoAndroidAssembly = Path.Combine (intermediate, "linked", "Mono.Android.dll"); + var linkedMonoAndroidAssembly = Path.Combine (intermediate, "android-arm64", "linked", "Mono.Android.dll"); FileAssert.Exists (linkedMonoAndroidAssembly); using (var assembly = AssemblyDefinition.ReadAssembly (linkedMonoAndroidAssembly)) { var typeName = "Android.App.Activity"; @@ -170,7 +166,7 @@ public void NativeAOT () } var typemap = new Dictionary (); - var linkedRuntimeAssembly = Path.Combine (intermediate, "linked", "Microsoft.Android.Runtime.NativeAOT.dll"); + var linkedRuntimeAssembly = Path.Combine (intermediate, "android-arm64", "linked", "Microsoft.Android.Runtime.NativeAOT.dll"); FileAssert.Exists (linkedRuntimeAssembly); using (var assembly = AssemblyDefinition.ReadAssembly (linkedRuntimeAssembly)) { var type = assembly.MainModule.Types.FirstOrDefault (t => t.Name == "NativeAotTypeManager"); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownProperties.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownProperties.cs index 427ec8cb52a..dfc9da64a38 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownProperties.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/KnownProperties.cs @@ -36,5 +36,6 @@ public static class KnownProperties public const string _AndroidAllowDeltaInstall = "_AndroidAllowDeltaInstall"; public const string Nullable = "Nullable"; public const string ImplicitUsings = "ImplicitUsings"; + public const string PublishAot = "PublishAot"; } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs index 7cf28b8ace0..772b0f3a438 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/XamarinAndroidApplicationProject.cs @@ -165,6 +165,30 @@ public bool EnableMarshalMethods { set { SetProperty (KnownProperties.AndroidEnableMarshalMethods, value.ToString ()); } } + private bool PublishAot { + get { return string.Equals (GetProperty (KnownProperties.PublishAot), "True", StringComparison.OrdinalIgnoreCase); } + set { SetProperty (KnownProperties.PublishAot, value.ToString ()); } + } + + /// + /// Sets properties required for $(PublishAot)=true + /// + public void SetPublishAot (bool value, string androidNdkPath) + { + IsRelease = value; + PublishAot = value; + SetProperty ("AndroidNdkDirectory", androidNdkPath); + + // NuGet feed needed as Microsoft.Android.Runtime.NativeAOT packs not installed in workload by default + var source = Path.Combine (XABuildPaths.BuildOutputDirectory, "nuget-unsigned"); + if (value) { + if (!ExtraNuGetConfigSources.Contains (source)) + ExtraNuGetConfigSources.Add (source); + } else { + ExtraNuGetConfigSources.Remove (source); + } + } + public string AndroidManifest { get; set; } public string LayoutMain { get; set; } public string MainActivity { get; set; }