diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs
index c13c7e400ca..de5cf20d655 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs
@@ -1944,5 +1944,41 @@ public void BuildPropsBreaksConvertResourcesCasesOnSecondBuild ([Values] Android
}
}
+ [Test]
+ public void AfterILLinkAdditionalStepsIsSkippedOnSecondBuild ([Values] AndroidRuntime runtime)
+ {
+ bool isRelease = runtime == AndroidRuntime.NativeAOT;
+ if (IgnoreUnsupportedConfiguration (runtime, release: isRelease)) {
+ return;
+ }
+
+ var proj = new XamarinAndroidApplicationProject {
+ IsRelease = isRelease,
+ };
+ proj.SetRuntime (runtime);
+ proj.SetProperty ("PublishTrimmed", "true");
+
+ using (var b = CreateApkBuilder ()) {
+ Assert.IsTrue (b.Build (proj), "first build should succeed");
+ b.Output.AssertTargetIsNotSkipped ("_RunAfterILLinkAdditionalSteps");
+ b.Output.AssertTargetIsNotSkipped ("_AfterILLinkAdditionalSteps");
+
+ // Verify afterlink/ output directory was created with per-ABI subdirectories containing assemblies
+ var afterlinkDir = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "afterlink");
+ Assert.IsTrue (Directory.Exists (afterlinkDir), "afterlink/ directory should exist after first build");
+ var abiDirs = Directory.GetDirectories (afterlinkDir);
+ Assert.IsTrue (abiDirs.Length > 0, "afterlink/ should contain ABI subdirectories");
+ foreach (var abiDir in abiDirs) {
+ var afterlinkFiles = Directory.GetFiles (abiDir, "*.dll");
+ Assert.IsTrue (afterlinkFiles.Length > 0, $"afterlink/{Path.GetFileName (abiDir)}/ should contain assemblies");
+ }
+
+ Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "second build should succeed");
+ b.Output.AssertTargetIsSkipped ("_RunAfterILLinkAdditionalSteps");
+ // The outer target must always run to update assembly itemgroups for downstream targets
+ b.Output.AssertTargetIsNotSkipped ("_AfterILLinkAdditionalSteps");
+ }
+ }
+
}
}
diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs
index dd599912590..96f9a9d52c7 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs
@@ -601,11 +601,8 @@ public void CheckSignApk ([Values] bool useApkSigner, [Values] bool perAbiApk, [
item.TextContent = () => proj.StringsXml.Replace ("${PROJECT_NAME}", "Foo");
item.Timestamp = null;
Assert.IsTrue (b.Build (proj), "Second build failed");
- if (runtime != AndroidRuntime.NativeAOT) {
- b.AssertHasNoWarnings ();
- } else {
- StringAssertEx.Contains ("2 Warning(s)", b.LastBuildOutput, "NativeAOT should produce two IL3053 warnings");
- }
+ // Resource-only change does not trigger IlcCompile, so no IL3053 warnings on second build
+ b.AssertHasNoWarnings ();
//Make sure the APKs are signed
foreach (var apk in Directory.GetFiles (bin, "*-Signed.apk")) {
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index 42b4601125c..f3dab9d5eb8 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -934,6 +934,7 @@ because xbuild doesn't support framework reference assemblies.
<_AndroidApkPerAbiFlagFile>$(IntermediateOutputPath)android\bin\apk_per_abi.flag
<_AndroidDebugKeyStoreFlag>$(IntermediateOutputPath)android_debug_keystore.flag
<_AdditionalPostLinkerStepsFlag>$(_AndroidStampDirectory)_AdditionalPostLinkerSteps.stamp
+ <_AfterILLinkOutputDir>$(IntermediateOutputPath)afterlink\
<_AcwMapFile>$(IntermediateOutputPath)acw-map.txt
<_CustomViewMapFile>$(IntermediateOutputPath)customview-map.txt
$(RootNamespace)
@@ -1465,16 +1466,17 @@ because xbuild doesn't support framework reference assemblies.
-
+
-
+
+
+
+
+
+
+
+
+ <_OrigResolvedAssemblies Include="@(ResolvedAssemblies)" />
+
+
+
+ <_OrigResolvedUserAssemblies Include="@(ResolvedUserAssemblies)" />
+
+
+
+ <_OrigResolvedFrameworkAssemblies Include="@(ResolvedFrameworkAssemblies)" />
+
+
+
+ <_OrigResolvedAssemblies Remove="@(_OrigResolvedAssemblies)" />
+ <_OrigResolvedUserAssemblies Remove="@(_OrigResolvedUserAssemblies)" />
+ <_OrigResolvedFrameworkAssemblies Remove="@(_OrigResolvedFrameworkAssemblies)" />
+