From 7e4162e1a7d8759d3579576206cafc1213aa4fcd Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 2 Apr 2026 09:19:43 +0000
Subject: [PATCH 01/10] Initial plan
From 908aa09a0e902ce275b87a99c0d7ae54a28f0a63 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Thu, 2 Apr 2026 09:44:08 +0000
Subject: [PATCH 02/10] Guard Mono AOT targets for MonoVM-only runtime, add
XA1042 warning for Mono-specific properties used with non-MonoVM runtimes
Agent-Logs-Url: https://github.com/dotnet/android/sessions/a5ac81b3-0cd5-4a8a-9394-531fa1466274
Co-authored-by: simonrozsival <374616+simonrozsival@users.noreply.github.com>
---
Documentation/docs-mobile/messages/xa1042.md | 45 +++++++++++++++++++
.../targets/Microsoft.Android.Sdk.Aot.targets | 4 +-
...soft.Android.Sdk.DefaultProperties.targets | 5 +++
.../Properties/Resources.Designer.cs | 9 ++++
.../Properties/Resources.resx | 7 +++
.../Xamarin.Android.Build.Tests/AotTests.cs | 32 +++++++++++++
.../Xamarin.Android.Common.targets | 10 +++++
7 files changed, 110 insertions(+), 2 deletions(-)
create mode 100644 Documentation/docs-mobile/messages/xa1042.md
diff --git a/Documentation/docs-mobile/messages/xa1042.md b/Documentation/docs-mobile/messages/xa1042.md
new file mode 100644
index 00000000000..f57c6e6cbd2
--- /dev/null
+++ b/Documentation/docs-mobile/messages/xa1042.md
@@ -0,0 +1,45 @@
+---
+title: .NET for Android warning XA1042
+description: XA1042 warning code
+ms.date: 04/02/2026
+f1_keywords:
+ - "XA1042"
+---
+
+# .NET for Android warning XA1042
+
+## Example messages
+
+```
+warning XA1042: The MSBuild property 'RunAOTCompilation' is not compatible with the CoreCLR runtime and will be ignored. Either remove the property or guard it with a condition: Condition="'$(UseMonoRuntime)' == 'true'"
+```
+
+## Issue
+
+This warning indicates that a Mono-specific MSBuild property is set in
+the project file, but the project is configured to use a non-Mono
+runtime (such as CoreCLR or NativeAOT). The property will have no
+effect with the current runtime and will be ignored.
+
+Properties that trigger this warning include:
+- `RunAOTCompilation` — Mono AOT compilation; CoreCLR uses `PublishReadyToRun` instead.
+- `EnableLLVM` — Enables LLVM for the Mono AOT compiler.
+
+## Solution
+
+Remove the Mono-specific property from your project file or
+`Directory.Build.props`, or guard it with a runtime condition:
+
+```xml
+
+ true
+
+```
+
+For CoreCLR, use `PublishReadyToRun` instead of `RunAOTCompilation`:
+
+```xml
+
+ true
+
+```
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 d80be84d01c..3537c75fb4b 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
@@ -21,7 +21,7 @@ They run in a context of an inner build with a single $(RuntimeIdentifier).
when $(MonoAOTCompilerTasksAssemblyPath) is blank:
https://github.com/dotnet/runtime/blob/69711860262e44458bbe276393ea3eb9f7a2192a/src/mono/nuget/Microsoft.NET.Workload.Mono.Toolchain.Manifest/WorkloadManifest.targets.in#L20-L25
-->
-
+
@@ -39,7 +39,7 @@ They run in a context of an inner build with a single $(RuntimeIdentifier).
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets
index e9c75e1667d..fd8c19234f1 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets
@@ -119,6 +119,11 @@
true
true
false
+
+ <_AndroidXA1042_RunAOTCompilation Condition=" '$(RunAOTCompilation)' == 'true' and '$(_AndroidRuntime)' != 'MonoVM' ">true
+ <_AndroidXA1042_EnableLLVM Condition=" '$(EnableLLVM)' == 'true' and '$(_AndroidRuntime)' != 'MonoVM' ">true
+ false
+ false
<_AndroidXA1029 Condition=" '$(AotAssemblies)' != '' ">true
<_AndroidXA1030 Condition=" '$(RunAOTCompilation)' == 'true' and '$(PublishTrimmed)' == 'false' ">true
$(RunAOTCompilation)
diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
index bc2d9a7d4d4..4b7c0de91fc 100644
--- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
+++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
@@ -938,6 +938,15 @@ public static string XA1041 {
}
}
+ ///
+ /// Looks up a localized string similar to The MSBuild property '{0}' is not compatible with the {1} runtime and will be ignored. Either remove the property or guard it with a condition: Condition="'$(UseMonoRuntime)' == 'true'".
+ ///
+ public static string XA1042 {
+ get {
+ return ResourceManager.GetString("XA1042", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to 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 .NET for Android once .NET 6 is released..
///
diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
index d1ee02dc051..6d6eb3546f6 100644
--- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
+++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
@@ -1007,6 +1007,13 @@ To use a custom JDK path for a command line build, set the 'JavaSdkDirectory' MS
The following are literal names and should not be translated: .NET.
{0} - The MSBuild property that has the incorrect value.
{1} - The current value of the property
+
+
+
+ The MSBuild property '{0}' is not compatible with the {1} runtime and will be ignored. Either remove the property or guard it with a condition: Condition="'$(UseMonoRuntime)' == 'true'"
+ The following are literal names and should not be translated: MSBuild, UseMonoRuntime.
+{0} - The MSBuild property name (e.g. RunAOTCompilation, EnableLLVM).
+{1} - The name of the .NET runtime (e.g. CoreCLR, NativeAOT).
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 6a6b91aa900..09d36e7b02a 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
@@ -492,5 +492,37 @@ public void CheckWhetherLibcAndLibmAreReferencedInAOTLibraries ()
}
}
+ [Test]
+ public void RunAOTCompilationWithCoreClrWarnsAndSkipsMonoAot ()
+ {
+ var proj = new XamarinAndroidApplicationProject {
+ IsRelease = true,
+ };
+ proj.SetRuntime (AndroidRuntime.CoreCLR);
+ proj.SetProperty ("RunAOTCompilation", "true");
+
+ using var b = CreateApkBuilder ();
+ Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
+ StringAssertEx.Contains ("warning XA1042", b.LastBuildOutput, "Build output should contain warning XA1042");
+ StringAssertEx.Contains ("RunAOTCompilation", b.LastBuildOutput, "Build output should mention RunAOTCompilation");
+ StringAssertEx.Contains ("CoreCLR", b.LastBuildOutput, "Build output should mention CoreCLR");
+ }
+
+ [Test]
+ public void EnableLLVMWithCoreClrWarnsAndIsIgnored ()
+ {
+ var proj = new XamarinAndroidApplicationProject {
+ IsRelease = true,
+ };
+ proj.SetRuntime (AndroidRuntime.CoreCLR);
+ proj.SetProperty ("EnableLLVM", "true");
+
+ using var b = CreateApkBuilder ();
+ Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
+ StringAssertEx.Contains ("warning XA1042", b.LastBuildOutput, "Build output should contain warning XA1042");
+ StringAssertEx.Contains ("EnableLLVM", b.LastBuildOutput, "Build output should mention EnableLLVM");
+ StringAssertEx.Contains ("CoreCLR", b.LastBuildOutput, "Build output should mention CoreCLR");
+ }
+
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index c2527d1954e..e6a46aab923 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -550,6 +550,16 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
ResourceName="XA1030"
Condition=" $(_AndroidXA1030) == 'true' "
/>
+
+
Date: Fri, 3 Apr 2026 21:30:02 +0000
Subject: [PATCH 03/10] Fix NDK requirement for NativeAOT: add PublishAot
condition and dedicated test
Agent-Logs-Url: https://github.com/dotnet/android/sessions/1e564b95-24aa-400d-b01f-f153bea868fd
Co-authored-by: jonathanpeppers <840039+jonathanpeppers@users.noreply.github.com>
---
.../AndroidDependenciesTests.cs | 20 +++++++++++++++++++
.../Xamarin.Android.Common.targets | 1 +
2 files changed, 21 insertions(+)
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
index d150196d51c..9bd7e91eed3 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
@@ -188,6 +188,26 @@ public void GetDependencyNdkRequiredConditions (string property, bool ndkRequire
}
}
+ [Test]
+ public void NativeAotRequiresNdk ()
+ {
+ var proj = new XamarinAndroidApplicationProject {
+ IsRelease = true,
+ };
+ proj.SetRuntime (AndroidRuntime.NativeAOT);
+ using (var builder = CreateApkBuilder ()) {
+ builder.Verbosity = LoggerVerbosity.Detailed;
+ builder.Target = "GetAndroidDependencies";
+ Assert.IsTrue (builder.Build (proj), "Build should have succeeded.");
+ IEnumerable taskOutput = builder.LastBuildOutput
+ .Select (x => x.Trim ())
+ .SkipWhile (x => !x.StartsWith ("Task \"CalculateProjectDependencies\"", StringComparison.Ordinal))
+ .SkipWhile (x => !x.StartsWith ("Output Item(s):", StringComparison.Ordinal))
+ .TakeWhile (x => !x.StartsWith ("Done executing task \"CalculateProjectDependencies\"", StringComparison.Ordinal));
+ StringAssertEx.Contains ("ndk-bundle", taskOutput, "ndk-bundle should be a dependency for NativeAOT.");
+ }
+ }
+
[Test]
public void GetDependencyWhenBuildToolsAreMissingTest ([Values] AndroidRuntime runtime)
{
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index e6a46aab923..754086557d0 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -2856,6 +2856,7 @@ because xbuild doesn't support framework reference assemblies.
<_ProjectAndroidManifest>$(ProjectDir)$(AndroidManifest)
<_NdkRequired Condition="'$(EnableLLVM)' == 'True'">true
+ <_NdkRequired Condition="'$(PublishAot)' == 'true'">true
<_NdkRequired Condition="'$(_NdkRequired)' == ''">false
From 2c4b57d5858610912fc91b8a439a7685c460eb70 Mon Sep 17 00:00:00 2001
From: Jonathan Peppers
Date: Mon, 13 Apr 2026 11:11:04 -0500
Subject: [PATCH 04/10] Change NDK dependency identity from ndk-bundle to ndk
The CalculateProjectDependencies task was emitting 'ndk-bundle' as the
AndroidDependency item identity, but modern Android SDK uses side-by-side
NDK installed under 'ndk/{version}'. The GoogleV2 manifest doesn't have
a component with path 'ndk-bundle', causing InstallAndroidDependencies
to fail with 'could not be resolved' warnings.
Change the identity to 'ndk' so it matches the GoogleV2 manifest component
and resolves correctly.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../Tasks/CalculateProjectDependencies.cs | 2 +-
.../AndroidDependenciesTests.cs | 4 ++--
.../Tasks/GetDependenciesTests.cs | 16 ++++++++--------
3 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
index 764129c5574..1473f753a95 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
@@ -82,7 +82,7 @@ public override bool RunTask ()
dependencies.Add (CreateAndroidDependency ($"cmdline-tools/{CommandLineToolsVersion}", CommandLineToolsVersion));
}
if (!NdkVersion.IsNullOrEmpty () && NdkRequired) {
- dependencies.Add (CreateAndroidDependency ("ndk-bundle", NdkVersion));
+ dependencies.Add (CreateAndroidDependency ("ndk", NdkVersion));
}
if (!JdkVersion.IsNullOrEmpty () && GetJavaDependencies) {
javaDependencies.Add (CreateAndroidDependency ("jdk", JdkVersion));
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
index 9bd7e91eed3..f4ae14e5e90 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
@@ -182,9 +182,9 @@ public void GetDependencyNdkRequiredConditions (string property, bool ndkRequire
.SkipWhile (x => !x.StartsWith ("Output Item(s):", StringComparison.Ordinal))
.TakeWhile (x => !x.StartsWith ("Done executing task \"CalculateProjectDependencies\"", StringComparison.Ordinal));
if (ndkRequired)
- StringAssertEx.Contains ("ndk-bundle", taskOutput, "ndk-bundle should be a dependency.");
+ StringAssertEx.Contains ("ndk", taskOutput, "ndk should be a dependency.");
else
- StringAssertEx.DoesNotContain ("ndk-bundle", taskOutput, "ndk-bundle should not be a dependency.");
+ StringAssertEx.DoesNotContain ("ndk", taskOutput, "ndk should not be a dependency.");
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
index e466de20a98..4b55dea4fb7 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
@@ -43,11 +43,11 @@ public void CheckNdkBundle ([Values(true, false)] bool ndkRequred)
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
if (ndkRequred) {
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle" && x.GetMetadata ("Version") == "12.1"),
- "Dependencies should contain a ndk-bundle version 12.1");
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
+ "Dependencies should contain a ndk version 12.1");
} else {
- Assert.IsNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle"),
- "Dependencies should not contain a ndk-bundle item");
+ Assert.IsNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk"),
+ "Dependencies should not contain a ndk item");
}
Directory.Delete (Path.Combine (Root, path), recursive: true);
}
@@ -80,8 +80,8 @@ public void ManifestFileDoesNotExist ()
"Dependencies should contains a platform version android-26");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle" && x.GetMetadata ("Version") == "12.1"),
- "Dependencies should contains a ndk-bundle version 12.1");
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
+ "Dependencies should contains a ndk version 12.1");
Directory.Delete (Path.Combine (Root, path), recursive: true);
}
@@ -121,8 +121,8 @@ public void ManifestFileExists ()
"Dependencies should contains a platform version android-26");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle" && x.GetMetadata ("Version") == "12.1"),
- "Dependencies should contains a ndk-bundle version 12.1");
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
+ "Dependencies should contains a ndk version 12.1");
Directory.Delete (path, recursive: true);
}
From 7145c4128f2d78e9ebc49f7187d663643e9bdca7 Mon Sep 17 00:00:00 2001
From: Jonathan Peppers
Date: Mon, 13 Apr 2026 14:53:07 -0500
Subject: [PATCH 05/10] Fix NDK dependency identity to use ndk/{version} format
Use ndk/{version} (e.g. ndk/27.2.1247901) as the AndroidDependency
identity, matching the pattern used by build-tools/{version} and
cmdline-tools/{version}. This allows the GoogleV2 manifest to resolve
the NDK component correctly.
Also fix tests:
- Skip GetDependencyNdkRequiredConditions for NativeAOT when
ndkRequired=false, since NativeAOT always requires NDK via
PublishAot=true
- Update NativeAotRequiresNdk assertion from ndk-bundle to ndk/
- Use ndk/ prefix matching in StringAssertEx to avoid false positives
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../Tasks/CalculateProjectDependencies.cs | 2 +-
.../AndroidDependenciesTests.cs | 11 ++++++++---
.../Tasks/GetDependenciesTests.cs | 8 ++++----
3 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
index 1473f753a95..c9692cbf9ec 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
@@ -82,7 +82,7 @@ public override bool RunTask ()
dependencies.Add (CreateAndroidDependency ($"cmdline-tools/{CommandLineToolsVersion}", CommandLineToolsVersion));
}
if (!NdkVersion.IsNullOrEmpty () && NdkRequired) {
- dependencies.Add (CreateAndroidDependency ("ndk", NdkVersion));
+ dependencies.Add (CreateAndroidDependency ($"ndk/{NdkVersion}", NdkVersion));
}
if (!JdkVersion.IsNullOrEmpty () && GetJavaDependencies) {
javaDependencies.Add (CreateAndroidDependency ("jdk", JdkVersion));
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
index f4ae14e5e90..a6d061f344f 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
@@ -166,6 +166,11 @@ public void GetDependencyNdkRequiredConditions (string property, bool ndkRequire
Assert.Ignore ("NativeAOT doesn't support profiled AOT");
}
+ // NativeAOT always requires the NDK (PublishAot=true), so ndkRequired=false cases don't apply
+ if (runtime == AndroidRuntime.NativeAOT && !ndkRequired) {
+ Assert.Ignore ("NativeAOT always requires NDK via PublishAot=true");
+ }
+
var proj = new XamarinAndroidApplicationProject {
IsRelease = isRelease,
};
@@ -182,9 +187,9 @@ public void GetDependencyNdkRequiredConditions (string property, bool ndkRequire
.SkipWhile (x => !x.StartsWith ("Output Item(s):", StringComparison.Ordinal))
.TakeWhile (x => !x.StartsWith ("Done executing task \"CalculateProjectDependencies\"", StringComparison.Ordinal));
if (ndkRequired)
- StringAssertEx.Contains ("ndk", taskOutput, "ndk should be a dependency.");
+ StringAssertEx.Contains ("ndk/", taskOutput, "ndk should be a dependency.");
else
- StringAssertEx.DoesNotContain ("ndk", taskOutput, "ndk should not be a dependency.");
+ StringAssertEx.DoesNotContain ("ndk/", taskOutput, "ndk should not be a dependency.");
}
}
@@ -204,7 +209,7 @@ public void NativeAotRequiresNdk ()
.SkipWhile (x => !x.StartsWith ("Task \"CalculateProjectDependencies\"", StringComparison.Ordinal))
.SkipWhile (x => !x.StartsWith ("Output Item(s):", StringComparison.Ordinal))
.TakeWhile (x => !x.StartsWith ("Done executing task \"CalculateProjectDependencies\"", StringComparison.Ordinal));
- StringAssertEx.Contains ("ndk-bundle", taskOutput, "ndk-bundle should be a dependency for NativeAOT.");
+ StringAssertEx.Contains ("ndk/", taskOutput, "ndk should be a dependency for NativeAOT.");
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
index 4b55dea4fb7..f62ce47e493 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
@@ -43,10 +43,10 @@ public void CheckNdkBundle ([Values(true, false)] bool ndkRequred)
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
if (ndkRequred) {
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk/12.1" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contain a ndk version 12.1");
} else {
- Assert.IsNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk"),
+ Assert.IsNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec.StartsWith ("ndk/")),
"Dependencies should not contain a ndk item");
}
Directory.Delete (Path.Combine (Root, path), recursive: true);
@@ -80,7 +80,7 @@ public void ManifestFileDoesNotExist ()
"Dependencies should contains a platform version android-26");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk/12.1" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contains a ndk version 12.1");
Directory.Delete (Path.Combine (Root, path), recursive: true);
}
@@ -121,7 +121,7 @@ public void ManifestFileExists ()
"Dependencies should contains a platform version android-26");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk/12.1" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contains a ndk version 12.1");
Directory.Delete (path, recursive: true);
From 2b468ec4c95c24d927307afd6197f9da3c122f74 Mon Sep 17 00:00:00 2001
From: Jonathan Peppers
Date: Tue, 14 Apr 2026 11:17:21 -0500
Subject: [PATCH 06/10] Revert NDK identity to 'ndk' instead of 'ndk/{version}'
The downstream InstallAndroidDependencies task (from android-platform-support)
joins the identity and version with a semicolon separator to form the SDK
manager path (e.g. ndk;27.2.12479018). Using ndk/{version} as the identity
caused a malformed path like 'ndk;27.2.12479018/27.2.12479018' that couldn't
be resolved.
The correct identity is just 'ndk' with the version in metadata, which
produces the expected 'ndk;27.2.12479018' component path.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../Tasks/CalculateProjectDependencies.cs | 2 +-
.../AndroidDependenciesTests.cs | 6 +++---
.../Tasks/GetDependenciesTests.cs | 8 ++++----
3 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
index c9692cbf9ec..1473f753a95 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
@@ -82,7 +82,7 @@ public override bool RunTask ()
dependencies.Add (CreateAndroidDependency ($"cmdline-tools/{CommandLineToolsVersion}", CommandLineToolsVersion));
}
if (!NdkVersion.IsNullOrEmpty () && NdkRequired) {
- dependencies.Add (CreateAndroidDependency ($"ndk/{NdkVersion}", NdkVersion));
+ dependencies.Add (CreateAndroidDependency ("ndk", NdkVersion));
}
if (!JdkVersion.IsNullOrEmpty () && GetJavaDependencies) {
javaDependencies.Add (CreateAndroidDependency ("jdk", JdkVersion));
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
index a6d061f344f..b8d09a390b7 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
@@ -187,9 +187,9 @@ public void GetDependencyNdkRequiredConditions (string property, bool ndkRequire
.SkipWhile (x => !x.StartsWith ("Output Item(s):", StringComparison.Ordinal))
.TakeWhile (x => !x.StartsWith ("Done executing task \"CalculateProjectDependencies\"", StringComparison.Ordinal));
if (ndkRequired)
- StringAssertEx.Contains ("ndk/", taskOutput, "ndk should be a dependency.");
+ StringAssertEx.Contains ("ndk", taskOutput, "ndk should be a dependency.");
else
- StringAssertEx.DoesNotContain ("ndk/", taskOutput, "ndk should not be a dependency.");
+ StringAssertEx.DoesNotContain ("ndk", taskOutput, "ndk should not be a dependency.");
}
}
@@ -209,7 +209,7 @@ public void NativeAotRequiresNdk ()
.SkipWhile (x => !x.StartsWith ("Task \"CalculateProjectDependencies\"", StringComparison.Ordinal))
.SkipWhile (x => !x.StartsWith ("Output Item(s):", StringComparison.Ordinal))
.TakeWhile (x => !x.StartsWith ("Done executing task \"CalculateProjectDependencies\"", StringComparison.Ordinal));
- StringAssertEx.Contains ("ndk/", taskOutput, "ndk should be a dependency for NativeAOT.");
+ StringAssertEx.Contains ("ndk", taskOutput, "ndk should be a dependency for NativeAOT.");
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
index f62ce47e493..4b55dea4fb7 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
@@ -43,10 +43,10 @@ public void CheckNdkBundle ([Values(true, false)] bool ndkRequred)
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
if (ndkRequred) {
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk/12.1" && x.GetMetadata ("Version") == "12.1"),
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contain a ndk version 12.1");
} else {
- Assert.IsNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec.StartsWith ("ndk/")),
+ Assert.IsNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk"),
"Dependencies should not contain a ndk item");
}
Directory.Delete (Path.Combine (Root, path), recursive: true);
@@ -80,7 +80,7 @@ public void ManifestFileDoesNotExist ()
"Dependencies should contains a platform version android-26");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk/12.1" && x.GetMetadata ("Version") == "12.1"),
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contains a ndk version 12.1");
Directory.Delete (Path.Combine (Root, path), recursive: true);
}
@@ -121,7 +121,7 @@ public void ManifestFileExists ()
"Dependencies should contains a platform version android-26");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk/12.1" && x.GetMetadata ("Version") == "12.1"),
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contains a ndk version 12.1");
Directory.Delete (path, recursive: true);
From fc75a9cf71c601bab793423aa2e565f600debf37 Mon Sep 17 00:00:00 2001
From: Jonathan Peppers
Date: Wed, 15 Apr 2026 11:42:58 -0500
Subject: [PATCH 07/10] Emit both ndk-bundle and ndk as AndroidDependency items
The bundled Xamarin manifest uses 'ndk-bundle' as the component path,
while the GoogleV2 manifest (once regenerated) will use 'ndk'. Emit
both identities so the dependency resolves regardless of which manifest
the downstream InstallAndroidDependencies task is configured to use.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../Tasks/CalculateProjectDependencies.cs | 3 +++
.../Tasks/GetDependenciesTests.cs | 14 +++++++++++---
2 files changed, 14 insertions(+), 3 deletions(-)
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
index 1473f753a95..b2d68196f63 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
@@ -82,6 +82,9 @@ public override bool RunTask ()
dependencies.Add (CreateAndroidDependency ($"cmdline-tools/{CommandLineToolsVersion}", CommandLineToolsVersion));
}
if (!NdkVersion.IsNullOrEmpty () && NdkRequired) {
+ // Emit both identities so the dependency resolves against either
+ // the legacy "ndk-bundle" manifest entries or the modern "ndk" entries.
+ dependencies.Add (CreateAndroidDependency ("ndk-bundle", NdkVersion));
dependencies.Add (CreateAndroidDependency ("ndk", NdkVersion));
}
if (!JdkVersion.IsNullOrEmpty () && GetJavaDependencies) {
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
index 4b55dea4fb7..73e12f78634 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
@@ -35,7 +35,7 @@ public void CheckNdkBundle ([Values(true, false)] bool ndkRequred)
task.ManifestFile = new TaskItem (Path.Combine (path, "AndroidManifest.xml"));
Assert.IsTrue (task.Execute ());
Assert.IsNotNull (task.Dependencies);
- Assert.AreEqual (ndkRequred ? 4 : 3, task.Dependencies.Length);
+ Assert.AreEqual (ndkRequred ? 5 : 3, task.Dependencies.Length);
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "build-tools/26.0.1" && x.GetMetadata ("Version") == "26.0.1"),
"Dependencies should contains a build-tools version 26.0.1");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platforms/android-26" && x.GetMetadata ("Version") == ""),
@@ -43,9 +43,13 @@ public void CheckNdkBundle ([Values(true, false)] bool ndkRequred)
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
if (ndkRequred) {
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle" && x.GetMetadata ("Version") == "12.1"),
+ "Dependencies should contain a ndk-bundle version 12.1");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contain a ndk version 12.1");
} else {
+ Assert.IsNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle"),
+ "Dependencies should not contain a ndk-bundle item");
Assert.IsNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk"),
"Dependencies should not contain a ndk item");
}
@@ -73,13 +77,15 @@ public void ManifestFileDoesNotExist ()
task.ManifestFile = new TaskItem (Path.Combine (path, "AndroidManifest.xml"));
Assert.IsTrue (task.Execute ());
Assert.IsNotNull (task.Dependencies);
- Assert.AreEqual (4, task.Dependencies.Length);
+ Assert.AreEqual (5, task.Dependencies.Length);
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "build-tools/26.0.1" && x.GetMetadata ("Version") == "26.0.1"),
"Dependencies should contains a build-tools version 26.0.1");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platforms/android-26" && x.GetMetadata ("Version") == ""),
"Dependencies should contains a platform version android-26");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle" && x.GetMetadata ("Version") == "12.1"),
+ "Dependencies should contains a ndk-bundle version 12.1");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contains a ndk version 12.1");
Directory.Delete (Path.Combine (Root, path), recursive: true);
@@ -114,13 +120,15 @@ public void ManifestFileExists ()
task.ManifestFile = new TaskItem (manifestFile);
Assert.IsTrue(task.Execute ());
Assert.IsNotNull (task.Dependencies);
- Assert.AreEqual (4, task.Dependencies.Length);
+ Assert.AreEqual (5, task.Dependencies.Length);
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "build-tools/26.0.1" && x.GetMetadata ("Version") == "26.0.1"),
"Dependencies should contains a build-tools version 26.0.1");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platforms/android-26" && x.GetMetadata ("Version") == ""),
"Dependencies should contains a platform version android-26");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platform-tools" && x.GetMetadata ("Version") == "26.0.3"),
"Dependencies should contains a platform-tools version 26.0.3");
+ Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle" && x.GetMetadata ("Version") == "12.1"),
+ "Dependencies should contains a ndk-bundle version 12.1");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contains a ndk version 12.1");
From 80af176efd6192406031d15ff8908007b721032c Mon Sep 17 00:00:00 2001
From: Jonathan Peppers
Date: Wed, 15 Apr 2026 15:33:59 -0500
Subject: [PATCH 08/10] Revert NDK identity back to ndk-bundle
The bundled manifests in android-platform-support still use ndk-bundle
as the component path. Revert to the original identity and only add
the NativeAOT-specific test changes:
- Skip GetDependencyNdkRequiredConditions for NativeAOT when
ndkRequired=false (PublishAot=true always requires NDK)
- Add NativeAotRequiresNdk test
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../Tasks/CalculateProjectDependencies.cs | 3 ---
.../AndroidDependenciesTests.cs | 6 +++---
.../Tasks/GetDependenciesTests.cs | 14 +++-----------
3 files changed, 6 insertions(+), 17 deletions(-)
diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs b/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
index b2d68196f63..764129c5574 100644
--- a/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tasks/CalculateProjectDependencies.cs
@@ -82,10 +82,7 @@ public override bool RunTask ()
dependencies.Add (CreateAndroidDependency ($"cmdline-tools/{CommandLineToolsVersion}", CommandLineToolsVersion));
}
if (!NdkVersion.IsNullOrEmpty () && NdkRequired) {
- // Emit both identities so the dependency resolves against either
- // the legacy "ndk-bundle" manifest entries or the modern "ndk" entries.
dependencies.Add (CreateAndroidDependency ("ndk-bundle", NdkVersion));
- dependencies.Add (CreateAndroidDependency ("ndk", NdkVersion));
}
if (!JdkVersion.IsNullOrEmpty () && GetJavaDependencies) {
javaDependencies.Add (CreateAndroidDependency ("jdk", JdkVersion));
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
index b8d09a390b7..e55609045ee 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
@@ -187,9 +187,9 @@ public void GetDependencyNdkRequiredConditions (string property, bool ndkRequire
.SkipWhile (x => !x.StartsWith ("Output Item(s):", StringComparison.Ordinal))
.TakeWhile (x => !x.StartsWith ("Done executing task \"CalculateProjectDependencies\"", StringComparison.Ordinal));
if (ndkRequired)
- StringAssertEx.Contains ("ndk", taskOutput, "ndk should be a dependency.");
+ StringAssertEx.Contains ("ndk-bundle", taskOutput, "ndk-bundle should be a dependency.");
else
- StringAssertEx.DoesNotContain ("ndk", taskOutput, "ndk should not be a dependency.");
+ StringAssertEx.DoesNotContain ("ndk-bundle", taskOutput, "ndk-bundle should not be a dependency.");
}
}
@@ -209,7 +209,7 @@ public void NativeAotRequiresNdk ()
.SkipWhile (x => !x.StartsWith ("Task \"CalculateProjectDependencies\"", StringComparison.Ordinal))
.SkipWhile (x => !x.StartsWith ("Output Item(s):", StringComparison.Ordinal))
.TakeWhile (x => !x.StartsWith ("Done executing task \"CalculateProjectDependencies\"", StringComparison.Ordinal));
- StringAssertEx.Contains ("ndk", taskOutput, "ndk should be a dependency for NativeAOT.");
+ StringAssertEx.Contains ("ndk-bundle", taskOutput, "ndk-bundle should be a dependency for NativeAOT.");
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
index 73e12f78634..e466de20a98 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Tasks/GetDependenciesTests.cs
@@ -35,7 +35,7 @@ public void CheckNdkBundle ([Values(true, false)] bool ndkRequred)
task.ManifestFile = new TaskItem (Path.Combine (path, "AndroidManifest.xml"));
Assert.IsTrue (task.Execute ());
Assert.IsNotNull (task.Dependencies);
- Assert.AreEqual (ndkRequred ? 5 : 3, task.Dependencies.Length);
+ Assert.AreEqual (ndkRequred ? 4 : 3, task.Dependencies.Length);
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "build-tools/26.0.1" && x.GetMetadata ("Version") == "26.0.1"),
"Dependencies should contains a build-tools version 26.0.1");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platforms/android-26" && x.GetMetadata ("Version") == ""),
@@ -45,13 +45,9 @@ public void CheckNdkBundle ([Values(true, false)] bool ndkRequred)
if (ndkRequred) {
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contain a ndk-bundle version 12.1");
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
- "Dependencies should contain a ndk version 12.1");
} else {
Assert.IsNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle"),
"Dependencies should not contain a ndk-bundle item");
- Assert.IsNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk"),
- "Dependencies should not contain a ndk item");
}
Directory.Delete (Path.Combine (Root, path), recursive: true);
}
@@ -77,7 +73,7 @@ public void ManifestFileDoesNotExist ()
task.ManifestFile = new TaskItem (Path.Combine (path, "AndroidManifest.xml"));
Assert.IsTrue (task.Execute ());
Assert.IsNotNull (task.Dependencies);
- Assert.AreEqual (5, task.Dependencies.Length);
+ Assert.AreEqual (4, task.Dependencies.Length);
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "build-tools/26.0.1" && x.GetMetadata ("Version") == "26.0.1"),
"Dependencies should contains a build-tools version 26.0.1");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platforms/android-26" && x.GetMetadata ("Version") == ""),
@@ -86,8 +82,6 @@ public void ManifestFileDoesNotExist ()
"Dependencies should contains a platform-tools version 26.0.3");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contains a ndk-bundle version 12.1");
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
- "Dependencies should contains a ndk version 12.1");
Directory.Delete (Path.Combine (Root, path), recursive: true);
}
@@ -120,7 +114,7 @@ public void ManifestFileExists ()
task.ManifestFile = new TaskItem (manifestFile);
Assert.IsTrue(task.Execute ());
Assert.IsNotNull (task.Dependencies);
- Assert.AreEqual (5, task.Dependencies.Length);
+ Assert.AreEqual (4, task.Dependencies.Length);
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "build-tools/26.0.1" && x.GetMetadata ("Version") == "26.0.1"),
"Dependencies should contains a build-tools version 26.0.1");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "platforms/android-26" && x.GetMetadata ("Version") == ""),
@@ -129,8 +123,6 @@ public void ManifestFileExists ()
"Dependencies should contains a platform-tools version 26.0.3");
Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk-bundle" && x.GetMetadata ("Version") == "12.1"),
"Dependencies should contains a ndk-bundle version 12.1");
- Assert.IsNotNull (task.Dependencies.FirstOrDefault (x => x.ItemSpec == "ndk" && x.GetMetadata ("Version") == "12.1"),
- "Dependencies should contains a ndk version 12.1");
Directory.Delete (path, recursive: true);
}
From 4f264644f93985883af57875ab72a265051cc353 Mon Sep 17 00:00:00 2001
From: Jonathan Peppers
Date: Wed, 15 Apr 2026 15:40:36 -0500
Subject: [PATCH 09/10] Skip InstallAndroidDependenciesTest for
GoogleV2+NativeAOT
The GoogleV2 manifest from Google does not have an ndk-bundle component,
so the NDK dependency cannot be resolved for runtimes that require it.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
index e55609045ee..c98c394daed 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidDependenciesTests.cs
@@ -26,6 +26,12 @@ public void InstallAndroidDependenciesTest ([Values ("GoogleV2", "Xamarin")] str
return;
}
+ // The GoogleV2 manifest from Google doesn't have an ndk-bundle component,
+ // so the NDK dependency can't be resolved for runtimes that require it.
+ if (manifestType == "GoogleV2" && runtime == AndroidRuntime.NativeAOT) {
+ Assert.Ignore ("GoogleV2 manifest does not have an ndk-bundle component for NativeAOT");
+ }
+
// Set to true when we are marking a new Android API level as stable, but it has not
// been added to the Xamarin manifest yet.
var xamarin_manifest_needs_updating = false;
From 3e108ac081e041ea51386d04a7c6e071ce924ae6 Mon Sep 17 00:00:00 2001
From: Jonathan Peppers
Date: Fri, 17 Apr 2026 12:24:54 -0500
Subject: [PATCH 10/10] Renumber XA1042 to XA1044 to avoid conflict with main
XA1042 was already taken on main for a different warning (missing
android:name in ). Renumber our Mono-specific
property warning to XA1044.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---
.../docs-mobile/messages/{xa1042.md => xa1044.md} | 10 +++++-----
.../Microsoft.Android.Sdk.DefaultProperties.targets | 8 ++++----
.../Properties/Resources.Designer.cs | 4 ++--
.../Properties/Resources.resx | 2 +-
.../Tests/Xamarin.Android.Build.Tests/AotTests.cs | 4 ++--
.../Xamarin.Android.Common.targets | 12 ++++++------
6 files changed, 20 insertions(+), 20 deletions(-)
rename Documentation/docs-mobile/messages/{xa1042.md => xa1044.md} (86%)
diff --git a/Documentation/docs-mobile/messages/xa1042.md b/Documentation/docs-mobile/messages/xa1044.md
similarity index 86%
rename from Documentation/docs-mobile/messages/xa1042.md
rename to Documentation/docs-mobile/messages/xa1044.md
index f57c6e6cbd2..331dd99594c 100644
--- a/Documentation/docs-mobile/messages/xa1042.md
+++ b/Documentation/docs-mobile/messages/xa1044.md
@@ -1,17 +1,17 @@
---
-title: .NET for Android warning XA1042
-description: XA1042 warning code
+title: .NET for Android warning XA1044
+description: XA1044 warning code
ms.date: 04/02/2026
f1_keywords:
- - "XA1042"
+ - "XA1044"
---
-# .NET for Android warning XA1042
+# .NET for Android warning XA1044
## Example messages
```
-warning XA1042: The MSBuild property 'RunAOTCompilation' is not compatible with the CoreCLR runtime and will be ignored. Either remove the property or guard it with a condition: Condition="'$(UseMonoRuntime)' == 'true'"
+warning XA1044: The MSBuild property 'RunAOTCompilation' is not compatible with the CoreCLR runtime and will be ignored. Either remove the property or guard it with a condition: Condition="'$(UseMonoRuntime)' == 'true'"
```
## Issue
diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets
index fd8c19234f1..22816880d1b 100644
--- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets
+++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.DefaultProperties.targets
@@ -120,10 +120,10 @@
true
false
- <_AndroidXA1042_RunAOTCompilation Condition=" '$(RunAOTCompilation)' == 'true' and '$(_AndroidRuntime)' != 'MonoVM' ">true
- <_AndroidXA1042_EnableLLVM Condition=" '$(EnableLLVM)' == 'true' and '$(_AndroidRuntime)' != 'MonoVM' ">true
- false
- false
+ <_AndroidXA1044_RunAOTCompilation Condition=" '$(RunAOTCompilation)' == 'true' and '$(_AndroidRuntime)' != 'MonoVM' ">true
+ <_AndroidXA1044_EnableLLVM Condition=" '$(EnableLLVM)' == 'true' and '$(_AndroidRuntime)' != 'MonoVM' ">true
+ false
+ false
<_AndroidXA1029 Condition=" '$(AotAssemblies)' != '' ">true
<_AndroidXA1030 Condition=" '$(RunAOTCompilation)' == 'true' and '$(PublishTrimmed)' == 'false' ">true
$(RunAOTCompilation)
diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
index e947f7ad6e6..03e8aa2ea48 100644
--- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
+++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.Designer.cs
@@ -959,9 +959,9 @@ public static string XA1043 {
///
/// Looks up a localized string similar to The MSBuild property '{0}' is not compatible with the {1} runtime and will be ignored. Either remove the property or guard it with a condition: Condition="'$(UseMonoRuntime)' == 'true'".
///
- public static string XA1042 {
+ public static string XA1044 {
get {
- return ResourceManager.GetString("XA1042", resourceCulture);
+ return ResourceManager.GetString("XA1044", resourceCulture);
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
index 038b1677127..bdfc38d26bc 100644
--- a/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
+++ b/src/Xamarin.Android.Build.Tasks/Properties/Resources.resx
@@ -1009,7 +1009,7 @@ To use a custom JDK path for a command line build, set the 'JavaSdkDirectory' MS
{1} - The current value of the property
-
+
The MSBuild property '{0}' is not compatible with the {1} runtime and will be ignored. Either remove the property or guard it with a condition: Condition="'$(UseMonoRuntime)' == 'true'"
The following are literal names and should not be translated: MSBuild, UseMonoRuntime.
{0} - The MSBuild property name (e.g. RunAOTCompilation, EnableLLVM).
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 09d36e7b02a..90f43cf6614 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
@@ -503,7 +503,7 @@ public void RunAOTCompilationWithCoreClrWarnsAndSkipsMonoAot ()
using var b = CreateApkBuilder ();
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
- StringAssertEx.Contains ("warning XA1042", b.LastBuildOutput, "Build output should contain warning XA1042");
+ StringAssertEx.Contains ("warning XA1044", b.LastBuildOutput, "Build output should contain warning XA1044");
StringAssertEx.Contains ("RunAOTCompilation", b.LastBuildOutput, "Build output should mention RunAOTCompilation");
StringAssertEx.Contains ("CoreCLR", b.LastBuildOutput, "Build output should mention CoreCLR");
}
@@ -519,7 +519,7 @@ public void EnableLLVMWithCoreClrWarnsAndIsIgnored ()
using var b = CreateApkBuilder ();
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
- StringAssertEx.Contains ("warning XA1042", b.LastBuildOutput, "Build output should contain warning XA1042");
+ StringAssertEx.Contains ("warning XA1044", b.LastBuildOutput, "Build output should contain warning XA1044");
StringAssertEx.Contains ("EnableLLVM", b.LastBuildOutput, "Build output should mention EnableLLVM");
StringAssertEx.Contains ("CoreCLR", b.LastBuildOutput, "Build output should mention CoreCLR");
}
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index c2545eaf4f4..8a18a922bb1 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -549,15 +549,15 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
ResourceName="XA1030"
Condition=" $(_AndroidXA1030) == 'true' "
/>
-
-