diff --git a/build-tools/automation/azure-pipelines.yaml b/build-tools/automation/azure-pipelines.yaml
index fabd51a8fdd..cf31bee22e4 100644
--- a/build-tools/automation/azure-pipelines.yaml
+++ b/build-tools/automation/azure-pipelines.yaml
@@ -49,7 +49,7 @@ variables:
# - This is a non-fork branch with name containing "mono-" (for Mono bumps)
IsMonoBranch: $[and(ne(variables['System.PullRequest.IsFork'], 'True'), or(contains(variables['Build.SourceBranchName'], 'mono-'), contains(variables['System.PullRequest.SourceBranch'], 'mono-')))]
RunAllTests: $[or(eq(variables['XA.RunAllTests'], true), eq(variables['IsMonoBranch'], true))]
- DotNetNUnitCategories: '& TestCategory != DotNetIgnore & TestCategory != HybridAOT & TestCategory != ProfiledAOT & TestCategory != LLVM & TestCategory != MkBundle & TestCategory != MonoSymbolicate & TestCategory != PackagesConfig & TestCategory != StaticProject & TestCategory != Debugger & TestCategory != SystemApplication'
+ DotNetNUnitCategories: '& TestCategory != DotNetIgnore & TestCategory != HybridAOT & TestCategory != ProfiledAOT & TestCategory != MkBundle & TestCategory != MonoSymbolicate & TestCategory != PackagesConfig & TestCategory != StaticProject & TestCategory != Debugger & TestCategory != SystemApplication'
NUnit.NumberOfTestWorkers: 4
GitHub.Token: $(github--pat--vs-mobiletools-engineering-service2)
CONVERT_JAVADOC_TO_XMLDOC: $[ne(variables['Build.DefinitionName'], 'Xamarin.Android-PR')]
@@ -809,6 +809,17 @@ stages:
artifactFolder: net6-aot
useDotNet: true
+ - template: yaml-templates/apk-instrumentation.yaml
+ parameters:
+ configuration: $(XA.Build.Configuration)
+ testName: Mono.Android.NET_Tests-AotLlvm
+ project: tests/Mono.Android-Tests/Runtime-Microsoft.Android.Sdk/Mono.Android.NET-Tests.csproj
+ testResultsFiles: TestResult-Mono.Android.NET_Tests-$(XA.Build.Configuration)AotLlvm.xml
+ extraBuildArgs: /p:TestsFlavor=AotLlvm /p:RunAOTCompilation=true /p:EnableLlvm=true
+ artifactSource: bin/Test$(XA.Build.Configuration)/net6.0-android/Mono.Android.NET_Tests-Signed.apk
+ artifactFolder: net6-aotllvm
+ useDotNet: true
+
- task: MSBuild@1
displayName: shut down emulator
inputs:
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 705affcc8b0..e6ec675b479 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
@@ -54,17 +54,26 @@ They run in a context of an inner build with a single $(RuntimeIdentifier).
AotOutputDirectory="$(_AndroidAotBinDirectory)"
RuntimeIdentifier="$(RuntimeIdentifier)"
EnableLLVM="$(EnableLLVM)"
+ UsingAndroidNETSdk="true"
Profiles="@(_AotProfiles)">
-
+
+
+ <_MonoAOTCompilerPath>@(MonoAotCrossCompiler->WithMetadataValue('RuntimeIdentifier', '$(RuntimeIdentifier)'))
+ <_LLVMPath Condition=" '$(EnableLLVM)' == 'true' ">$([System.IO.Path]::GetDirectoryName ('$(_MonoAOTCompilerPath)'))
+
- <_MonoAOTAssemblies Include="@(_AndroidAotInputs->'%(FullPath)')" AotArguments="$(_AotArguments)" />
+ <_MonoAOTAssemblies
+ Include="@(_AndroidAotInputs->'%(FullPath)')"
+ TempDirectory="$([MSBuild]::EnsureTrailingSlash($(_AotOutputDirectory)))%(FileName)"
+ AotArguments="$(_AotArguments),temp-path=$([System.IO.Path]::GetFullPath(%(_MonoAOTAssemblies.TempDirectory)))"
+ />
-
+
GetAotConfigs (NdkTools ndk)
}
string toolPrefix = GetToolPrefix (ndk, arch, out int level);
- var toolchainPath = toolPrefix.Substring(0, toolPrefix.LastIndexOf(Path.DirectorySeparatorChar));
- var ldFlags = string.Empty;
- if (EnableLLVM) {
- if (string.IsNullOrEmpty (AndroidNdkDirectory)) {
- yield return Config.Invalid;
- yield break;
- }
-
- string androidLibPath = string.Empty;
- try {
- androidLibPath = ndk.GetDirectoryPath (NdkToolchainDir.PlatformLib, arch, level);
- } catch (InvalidOperationException ex) {
- Diagnostic.Error (5101, ex.Message);
- }
-
- string toolchainLibDir;
- if (ndk.UsesClang)
- toolchainLibDir = GetNdkToolchainLibraryDir (ndk, toolchainPath, arch);
- else
- toolchainLibDir = GetNdkToolchainLibraryDir (ndk, toolchainPath);
-
- var libs = new List();
- if (ndk.UsesClang) {
- libs.Add ($"-L{toolchainLibDir.TrimEnd ('\\')}");
- libs.Add ($"-L{androidLibPath.TrimEnd ('\\')}");
-
- if (arch == AndroidTargetArch.Arm) {
- // Needed for -lunwind to work
- string compilerLibDir = Path.Combine (toolchainPath, "..", "sysroot", "usr", "lib", ndk.GetArchDirName (arch));
- libs.Add ($"-L{compilerLibDir.TrimEnd ('\\')}");
- }
- }
-
- libs.Add (Path.Combine (toolchainLibDir, "libgcc.a"));
- libs.Add (Path.Combine (androidLibPath, "libc.so"));
- libs.Add (Path.Combine (androidLibPath, "libm.so"));
-
- ldFlags = $"\\\"{string.Join("\\\";\\\"", libs)}\\\"";
- }
-
- string ldName = String.Empty;
- if (EnableLLVM) {
- ldName = ndk.GetToolPath (NdkToolKind.Linker, arch, level);
- if (!String.IsNullOrEmpty (ldName)) {
- ldName = Path.GetFileName (ldName);
- if (ldName.IndexOf ('-') >= 0) {
- ldName = ldName.Substring (ldName.LastIndexOf ("-") + 1);
- }
- }
- } else {
- ldName = "ld";
- }
-
foreach (var assembly in ResolvedAssemblies) {
string outputFile = Path.Combine(outdir, string.Format ("libaot-{0}.so",
Path.GetFileName (assembly.ItemSpec)));
@@ -232,20 +138,13 @@ IEnumerable GetAotConfigs (NdkTools ndk)
Path.GetFileName (assembly.ItemSpec)));
string tempDir = Path.Combine (outdir, Path.GetFileName (assembly.ItemSpec));
- if (!Directory.Exists (tempDir))
- Directory.CreateDirectory (tempDir);
-
- var aotOptions = GetAotOptions (outdir, mtriple, toolPrefix);
- aotOptions.Add ($"outfile={outputFile}");
- aotOptions.Add ($"llvm-path={SdkBinDirectory}");
- aotOptions.Add ($"temp-path={tempDir}");
-
- if (!String.IsNullOrEmpty (ldName)) {
- // MUST be before `ld-flags`, otherwise Mono fails to parse it on Windows
- aotOptions.Add ($"ld-name={ldName}");
- }
+ Directory.CreateDirectory (tempDir);
- aotOptions.Add ($"ld-flags={ldFlags}");
+ var aotOptions = GetAotOptions (ndk, arch, level, outdir, mtriple, 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}");
// we need to quote the entire --aot arguments here to make sure it is parsed
// on windows as one argument. Otherwise it will be split up into multiple
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs
index 7fcbc5299be..9e15a17aac1 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/GetAotArguments.cs
@@ -1,7 +1,9 @@
using System;
using System.Collections.Generic;
using System.IO;
+using System.Linq;
using System.Threading.Tasks;
+using Java.Interop.Tools.Diagnostics;
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Framework;
using Xamarin.Android.Tools;
@@ -48,13 +50,15 @@ public class GetAotArguments : AndroidAsyncTask
public ITaskItem [] Profiles { get; set; }
+ public bool UsingAndroidNETSdk { get; set; }
+
public string AotAdditionalArguments { get; set; }
[Output]
public string Arguments { get; set; }
[Output]
- public string LLVMPath { get; set; }
+ public string OutputDirectory { get; set; }
protected AotMode AotMode;
protected SequencePointsMode SequencePointsMode;
@@ -135,11 +139,10 @@ public override Task RunTaskAsync ()
}
(_, string outdir, string mtriple, AndroidTargetArch arch) = GetAbiSettings (abi);
- string toolPrefix = GetToolPrefix (ndk, arch, out _);
+ string toolPrefix = GetToolPrefix (ndk, arch, out int level);
- Arguments = string.Join (",", GetAotOptions (outdir, mtriple, toolPrefix));
- if (EnableLLVM)
- LLVMPath = Path.GetDirectoryName (toolPrefix);
+ Arguments = string.Join (",", GetAotOptions (ndk, arch, level, outdir, mtriple, toolPrefix));
+ OutputDirectory = outdir;
return Task.CompletedTask;
}
@@ -245,7 +248,7 @@ int GetNdkApiLevel (NdkTools ndk, AndroidTargetArch arch)
///
/// Returns a list of parameters to pass to the --aot switch
///
- protected List GetAotOptions (string outdir, string mtriple, string toolPrefix)
+ protected List GetAotOptions (NdkTools ndk, AndroidTargetArch arch, int level, string outdir, string mtriple, string toolPrefix)
{
List aotOptions = new List ();
@@ -266,7 +269,117 @@ protected List GetAotOptions (string outdir, string mtriple, string tool
aotOptions.Add ("asmwriter");
aotOptions.Add ($"mtriple={mtriple}");
aotOptions.Add ($"tool-prefix={toolPrefix}");
+
+ string ldName;
+ if (EnableLLVM) {
+ ldName = ndk.GetToolPath (NdkToolKind.Linker, arch, level);
+ if (!string.IsNullOrEmpty (ldName)) {
+ ldName = Path.GetFileName (ldName);
+ if (ldName.IndexOf ('-') >= 0) {
+ ldName = ldName.Substring (ldName.LastIndexOf ("-") + 1);
+ }
+ }
+ } else {
+ 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}");
+ }
+ if (!string.IsNullOrEmpty (ldFlags)) {
+ aotOptions.Add ($"ld-flags={ldFlags}");
+ }
+
return aotOptions;
}
+
+ string GetLdFlags(NdkTools ndk, AndroidTargetArch arch, int level, string toolPrefix)
+ {
+ var toolchainPath = toolPrefix.Substring (0, toolPrefix.LastIndexOf (Path.DirectorySeparatorChar));
+ var ldFlags = string.Empty;
+ if (EnableLLVM) {
+ if (string.IsNullOrEmpty (AndroidNdkDirectory)) {
+ return null;
+ }
+
+ string androidLibPath = string.Empty;
+ try {
+ androidLibPath = ndk.GetDirectoryPath (NdkToolchainDir.PlatformLib, arch, level);
+ } catch (InvalidOperationException ex) {
+ Diagnostic.Error (5101, ex.Message);
+ }
+
+ string toolchainLibDir;
+ if (ndk.UsesClang)
+ toolchainLibDir = GetNdkToolchainLibraryDir (ndk, toolchainPath, arch);
+ else
+ toolchainLibDir = GetNdkToolchainLibraryDir (ndk, toolchainPath);
+
+ var libs = new List ();
+ if (ndk.UsesClang) {
+ libs.Add ($"-L{toolchainLibDir.TrimEnd ('\\')}");
+ libs.Add ($"-L{androidLibPath.TrimEnd ('\\')}");
+
+ if (arch == AndroidTargetArch.Arm) {
+ // Needed for -lunwind to work
+ string compilerLibDir = Path.Combine (toolchainPath, "..", "sysroot", "usr", "lib", ndk.GetArchDirName (arch));
+ libs.Add ($"-L{compilerLibDir.TrimEnd ('\\')}");
+ }
+ }
+
+ libs.Add (Path.Combine (toolchainLibDir, "libgcc.a"));
+ 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)}\\\"";
+ }
+ }
+ return ldFlags;
+ }
+
+ static string GetNdkToolchainLibraryDir (NdkTools ndk, string binDir, string archDir = null)
+ {
+ var baseDir = Path.GetFullPath (Path.Combine (binDir, ".."));
+
+ string libDir = Path.Combine (baseDir, "lib", "gcc");
+ if (!String.IsNullOrEmpty (archDir))
+ libDir = Path.Combine (libDir, archDir);
+
+ var gccLibDir = Directory.EnumerateDirectories (libDir).ToList ();
+ gccLibDir.Sort ();
+
+ var libPath = gccLibDir.LastOrDefault ();
+ if (libPath == null) {
+ goto no_toolchain_error;
+ }
+
+ if (ndk.UsesClang)
+ return libPath;
+
+ gccLibDir = Directory.EnumerateDirectories (libPath).ToList ();
+ gccLibDir.Sort ();
+
+ libPath = gccLibDir.LastOrDefault ();
+ if (libPath == null) {
+ goto no_toolchain_error;
+ }
+
+ return libPath;
+
+ no_toolchain_error:
+ throw new Exception ("Could not find a valid NDK compiler toolchain library path");
+ }
+
+ static string GetNdkToolchainLibraryDir (NdkTools ndk, string binDir, AndroidTargetArch arch)
+ {
+ return GetNdkToolchainLibraryDir (ndk, binDir, ndk.GetArchDirName (arch));
+ }
}
}
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 b0ea6906eb6..3ed2c53e192 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,6 +26,10 @@ 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;
@@ -45,6 +49,10 @@ 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);
@@ -150,8 +158,6 @@ public void BuildBasicApplicationReleaseProfiledAotWithoutDefaultProfile ()
[Category ("DotNetIgnore")] // Not currently working, see: https://github.com/dotnet/runtime/issues/56163
public void BuildAotApplicationAndÜmläüts (string supportedAbis, bool enableLLVM, bool expectedResult)
{
- AssertLLVMSupported (enableLLVM);
-
var path = Path.Combine ("temp", string.Format ("BuildAotApplication AndÜmläüts_{0}_{1}_{2}", supportedAbis, enableLLVM, expectedResult));
var proj = new XamarinAndroidApplicationProject () {
IsRelease = true,
@@ -230,8 +236,6 @@ public void BuildAotApplicationAndÜmläüts (string supportedAbis, bool enableL
[Category ("DotNetIgnore")] // Not currently working, see: https://github.com/dotnet/runtime/issues/56163
public void BuildAotApplicationAndBundleAndÜmläüts (string supportedAbis, bool enableLLVM, bool expectedResult)
{
- AssertLLVMSupported (enableLLVM);
-
var path = Path.Combine ("temp", string.Format ("BuildAotApplicationAndBundle AndÜmläüts_{0}_{1}_{2}", supportedAbis, enableLLVM, expectedResult));
var proj = new XamarinAndroidApplicationProject () {
IsRelease = true,
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs
index f4073426fa3..980d0918fca 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs
@@ -205,13 +205,6 @@ protected static void AssertAotModeSupported (string aotMode)
}
}
- protected static void AssertLLVMSupported (bool llvm)
- {
- if (Builder.UseDotNet && llvm) {
- Assert.Ignore ($"EnableLLVM={llvm} is not yet supported in .NET 6+");
- }
- }
-
protected static void AssertTargetFrameworkVersionSupported (string targetFrameworkVersion)
{
if (Builder.UseDotNet)