Skip to content

Commit 0434024

Browse files
authored
Fix AndroidResource Incremental build issue (#9592)
Fixes #9588 Adding a new Android resource to a project causes the incremental build to error with: ``` Resources\layout\activity_two.xml error APT2126: file not found. ``` This error comes from the `Aapt2Compile` task. It is looking for `\obj\Debug\net9.0-android\res\layout\activity_two.xml` but that file doesn't exist. What was happening is the new file had the same modified date as the flag/stamp file that was used to generate it. The user was using `copy Resources\layout\activity_main.xml Resources\layout\activity_two.xml`. So the modified date was not "new". This caused the _GenerateAndroidResourceDir target to get skipped. What we should do is copy what we do in other places, and hash all the input files (and their destinations) into one hash. We can then use that hash file as an input to the target. This allows us to detect when a new file is added, even if it has an old timestamp. A unit test was added as well.
1 parent 0cff647 commit 0434024

File tree

3 files changed

+43
-1
lines changed

3 files changed

+43
-1
lines changed

src/Xamarin.Android.Build.Tasks/Tasks/AndroidComputeResPaths.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,9 @@ public class AndroidComputeResPaths : AndroidTask
6161
[Output]
6262
public ITaskItem [] ResolvedResourceFiles { get; set; }
6363

64+
[Output]
65+
public string FilesHash { get; set; }
66+
6467
public override bool RunTask ()
6568
{
6669
var intermediateFiles = new List<ITaskItem> (ResourceFiles.Length);
@@ -77,6 +80,7 @@ public override bool RunTask ()
7780
}
7881

7982
var nameCaseMap = new Dictionary<string, string> (ResourceFiles.Length, StringComparer.Ordinal);
83+
var sb = new StringBuilder ();
8084

8185
for (int i = 0; i < ResourceFiles.Length; i++) {
8286
var item = ResourceFiles [i];
@@ -151,10 +155,13 @@ public override bool RunTask ()
151155
item.CopyMetadataTo (newItem);
152156
intermediateFiles.Add (newItem);
153157
resolvedFiles.Add (item);
158+
// write both files so we handle changes in destination also
159+
sb.AppendLine ($"{item.ItemSpec};{newItem.ItemSpec}");
154160
}
155161

156162
IntermediateFiles = intermediateFiles.ToArray ();
157163
ResolvedResourceFiles = resolvedFiles.ToArray ();
164+
FilesHash = Files.HashString (sb.ToString ());
158165
MonoAndroidHelper.SaveResourceCaseMap (BuildEngine4, nameCaseMap, ProjectSpecificTaskObjectKey);
159166
return !Log.HasLoggedErrors;
160167
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,29 @@ ReadLibraryProjectImportsCache ReadCache (string cacheFile)
902902
return task;
903903
}
904904

905+
[Test]
906+
[NonParallelizable]
907+
public void AddNewAndroidResourceOnSecondBuild ()
908+
{
909+
var xml = new AndroidItem.AndroidResource (@"Resources\values\emptyvalues.xml") {
910+
TextContent = () => "<?xml version=\"1.0\" encoding=\"utf-8\" ?><resources></resources>"
911+
};
912+
913+
var proj = new XamarinAndroidApplicationProject ();
914+
using (var b = CreateApkBuilder (Path.Combine ("temp", TestName))) {
915+
var projectFile = Path.Combine (Root, b.ProjectDirectory, proj.ProjectFilePath);
916+
b.ThrowOnBuildFailure = false;
917+
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
918+
b.Output.AssertTargetIsNotSkipped ("_GenerateAndroidResourceDir");
919+
proj.OtherBuildItems.Add (xml);
920+
b.Save (proj, doNotCleanupOnUpdate: true);
921+
var modified = File.GetLastWriteTimeUtc (Path.Combine (Root, b.ProjectDirectory, "Resources","layout","Main.axml"));
922+
File.SetLastWriteTimeUtc (Path.Combine (Root, b.ProjectDirectory, "Resources","values", "emptyvalues.xml"), modified);
923+
Assert.IsTrue (b.Build (proj), "Build should have succeeded.");
924+
b.Output.AssertTargetIsNotSkipped ("_GenerateAndroidResourceDir");
925+
}
926+
}
927+
905928
[Test]
906929
[NonParallelizable]
907930
public void InvalidAndroidResource ()

src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
232232
<_AndroidBuildIdFile>$(IntermediateOutputPath)buildid.txt</_AndroidBuildIdFile>
233233
<_AndroidApplicationSharedLibraryPath>$(IntermediateOutputPath)app_shared_libraries\</_AndroidApplicationSharedLibraryPath>
234234
<_ResolvedUserAssembliesHashFile>$(IntermediateOutputPath)resolvedassemblies.hash</_ResolvedUserAssembliesHashFile>
235+
<_AndroidResolvedResourcesHashFile>$(IntermediateOutputPath)_AndroidResolvedResources.hash</_AndroidResolvedResourcesHashFile>
235236

236237
<AndroidDexTool Condition=" '$(AndroidDexTool)' != 'dx' ">d8</AndroidDexTool>
237238
<_AndroidXA1027 Condition=" '$(EnableProguard)' == 'true' And '$(AndroidEnableProguard)' == '' And '$(AndroidDexTool)' == 'd8' And $(AndroidLinkTool) == '' ">true</_AndroidXA1027>
@@ -1057,13 +1058,24 @@ because xbuild doesn't support framework reference assemblies.
10571058
>
10581059
<Output ItemName="_AndroidResourceDest" TaskParameter="IntermediateFiles" />
10591060
<Output ItemName="_AndroidResolvedResources" TaskParameter="ResolvedResourceFiles" />
1061+
<Output PropertyName="_AndroidResolvedResourcesFilesHash" TaskParameter="FilesHash" />
10601062
</AndroidComputeResPaths>
10611063

1064+
<WriteLinesToFile
1065+
File="$(_AndroidResolvedResourcesHashFile)"
1066+
Lines="$(_AndroidResolvedResourcesFilesHash)"
1067+
Overwrite="True"
1068+
WriteOnlyWhenDifferent="True"
1069+
/>
1070+
<ItemGroup>
1071+
<FileWrites Include="$(_AndroidResolvedResourcesHashFile)"/>
1072+
</ItemGroup>
1073+
10621074
<MakeDir Directories="$(MonoAndroidResDirIntermediate)" />
10631075
</Target>
10641076

10651077
<Target Name="_GenerateAndroidResourceDir"
1066-
Inputs="$(MSBuildProjectFullPath);@(_AndroidMSBuildAllProjects);@(_AndroidResolvedResources);$(_AndroidBuildPropertiesCache)"
1078+
Inputs="$(MSBuildProjectFullPath);@(_AndroidMSBuildAllProjects);@(_AndroidResolvedResources);$(_AndroidBuildPropertiesCache);$(_AndroidResolvedResourcesHashFile)"
10671079
Outputs="$(_AndroidResFlagFile)"
10681080
DependsOnTargets="$(_OnResolveMonoAndroidSdks)">
10691081
<CheckForInvalidResourceFileNames

0 commit comments

Comments
 (0)