diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Aot.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Aot.targets index 0d8efae0eba..73f6867da17 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Aot.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.Aot.targets @@ -53,14 +53,17 @@ They run in a context of an inner build with a single $(RuntimeIdentifier). AndroidApiLevel="$(_AndroidApiLevel)" MinimumSupportedApiLevel="$(AndroidMinimumSupportedApiLevel)" AndroidSequencePointsMode="$(_SequencePointsMode)" - AotAdditionalArguments="$(AndroidAotAdditionalArguments)" TargetName="$(TargetName)" ResolvedAssemblies="@(_AndroidAotInputs)" AotOutputDirectory="$(_AndroidAotBinDirectory)" RuntimeIdentifier="$(RuntimeIdentifier)" EnableLLVM="$(EnableLLVM)" - UsingAndroidNETSdk="true" Profiles="@(AndroidAotProfile)"> + + + + + @@ -69,7 +72,10 @@ They run in a context of an inner build with a single $(RuntimeIdentifier). + LLVMPath="$(_LLVMPath)" + LdName="$(_LdName)" + LdFlags="$(_LdFlags)" + WorkingDirectory="$(MSBuildProjectDirectory)" + AotArguments="$(AndroidAotAdditionalArguments)"> diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs b/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs index a6b2636ca1b..90a8091770c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/Aot.cs @@ -45,6 +45,8 @@ public class Aot : GetAotArguments public string ExtraAotOptions { get; set; } + public string AotAdditionalArguments { get; set; } + [Output] public string[] NativeLibrariesReferences { get; set; } @@ -137,11 +139,27 @@ IEnumerable GetAotConfigs (NdkTools ndk) string tempDir = Path.Combine (outdir, Path.GetFileName (assembly.ItemSpec)); Directory.CreateDirectory (tempDir); - var aotOptions = GetAotOptions (ndk, arch, level, outdir, mtriple, toolPrefix); + GetAotOptions (ndk, arch, level, outdir, toolPrefix); // NOTE: ordering seems to matter on Windows - aotOptions.Insert (0, $"outfile={outputFile}"); - aotOptions.Insert (0, $"llvm-path={SdkBinDirectory}"); - aotOptions.Insert (0, $"temp-path={tempDir}"); + var aotOptions = new List (); + aotOptions.Add ("asmwriter"); + aotOptions.Add ($"mtriple={mtriple}"); + aotOptions.Add ($"tool-prefix={toolPrefix}"); + aotOptions.Add ($"outfile={outputFile}"); + aotOptions.Add ($"llvm-path={SdkBinDirectory}"); + aotOptions.Add ($"temp-path={tempDir}"); + if (!string.IsNullOrEmpty (AotAdditionalArguments)) { + aotOptions.Add (AotAdditionalArguments); + } + if (!string.IsNullOrEmpty (MsymPath)) { + aotOptions.Add ($"msym-dir={MsymPath}"); + } + if (!string.IsNullOrEmpty (LdName)) { + aotOptions.Add ($"ld-name={LdName}"); + } + if (!string.IsNullOrEmpty (LdFlags)) { + aotOptions.Add ($"ld-flags={LdFlags}"); + } if (Profiles != null && Profiles.Length > 0) { if (Path.GetFileNameWithoutExtension (assembly.ItemSpec) == TargetName) { LogDebugMessage ($"Not using profile(s) for main assembly: {assembly.ItemSpec}"); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs index ed632e9d946..e060844ab81 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs @@ -51,13 +51,24 @@ public abstract class GetAotArguments : AndroidAsyncTask public ITaskItem [] Profiles { get; set; } = Array.Empty (); - public bool UsingAndroidNETSdk { get; set; } - - public string AotAdditionalArguments { get; set; } = ""; - [Required, Output] public ITaskItem [] ResolvedAssemblies { get; set; } = Array.Empty (); + [Output] + public string? Triple { get; set; } + + [Output] + public string? ToolPrefix { get; set; } + + [Output] + public string? MsymPath { get; set; } + + [Output] + public string? LdName { get; set; } + + [Output] + public string? LdFlags { get; set; } + protected AotMode AotMode; protected SequencePointsMode SequencePointsMode; protected string SdkBinDirectory = ""; @@ -208,22 +219,12 @@ int GetNdkApiLevel (NdkTools ndk, AndroidTargetArch arch) } /// - /// Returns a list of parameters to pass to the --aot switch + /// Fills [Output] parameters to pass to the --aot switch /// - protected List GetAotOptions (NdkTools ndk, AndroidTargetArch arch, int level, string outdir, string mtriple, string toolPrefix) + protected void GetAotOptions (NdkTools ndk, AndroidTargetArch arch, int level, string outdir, string toolPrefix) { - List aotOptions = new List (); - - if (!string.IsNullOrEmpty (AotAdditionalArguments)) - aotOptions.Add (AotAdditionalArguments); if (SequencePointsMode == SequencePointsMode.Offline) - aotOptions.Add ($"msym-dir={outdir}"); - if (AotMode != AotMode.Normal) - aotOptions.Add (AotMode.ToString ().ToLowerInvariant ()); - - aotOptions.Add ("asmwriter"); - aotOptions.Add ($"mtriple={mtriple}"); - aotOptions.Add ($"tool-prefix={toolPrefix}"); + MsymPath = outdir; string ldName; if (EnableLLVM) { @@ -238,16 +239,12 @@ protected List GetAotOptions (NdkTools ndk, AndroidTargetArch arch, int ldName = "ld"; } string ldFlags = GetLdFlags (ndk, arch, level, toolPrefix); - - // MUST be before `ld-flags`, otherwise Mono fails to parse it on Windows if (!string.IsNullOrEmpty (ldName)) { - aotOptions.Add ($"ld-name={ldName}"); + LdName = ldName; } if (!string.IsNullOrEmpty (ldFlags)) { - aotOptions.Add ($"ld-flags={ldFlags}"); + LdFlags = ldFlags; } - - return aotOptions; } string GetLdFlags(NdkTools ndk, AndroidTargetArch arch, int level, string toolPrefix) @@ -292,13 +289,7 @@ string GetLdFlags(NdkTools ndk, AndroidTargetArch arch, int level, string toolPr libs.Add (Path.Combine (androidLibPath, "libc.so")); libs.Add (Path.Combine (androidLibPath, "libm.so")); - if (UsingAndroidNETSdk) { - // NOTE: in .NET 6+ use space for the delimiter and escape spaces in paths - var escaped = libs.Select (l => l.Replace (" ", "\\ ")); - ldFlags = string.Join (" ", escaped); - } else { - ldFlags = $"\\\"{string.Join ("\\\";\\\"", libs)}\\\""; - } + ldFlags = $"\\\"{string.Join ("\\\";\\\"", libs)}\\\""; } return ldFlags; } diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GetAotAssemblies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GetAotAssemblies.cs index f87e8e479fd..d9c98fa208a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GetAotAssemblies.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GetAotAssemblies.cs @@ -42,9 +42,10 @@ public override Task RunTaskAsync () } (_, string outdir, string mtriple, AndroidTargetArch arch) = GetAbiSettings (abi); - string toolPrefix = GetToolPrefix (ndk, arch, out int level); + Triple = mtriple; + ToolPrefix = GetToolPrefix (ndk, arch, out int level); - var aotOptions = GetAotOptions (ndk, arch, level, outdir, mtriple, toolPrefix); + GetAotOptions (ndk, arch, level, outdir, ToolPrefix); var aotProfiles = new StringBuilder (); if (Profiles != null && Profiles.Length > 0) { @@ -56,15 +57,16 @@ public override Task RunTaskAsync () } } - var arguments = string.Join (",", aotOptions); foreach (var assembly in ResolvedAssemblies) { - var temp = Path.GetFullPath (Path.Combine (outdir, Path.GetFileNameWithoutExtension (assembly.ItemSpec))); + var temp = Path.Combine (outdir, Path.GetFileNameWithoutExtension (assembly.ItemSpec)); Directory.CreateDirectory (temp); if (Path.GetFileNameWithoutExtension (assembly.ItemSpec) == TargetName) { - LogDebugMessage ($"Not using profile(s) for main assembly: {assembly.ItemSpec}"); - assembly.SetMetadata ("AotArguments", $"{arguments},temp-path={temp}"); + if (Profiles != null && Profiles.Length > 0) { + LogDebugMessage ($"Not using profile(s) for main assembly: {assembly.ItemSpec}"); + } + assembly.SetMetadata ("AotArguments", $"asmwriter,temp-path={temp}"); } else { - assembly.SetMetadata ("AotArguments", $"{arguments},temp-path={temp}{aotProfiles}"); + assembly.SetMetadata ("AotArguments", $"asmwriter,temp-path={temp}{aotProfiles}"); } } diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs index a2b6fab31c3..7356a582a98 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AotTests.cs @@ -26,10 +26,6 @@ public void Setup () { if (!IsWindows) return; - // Use standard NDK directory for now - // See: https://github.com/dotnet/runtime/issues/56163 - if (Builder.UseDotNet) - return; var sdkPath = AndroidSdkPath; var ndkPath = AndroidNdkPath; @@ -49,10 +45,6 @@ public void TearDown () { if (!IsWindows) return; - // Use standard NDK directory for now - // See: https://github.com/dotnet/runtime/issues/56163 - if (Builder.UseDotNet) - return; Environment.SetEnvironmentVariable ("TEST_ANDROID_SDK_PATH", ""); Environment.SetEnvironmentVariable ("TEST_ANDROID_NDK_PATH", ""); Directory.Delete (SdkWithSpacesPath, recursive: true); @@ -169,7 +161,6 @@ public void BuildBasicApplicationReleaseProfiledAotWithoutDefaultProfile () [Test] [TestCaseSource (nameof (AotChecks))] - [Category ("DotNetIgnore")] // Not currently working, see: https://github.com/dotnet/runtime/issues/56163 public void BuildAotApplicationAndÜmläüts (string supportedAbis, bool enableLLVM, bool expectedResult, bool usesAssemblyBlobs) { var path = Path.Combine ("temp", string.Format ("BuildAotApplication AndÜmläüts_{0}_{1}_{2}_{3}", supportedAbis, enableLLVM, expectedResult, usesAssemblyBlobs)); @@ -203,7 +194,7 @@ public void BuildBasicApplicationReleaseProfiledAotWithoutDefaultProfile () if (!expectedResult) return; //NOTE: Windows has shortened paths such as: C:\Users\myuser\ANDROI~3\ndk\PLATFO~1\AN3971~1\arch-x86\usr\lib\libc.so - if (checkMinLlvmPath && !IsWindows) { + if (checkMinLlvmPath && !IsWindows && !Builder.UseDotNet) { Xamarin.Android.Tasks.NdkTools ndk = Xamarin.Android.Tasks.NdkTools.Create (AndroidNdkPath); bool ndk22OrNewer = ndk.Version.Main.Major >= 22; @@ -218,12 +209,13 @@ public void BuildBasicApplicationReleaseProfiledAotWithoutDefaultProfile () } } foreach (var abi in supportedAbis.Split (new char [] { ';' })) { - var libapp = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, - "bundles", abi, "libmonodroid_bundle_app.so"); - Assert.IsFalse (File.Exists (libapp), abi + " libmonodroid_bundle_app.so should not exist"); - var assemblies = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, - "aot", abi, "libaot-UnnamedProject.dll.so"); - Assert.IsTrue (File.Exists (assemblies), "{0} libaot-UnnamedProject.dll.so does not exist", abi); + var intermediate = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath); + var libapp = Path.Combine (intermediate, "bundles", abi, "libmonodroid_bundle_app.so"); + FileAssert.DoesNotExist (libapp); + var aotNativeLibrary = Builder.UseDotNet ? + Path.Combine (intermediate, AbiUtils.AbiToRuntimeIdentifier (abi), "aot", "UnnamedProject.dll.so") : + Path.Combine (intermediate, "aot", abi, "libaot-UnnamedProject.dll.so"); + FileAssert.Exists (aotNativeLibrary); var apk = Path.Combine (Root, b.ProjectDirectory, proj.OutputPath, $"{proj.PackageName}-Signed.apk"); @@ -248,7 +240,6 @@ public void BuildBasicApplicationReleaseProfiledAotWithoutDefaultProfile () [Test] [TestCaseSource (nameof (AotChecks))] [Category ("Minor"), Category ("MkBundle")] - [Category ("DotNetIgnore")] // Not currently working, see: https://github.com/dotnet/runtime/issues/56163 public void BuildAotApplicationAndBundleAndÜmläüts (string supportedAbis, bool enableLLVM, bool expectedResult, bool usesAssemblyBlobs) { var path = Path.Combine ("temp", string.Format ("BuildAotApplicationAndBundle AndÜmläüts_{0}_{1}_{2}_{3}", supportedAbis, enableLLVM, expectedResult, usesAssemblyBlobs)); @@ -449,10 +440,6 @@ public static void Foo () { [Category ("LLVM")] public void NoSymbolsArgShouldReduceAppSize ([Values ("", "Hybrid")] string androidAotMode) { - if (Builder.UseDotNet) { - Assert.Ignore ("https://github.com/dotnet/runtime/issues/57800"); - } - AssertAotModeSupported (androidAotMode); var proj = new XamarinAndroidApplicationProject () { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/AbiUtils.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/AbiUtils.cs new file mode 100644 index 00000000000..5873229dff2 --- /dev/null +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/AbiUtils.cs @@ -0,0 +1,21 @@ +using System; + +namespace Xamarin.ProjectTools +{ + public static class AbiUtils + { + public static string AbiToRuntimeIdentifier (string androidAbi) + { + if (androidAbi == "armeabi-v7a") { + return "android-arm"; + } else if (androidAbi == "arm64-v8a") { + return "android-arm64"; + } else if (androidAbi == "x86") { + return "android-x86"; + } else if (androidAbi == "x86_64") { + return "android-x64"; + } + throw new InvalidOperationException ($"Unknown abi: {androidAbi}"); + } + } +} diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/ProjectExtensions.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/ProjectExtensions.cs index 10cd90c18e3..87795118382 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/ProjectExtensions.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Utilities/ProjectExtensions.cs @@ -31,30 +31,14 @@ public static void SetAndroidSupportedAbis (this IShortFormProject project, stri public static void SetRuntimeIdentifier (this IShortFormProject project, string androidAbi) { - if (androidAbi == "armeabi-v7a") { - project.SetProperty (KnownProperties.RuntimeIdentifier, "android-arm"); - } else if (androidAbi == "arm64-v8a") { - project.SetProperty (KnownProperties.RuntimeIdentifier, "android-arm64"); - } else if (androidAbi == "x86") { - project.SetProperty (KnownProperties.RuntimeIdentifier, "android-x86"); - } else if (androidAbi == "x86_64") { - project.SetProperty (KnownProperties.RuntimeIdentifier, "android-x64"); - } + project.SetProperty (KnownProperties.RuntimeIdentifier, AbiUtils.AbiToRuntimeIdentifier (androidAbi)); } public static void SetRuntimeIdentifiers (this IShortFormProject project, string [] androidAbis) { var abis = new List (); foreach (var androidAbi in androidAbis) { - if (androidAbi == "armeabi-v7a") { - abis.Add ("android-arm"); - } else if (androidAbi == "arm64-v8a") { - abis.Add ("android-arm64"); - } else if (androidAbi == "x86") { - abis.Add ("android-x86"); - } else if (androidAbi == "x86_64") { - abis.Add ("android-x64"); - } + abis.Add (AbiUtils.AbiToRuntimeIdentifier (androidAbi)); } project.SetProperty (KnownProperties.RuntimeIdentifiers, string.Join (";", abis)); }