diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs
index 63a575f42a2..acb3f9c1713 100644
--- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs
+++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs
@@ -2300,6 +2300,79 @@ public void CheckLintResourceFileReferencesAreFixed ([Values (AndroidRuntime.Cor
}
}
+ [Test]
+ public void BuildDoesNotModifyNuGetPackageCache ()
+ {
+ var proj = new XamarinAndroidApplicationProject {
+ IsRelease = true,
+ GlobalPackagesFolder = Path.Combine (Root, TestName, "packages"),
+ Imports = {
+ new Import (() => "EnableMarshalMethodsForPostLink.targets") {
+ TextContent = () =>
+"""
+
+
+
+
+ <_AndroidUseMarshalMethods>true
+
+
+
+"""
+ },
+ },
+ PackageReferences = {
+ new Package { Id = "Humanizer.Core", Version = "2.14.1" },
+ new Package { Id = "Humanizer.Core.es", Version = "2.14.1" },
+ },
+ };
+ proj.SetRuntime (AndroidRuntime.CoreCLR);
+ proj.SetProperty ("AndroidTypeMapImplementation", "llvm-ir");
+ proj.SetProperty (KnownProperties.PublishTrimmed, true.ToString ());
+ proj.MainActivity = proj.DefaultMainActivity
+ .Replace ("//${USINGS}", "using Humanizer;")
+ .Replace ("//${AFTER_ONCREATE}", "System.Console.WriteLine (System.DateTime.UtcNow.Humanize ());");
+
+ using var builder = CreateApkBuilder ();
+ var buildParameters = new [] { $"RestorePackagesPath={proj.GlobalPackagesFolder}" };
+ Assert.IsTrue (builder.Restore (proj, parameters: buildParameters), "Package restore should have succeeded.");
+ Assert.IsTrue (builder.Build (proj, doNotCleanupOnUpdate: true, saveProject: false, parameters: buildParameters),
+ "Initial build should have succeeded.");
+
+ var satelliteAssemblies = Directory.GetFiles (proj.GlobalPackagesFolder, "*.resources.dll", SearchOption.AllDirectories);
+ Assert.IsNotEmpty (satelliteAssemblies, "The NuGet package should contain satellite assemblies.");
+
+ var originalWriteTimes = new Dictionary ();
+ foreach (string assembly in satelliteAssemblies) {
+ File.SetLastWriteTimeUtc (assembly, new DateTime (2000, 1, 1, 0, 0, 0, DateTimeKind.Utc));
+ originalWriteTimes.Add (assembly, File.GetLastWriteTimeUtc (assembly));
+ }
+
+ var postLinkStamp = Path.Combine (Root, builder.ProjectDirectory, proj.IntermediateOutputPath, "stamp", "_AdditionalPostLinkerSteps.stamp");
+ FileAssert.Exists (postLinkStamp);
+ File.Delete (postLinkStamp);
+
+ // A package cache is immutable: deny write sharing and verify timestamps remain unchanged.
+ var packageLocks = satelliteAssemblies
+ .Select (assembly => File.Open (assembly, FileMode.Open, FileAccess.Read, FileShare.Read))
+ .ToList ();
+ try {
+ var postLinkParameters = buildParameters.Append ("TestEnableMarshalMethodsForPostLink=true").ToArray ();
+ Assert.IsTrue (builder.RunTarget (proj, "_PrepareAssemblies", doNotCleanupOnUpdate: true, saveProject: false, parameters: postLinkParameters),
+ "Preparing assemblies should have succeeded.");
+ FileAssert.Exists (postLinkStamp);
+ foreach (string assembly in satelliteAssemblies) {
+ Assert.AreEqual (originalWriteTimes [assembly], File.GetLastWriteTimeUtc (assembly), $"Build should not modify '{assembly}'.");
+ }
+ } finally {
+ foreach (var packageLock in packageLocks) {
+ packageLock.Dispose ();
+ }
+ }
+ }
+
[Test]
[TestCase (true, AndroidRuntime.CoreCLR)]
[TestCase (false, AndroidRuntime.CoreCLR)]
diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
index 57fa1a57afc..82c799eed84 100644
--- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
+++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
@@ -1472,8 +1472,10 @@ because xbuild doesn't support framework reference assemblies.
Outputs="$(_AdditionalPostLinkerStepsFlag)">
- <_AfterILLinkDestFiles Condition=" '$(_AndroidUseMarshalMethods)' != 'True' " Include="@(ResolvedAssemblies->'$(_AfterILLinkOutputDir)%(DestinationSubPath)')" />
- <_AfterILLinkDestFiles Condition=" '$(_AndroidUseMarshalMethods)' == 'True' " Include="@(ResolvedAssemblies)" />
+ <_AfterILLinkSourceFiles Include="@(ResolvedAssemblies)"
+ Condition=" '$(_AndroidUseMarshalMethods)' != 'True' or !$([System.String]::Copy('%(ResolvedAssemblies.Filename)').ToLowerInvariant().EndsWith('.resources')) " />
+ <_AfterILLinkDestFiles Condition=" '$(_AndroidUseMarshalMethods)' != 'True' " Include="@(_AfterILLinkSourceFiles->'$(_AfterILLinkOutputDir)%(DestinationSubPath)')" />
+ <_AfterILLinkDestFiles Condition=" '$(_AndroidUseMarshalMethods)' == 'True' " Include="@(_AfterILLinkSourceFiles)" />
+ <_AfterILLinkSourceFiles Remove="@(_AfterILLinkSourceFiles)" />
<_AfterILLinkDestFiles Remove="@(_AfterILLinkDestFiles)" />