diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets index 9bb66ab4073..724c4a3de7b 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets @@ -174,7 +174,6 @@ properties that determine build ordering. _CheckForDeletedResourceFile; _ComputeAndroidResourcePaths; _UpdateAndroidResgen; - _CreateAar; _SetupMSBuildAllProjects; @@ -244,6 +243,7 @@ properties that determine build ordering. <_IncludeAarInNuGetPackageDependsOn> _BuildAndroidGradleProjects; _CategorizeAndroidLibraries; + _CreateAar; 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 dbb0bd836f3..c2b61a40093 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 @@ -522,6 +522,33 @@ public void LibraryProjectTargetsDoNotBreak () } } + [Test] + public void CreateAarRunsOnceWithGeneratePackageOnBuild () + { + // https://github.com/dotnet/android/issues/11514 + // `_CreateAar` was being invoked twice for a single library build when + // `GeneratePackageOnBuild=true`: once via `BuildDependsOn`, and again via + // NuGet pack's per-TFM dispatch which entered the project at + // `_GetFrameworkAssemblyReferences`. That target transitively pulled in + // `UpdateAndroidResources` -> `_UpdateAndroidResources` -> `_CreateAar` + // via `_UpdateAndroidResourcesDependsOn`. The second invocation can race + // the first writer when parallel builds (-m) consumers concurrently read + // the .aar via `Files.HashFile`, producing `XARLP7024`. + var proj = new XamarinAndroidLibraryProject (); + proj.SetProperty ("GeneratePackageOnBuild", "true"); + using (var b = CreateDllBuilder ()) { + b.Verbosity = LoggerVerbosity.Detailed; + Assert.IsTrue (b.Build (proj), "Build should have succeeded."); + // MSBuild emits "Building target X completely" only when the target + // actually runs (not when it is entered then skipped due to empty + // Inputs/Outputs). Counting that message gives us the number of real + // `_CreateAar` executions, which is what races on disk in #11514. + int count = b.LastBuildOutput.Count (l => l.Contains ("Building target \"_CreateAar\"")); + Assert.AreEqual (1, count, + $"`_CreateAar` should only execute once per build of a library project; was {count}."); + } + } + [Test] public void ManifestMergerIncremental () {