Skip to content

Commit 01be8ac

Browse files
dellis1972jonpryor
authored andcommitted
[Xamarin.Android.Build.Tasks] Stop designtime designer being deleted. (#1307)
Fixes: #1286 We have a number of problems with our DesignTime build system. The main one which this PR addresses is the designer file is deleted by `IncrementalClean` AND `CoreClean`. This them completely messes up the DesignTime system since it can no longer find the file. So what we should be doing is making sure we don't tell the build system about the designer file ;-). We do this by not writing the path to the `$(CleanFile)`. ~~ Some background on the [DesignTime build system][2] ~~ The primary entry point is the `CoreCompile` target, with occasional calls to the `RefreshReferences` target. In theory [`$(DesignTimeBuild)`][1] should be set to `true`; however, this is not always the case which is why we have the `_SetupForDesignTimeBuild` target which hooks into the `CoreCompile` target. Additionally, `$(BuildingProject)` should be False. ([Additional information][2]). However this document is not seem to be 100% accurate since the IDE's (namely Visual Studio) do not always set the required properties. One of the key requirements for design time builds seems to be that they are independent of the main builds. The files it uses should not be removed since the `CoreCompile` target does not seem to be called consistently. For example, if the designer file is removed and the `RefreshReferences` target is called, the design time build may well fail because the targets required to re-generate the designer file are not called. Now for the problem: the `IncrementalClean` target runs between builds. It seems to want to remove files from the previous build. I suspect the purpose is to remove files that are no longer needed. (For example an assembly which is no longer referenced.) The problem is that we have a file (the design time `Resource.designer.cs`) which is not built as part of the normal build. But this file was still being written to `$(CleanFile)` which is the driver for the `IncrementalClean` process. As a result, the file gets removed because its not in the list of current `@(FileWrites)`. Not writing the name of this file to `$(CleanFile)` seems to hide it from `IncrementalClean`. There was also another problem with the `CoreClean` target. This was also removing the designer files. Again this was down to the fact that the file was listed in `$(CleanFile)`. However our older workarounds did not work since they relied on `IncrementalClean` running. For a `Clean` target invocation it does not. Again the solution seems to be Don't Write the file to `$(CleanFile)`, which is counterintuitive since we are told to write all files we generate to that file. [1]: https://github.com/dotnet/project-system/blob/master/docs/design-time-builds.md#determining-whether-a-target-is-run-in-a-design-time-build [2]: https://github.com/dotnet/project-system/blob/master/docs/design-time-builds.md
1 parent 34f437d commit 01be8ac

File tree

4 files changed

+45
-9
lines changed

4 files changed

+45
-9
lines changed

src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Common/ImportAfter/Xamarin.Android.Windows.targets

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Copyright (C) 2014 Xamarin. All rights reserved.
1515
</PropertyGroup>
1616

1717
<Target Name="_RegisterAndroidFilesWithFileWrites" BeforeTargets="IncrementalClean" Condition=" '$(_IsRunningXBuild)' != 'true' ">
18-
<CreateItem Include="$(OutDir)*.pdb;$(OutDir)*.dll;$(OutDir)*.dll.mdb;$(MonoAndroidIntermediateAssemblyDir)*.dll.mdb;$(MonoAndroidIntermediateAssemblyDir)*.pdb;$(MonoAndroidLinkerInputDir)*.dll.mdb;$(MonoAndroidLinkerInputDir)*.pdb;$(_AndroidManagedResourceDesignerFile)">
18+
<CreateItem Include="$(OutDir)*.pdb;$(OutDir)*.dll;$(OutDir)*.dll.mdb;$(MonoAndroidIntermediateAssemblyDir)*.dll.mdb;$(MonoAndroidIntermediateAssemblyDir)*.pdb;$(MonoAndroidLinkerInputDir)*.dll.mdb;$(MonoAndroidLinkerInputDir)*.pdb">
1919
<Output TaskParameter="Include" ItemName="_FilesToRegister" />
2020
</CreateItem>
2121
<CreateItem Include="$([System.IO.Path]::GetFullPath('%(_FilesToRegister.Identity)'))"

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ public void BuildAppWithManagedResourceParser()
10161016
"Target '_ManagedUpdateAndroidResgen' should not have run.");
10171017

10181018
Assert.IsTrue (appBuilder.Clean (appProj), "Clean should have succeeded");
1019-
Assert.IsFalse (File.Exists (designerFile), $"'{designerFile}' should have been cleaned.");
1019+
Assert.IsTrue (File.Exists (designerFile), $"'{designerFile}' should not have been cleaned.");
10201020

10211021
}
10221022
}
@@ -1112,10 +1112,10 @@ public void BuildAppWithManagedResourceParserAndLibraries ()
11121112

11131113

11141114
Assert.IsTrue (appBuilder.Clean (appProj), "Clean should have succeeded");
1115-
Assert.IsFalse (File.Exists (designerFile), $"'{designerFile}' should have been cleaned.");
1115+
Assert.IsTrue (File.Exists (designerFile), $"'{designerFile}' should not have been cleaned.");
11161116
designerFile = Path.Combine (Root, path, libProj.ProjectName, libProj.IntermediateOutputPath, "designtime", "Resource.Designer.cs");
11171117
Assert.IsTrue (libBuilder.Clean (libProj), "Clean should have succeeded");
1118-
Assert.IsFalse (File.Exists (designerFile), $"'{designerFile}' should have been cleaned.");
1118+
Assert.IsTrue (File.Exists (designerFile), $"'{designerFile}' should not have been cleaned.");
11191119

11201120

11211121
}

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

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,47 @@ namespace Xamarin.Android.Build.Tests
1212
[Parallelizable (ParallelScope.Children)]
1313
public class IncrementalBuildTest : BaseTest
1414
{
15+
[Test]
16+
public void IncrementalCleanDuringClean ()
17+
{
18+
var path = Path.Combine ("temp", TestName);
19+
var proj = new XamarinAndroidApplicationProject () {
20+
ProjectName = "App1",
21+
IsRelease = true,
22+
};
23+
proj.SetProperty ("AndroidUseManagedDesignTimeResourceGenerator", "True");
24+
proj.SetProperty ("BuildingInsideVisualStudio", "True");
25+
using (var b = CreateApkBuilder (path)) {
26+
b.Target = "Compile";
27+
Assert.IsTrue(b.Build (proj), "DesignTime Build should have succeeded");
28+
var designTimeDesigner = Path.Combine (Root, b.ProjectDirectory, proj.IntermediateOutputPath, "designtime", "Resource.designer.cs");
29+
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should have been created.");
30+
b.Target = "Build";
31+
Assert.IsTrue(b.Build (proj), "Build should have succeeded");
32+
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should still exist after Build.");
33+
b.Target = "Clean";
34+
Assert.IsTrue(b.Build (proj), "Clean should have succeeded");
35+
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should still exist after Clean.");
36+
b.Target = "Compile";
37+
Assert.IsTrue(b.Build (proj), "Build should have succeeded");
38+
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should still exist after Compile.");
39+
b.Target = "Build";
40+
Assert.IsTrue(b.Build (proj), "Build should have succeeded");
41+
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should still exist after second Build.");
42+
Assert.IsTrue(b.Build (proj), "Build should have succeeded");
43+
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should still exist after third Build.");
44+
b.Target = "Compile";
45+
Assert.IsTrue(b.Build (proj), "Build should have succeeded");
46+
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should still exist after second Compile.");
47+
b.Target = "Clean";
48+
Assert.IsTrue(b.Build (proj), "Clean should have succeeded");
49+
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should still exist after second Clean.");
50+
b.Target = "ReBuild";
51+
Assert.IsTrue(b.Build (proj), "ReBuild should have succeeded");
52+
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should still exist after ReBuild.");
53+
}
54+
55+
}
1556

1657
[Test]
1758
public void LibraryIncrementalBuild () {

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

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,11 +1116,6 @@ because xbuild doesn't support framework reference assemblies.
11161116
<Compile Remove="@(CorrectCasedItem)" Condition=" '$(ManagedDesignTimeBuild)' == 'True' And '%(CorrectCasedItem.Identity)' != '' "/>
11171117
<Compile Include="$(_AndroidManagedResourceDesignerFile)" Condition=" '$(ManagedDesignTimeBuild)' == 'True' And Exists ('$(_AndroidManagedResourceDesignerFile)')" />
11181118
</ItemGroup>
1119-
<WriteLinesToFile
1120-
Condition="Exists ('$(_AndroidManagedResourceDesignerFile)')"
1121-
File="$(IntermediateOutputPath)$(CleanFile)"
1122-
Lines="$([System.IO.Path]::GetFullPath('$(_AndroidManagedResourceDesignerFile)'))"
1123-
Overwrite="false" />
11241119
</Target>
11251120

11261121
<!-- Resource Build -->

0 commit comments

Comments
 (0)