Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] Move DesignTime Designer to `$(BaseInte…
Browse files Browse the repository at this point in the history
…rmediateOutputPath)`.

Fixes dotnet#1286

One of the problems we face with design time builds is MSBuild
keeps deleting our files. As a result the design time build keeps
failing. The main reason for this is `IncrementalClean` keeps
removing the files. But in addition to this the `Clean` target
also ends up deleting these files. However our existing `fix` does
not work since `IncrementalClean` is not called. So the code we
have to save the files is not called.

One solution is to move the generated files out from the
`$(IntermediateOutputPath)` and into the `$(BaseIntermediateOutputPath)`.
The latter is not cleaned by the `IncrementalClean` target in
MSBuild.

Those does present a problem with our `xbuild` support. xbuild has
a target `CoreClean` which is called when `Clean` is called. However
it also calls `_GetCleanFileWrites` which populates the `PreviousFileWrites`
ItemGroup with files in the `$(CleanFile)`. As a result xbuild deletes
the files even if they are in `$(BaseIntermediateOutputPath)`. This
behaviour is different from MSBuild.

Interestingly `Xamarin.Android.Windows.targets` has some code in it already
to determine if we are running under MSBuild or xbuild. It also contains
the code for dealing with the `IncrementalClean` target problems.

Since we need some of those code on any platform that uses MSBuild
(Windows, Mac and Linux) we should move some of that code into the
main `Xamarin.Android.Common.targets/props` and reuse some of it to
handle this problem.

The code to check if we are running on MSBuild or xbuild is now in
`Xamarin.Android.Common.props`. The `_RegisterAndroidFilesWithFileWrites`
is now in `Xamarin.Android.Common.targets` along side a new target
`_OverrideXbuildCleanFileWrites` which will prevent the design time
files from being deleted under xbuild.

The various tests have been updated to reflect this new setup. A new
test to make sure we never delete these files has been added.
  • Loading branch information
dellis1972 committed Feb 13, 2018
1 parent cb68bc3 commit 0cec603
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,6 @@ Copyright (C) 2014 Xamarin. All rights reserved.

<PropertyGroup>
<Debugger Condition="'$(Debugger)'==''">Xamarin</Debugger>
<_IsRunningXBuild Condition=" '$(MSBuildRuntimeVersion)' == '' ">true</_IsRunningXBuild>
</PropertyGroup>

<Target Name="_RegisterAndroidFilesWithFileWrites" BeforeTargets="IncrementalClean" Condition=" '$(_IsRunningXBuild)' != 'true' ">
<CreateItem Include="$(OutDir)*.pdb;$(OutDir)*.dll;$(OutDir)*.dll.mdb;$(MonoAndroidIntermediateAssemblyDir)*.dll.mdb;$(MonoAndroidIntermediateAssemblyDir)*.pdb;$(MonoAndroidLinkerInputDir)*.dll.mdb;$(MonoAndroidLinkerInputDir)*.pdb;$(_AndroidManagedResourceDesignerFile)">
<Output TaskParameter="Include" ItemName="_FilesToRegister" />
</CreateItem>
<CreateItem Include="$([System.IO.Path]::GetFullPath('%(_FilesToRegister.Identity)'))"
Condition="Exists('%(_FilesToRegister.Identity)')">
<Output TaskParameter="Include" ItemName="_CleanCurrentFileWrites" />
</CreateItem>
</Target>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ public void DesignTimeBuild ([Values(false, true)] bool isRelease, [Values (fals
new BuildItem.ProjectReference (@"..\Lib1\Lib1.csproj", lib.ProjectName, lib.ProjectGuid),
},
};
var baseIntermediateOutputPath = Path.Combine (path, proj.ProjectName, "obj");
var intermediateOutputPath = Path.Combine (path, proj.ProjectName, proj.IntermediateOutputPath);
proj.SetProperty ("AndroidUseManagedDesignTimeResourceGenerator", useManagedParser.ToString ());
if (useManagedParser)
Expand Down Expand Up @@ -100,7 +101,7 @@ public void DesignTimeBuild ([Values(false, true)] bool isRelease, [Values (fals
first = items.First ();
Assert.IsTrue (items.All (x => x == first), "All Items should have matching values");
}
var designTimeDesigner = Path.Combine (intermediateOutputPath, "designtime", "Resource.designer.cs");
var designTimeDesigner = Path.Combine (baseIntermediateOutputPath, proj.GetProperty (KnownProperties.Configuration) + "_Resource.designer.cs");
if (useManagedParser) {
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should have been created.");
}
Expand Down Expand Up @@ -1000,7 +1001,7 @@ public void BuildAppWithManagedResourceParser()
"DesignTime Application Build should have succeeded.");
Assert.IsFalse (appProj.CreateBuildOutput (appBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"),
"Target '_ManagedUpdateAndroidResgen' should have run.");
var designerFile = Path.Combine (Root, path, appProj.ProjectName, appProj.IntermediateOutputPath, "designtime", "Resource.Designer.cs");
var designerFile = Path.Combine (Root, path, appProj.ProjectName, "obj", appProj.GetProperty (KnownProperties.Configuration) + "_Resource.designer.cs");
FileAssert.Exists (designerFile, $"'{designerFile}' should have been created.");

var designerContents = File.ReadAllText (designerFile);
Expand All @@ -1016,7 +1017,7 @@ public void BuildAppWithManagedResourceParser()
"Target '_ManagedUpdateAndroidResgen' should not have run.");

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

}
}
Expand Down Expand Up @@ -1075,7 +1076,7 @@ public void BuildAppWithManagedResourceParserAndLibraries ()
Assert.LessOrEqual (appBuilder.LastBuildTime.TotalMilliseconds, maxBuildTimeMs, $"DesignTime build should be less than {maxBuildTimeMs} milliseconds.");
Assert.IsFalse (appProj.CreateBuildOutput (appBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"),
"Target '_ManagedUpdateAndroidResgen' should have run.");
var designerFile = Path.Combine (Root, path, appProj.ProjectName, appProj.IntermediateOutputPath, "designtime", "Resource.Designer.cs");
var designerFile = Path.Combine (Root, path, appProj.ProjectName, "obj", appProj.GetProperty (KnownProperties.Configuration) + "_Resource.designer.cs");
FileAssert.Exists (designerFile, $"'{designerFile}' should have been created.");

var designerContents = File.ReadAllText (designerFile);
Expand Down Expand Up @@ -1112,10 +1113,10 @@ public void BuildAppWithManagedResourceParserAndLibraries ()


Assert.IsTrue (appBuilder.Clean (appProj), "Clean should have succeeded");
Assert.IsFalse (File.Exists (designerFile), $"'{designerFile}' should have been cleaned.");
designerFile = Path.Combine (Root, path, libProj.ProjectName, libProj.IntermediateOutputPath, "designtime", "Resource.Designer.cs");
Assert.IsTrue (File.Exists (designerFile), $"'{designerFile}' should not have been cleaned.");
designerFile = Path.Combine (Root, path, libProj.ProjectName, "obj", libProj.GetProperty (KnownProperties.Configuration) + "_Resource.designer.cs");
Assert.IsTrue (libBuilder.Clean (libProj), "Clean should have succeeded");
Assert.IsFalse (File.Exists (designerFile), $"'{designerFile}' should have been cleaned.");
Assert.IsTrue (File.Exists (designerFile), $"'{designerFile}' should not have been cleaned.");


}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2012,7 +2012,7 @@ public void BuildInDesignTimeMode ([Values(false, true)] bool useManagedParser)
builder.Build (proj, parameters: new string[] { "DesignTimeBuild=true" });
Assert.IsFalse (builder.Output.IsTargetSkipped ("_CreatePropertiesCache"), "target \"_CreatePropertiesCache\" should have been run.");
Assert.IsFalse (builder.Output.IsTargetSkipped ("_ResolveLibraryProjectImports"), "target \"_ResolveLibraryProjectImports\' should have been run.");
var librarycache = Path.Combine (Root, path, proj.IntermediateOutputPath, "designtime", "libraryprojectimports.cache");
var librarycache = Path.Combine (Root, path, "obj", proj.GetProperty (KnownProperties.Configuration) + "_libraryprojectimports.cache");
Assert.IsTrue (File.Exists (librarycache), $"'{librarycache}' should exist.");
librarycache = Path.Combine (Root, path, proj.IntermediateOutputPath, "libraryprojectimports.cache");
Assert.IsFalse (File.Exists (librarycache), $"'{librarycache}' should not exist.");
Expand All @@ -2022,7 +2022,7 @@ public void BuildInDesignTimeMode ([Values(false, true)] bool useManagedParser)
Assert.IsTrue (builder.Clean (proj), "Clean Should have succeeded");
builder.Target = "_CleanDesignTimeIntermediateDir";
Assert.IsTrue (builder.Build (proj), "_CleanDesignTimeIntermediateDir should have succeeded");
librarycache = Path.Combine (Root, path, proj.IntermediateOutputPath, "designtime", "libraryprojectimports.cache");
librarycache = Path.Combine (Root, path, "obj", proj.GetProperty (KnownProperties.Configuration) + "_libraryprojectimports.cache");
Assert.IsFalse (File.Exists (librarycache), $"'{librarycache}' should not exist.");
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,32 @@ public Class1 ()
}
}

[Test]
public void IncrementalCleanDuringClean ()
{
var path = Path.Combine ("temp", TestName);
var proj = new XamarinAndroidApplicationProject () {
ProjectName = "App1",
IsRelease = true,
};
proj.SetProperty ("AndroidUseManagedDesignTimeResourceGenerator", "True");
proj.SetProperty ("BuildingInsideVisualStudio", "True");
var intermediateOutputPath = Path.Combine (Root, path, "obj");
using (var b = CreateApkBuilder (path, false, false)) {
b.Target = "Compile";
Assert.IsTrue(b.Build (proj), "DesignTime Build should have succeeded");
var designTimeDesigner = Path.Combine (intermediateOutputPath, proj.GetProperty (KnownProperties.Configuration) + "_Resource.designer.cs");
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should have been created.");
b.Target = "Build";
Assert.IsTrue(b.Build (proj), "Build should have succeeded");
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should still exist after Build.");
b.Target = "Clean";
Assert.IsTrue(b.Build (proj), "Clean should have succeeded");
FileAssert.Exists (designTimeDesigner, $"{designTimeDesigner} should still exist after Clean.");
}

}

[Test]
public void AllProjectsHaveSameOutputDirectory()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
<Reference Include="nunit.framework">
<HintPath>..\..\..\..\packages\NUnit.3.7.1\lib\net45\nunit.framework.dll</HintPath>
</Reference>
<!-- Because Xamarin.Android.Build.Tasks.csproj doesn't build in VsForMac :(
<!-- Because Xamarin.Android.Build.Tasks.csproj doesn't build in VsForMac :(
<Reference Include="Xamarin.Android.Build.Tasks" Condition="Exists('$(OutputPath)..\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\Xamarin.Android.Build.Tasks.dll')">
<HintPath>$(OutputPath)..\$(Configuration)\lib\xamarin.android\xbuild\Xamarin\Android\Xamarin.Android.Build.Tasks.dll</HintPath>
</Reference>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,6 @@
<LatestSupportedJavaVersion Condition="'$(LatestSupportedJavaVersion)' == ''">1.8.0</LatestSupportedJavaVersion>
<MinimumSupportedJavaVersion Condition="'$(MinimumSupportedJavaVersion)' == ''">1.6.0</MinimumSupportedJavaVersion>
<AndroidVersionCodePattern Condition=" '$(AndroidUseLegacyVersionCode)' != 'True' And '$(AndroidVersionCodePattern)' == '' ">{abi}{versionCode:D5}</AndroidVersionCodePattern>
<_IsRunningXBuild Condition=" '$(MSBuildRuntimeVersion)' == '' ">true</_IsRunningXBuild>
</PropertyGroup>
</Project>
44 changes: 34 additions & 10 deletions src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets
Original file line number Diff line number Diff line change
Expand Up @@ -399,9 +399,9 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
<DesignTimeBuild Condition=" '$(DesignTimeBuild)' == '' ">true</DesignTimeBuild>
<ManagedDesignTimeBuild Condition=" '$(AndroidUseManagedDesignTimeResourceGenerator)' == 'True' And '$(DesignTimeBuild)' == 'True' And '$(BuildingInsideVisualStudio)' == 'True' ">True</ManagedDesignTimeBuild>
<ManagedDesignTimeBuild Condition=" '$(ManagedDesignTimeBuild)' == '' ">False</ManagedDesignTimeBuild>
<_AndroidResourcePathsCache Condition=" '$(DesignTimeBuild)' == 'true' ">$(_AndroidDesignTimeResDirIntermediate)resourcepaths.cache</_AndroidResourcePathsCache>
<_AndroidLibraryImportsCache Condition=" '$(DesignTimeBuild)' == 'true' ">$(_AndroidDesignTimeResDirIntermediate)libraryimports.cache</_AndroidLibraryImportsCache>
<_AndroidLibraryProjectImportsCache Condition=" '$(DesignTimeBuild)' == 'true' ">$(_AndroidDesignTimeResDirIntermediate)libraryprojectimports.cache</_AndroidLibraryProjectImportsCache>
<_AndroidResourcePathsCache Condition=" '$(DesignTimeBuild)' == 'true' ">$(_AndroidDesignTimeResDirIntermediate)$(Configuration)_resourcepaths.cache</_AndroidResourcePathsCache>
<_AndroidLibraryImportsCache Condition=" '$(DesignTimeBuild)' == 'true' ">$(_AndroidDesignTimeResDirIntermediate)$(Configuration)_libraryimports.cache</_AndroidLibraryImportsCache>
<_AndroidLibraryProjectImportsCache Condition=" '$(DesignTimeBuild)' == 'true' ">$(_AndroidDesignTimeResDirIntermediate)$(Configuration)_libraryprojectimports.cache</_AndroidLibraryProjectImportsCache>
</PropertyGroup>
<MakeDir Directories="$(_AndroidDesignTimeResDirIntermediate)" Condition=" '$(DesignTimeBuild)' == 'true' " />
</Target>
Expand All @@ -427,6 +427,9 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved.
ContinueOnError="$(DesignTimeBuild)"
Condition=" '$(DesignTimeBuild)' == '' Or '$(DesignTimeBuild)' == 'false' "
/>
<ItemGroup>
<FileWrites Include="$(_AndroidResourcePathsCache)" />
</ItemGroup>
<Message Text="Skipping GetAdditionalResourcesFromAssemblies in DesignTime build" Condition=" '$(DesignTimeBuild)' == 'true' " />
</Target>

Expand Down Expand Up @@ -1043,8 +1046,8 @@ because xbuild doesn't support framework reference assemblies.
<_AndroidStaticResourcesFlag>$(IntermediateOutputPath)static.flag</_AndroidStaticResourcesFlag>
<_AndroidResourcesCacheFile>$(IntermediateOutputPath)mergeresources.cache</_AndroidResourcesCacheFile>
<AndroidUseManagedDesignTimeResourceGenerator Condition=" '$(AndroidUseManagedDesignTimeResourceGenerator)' == '' " >True</AndroidUseManagedDesignTimeResourceGenerator>
<_AndroidDesignTimeResDirIntermediate>$(IntermediateOutputPath)designtime\</_AndroidDesignTimeResDirIntermediate>
<_AndroidManagedResourceDesignerFile>$(_AndroidDesignTimeResDirIntermediate)$(_AndroidResourceDesigner)</_AndroidManagedResourceDesignerFile>
<_AndroidDesignTimeResDirIntermediate>$(BaseIntermediateOutputPath)\</_AndroidDesignTimeResDirIntermediate>
<_AndroidManagedResourceDesignerFile>$(_AndroidDesignTimeResDirIntermediate)$(Configuration)_$(_AndroidResourceDesigner)</_AndroidManagedResourceDesignerFile>
</PropertyGroup>

<ItemGroup>
Expand Down Expand Up @@ -1116,11 +1119,6 @@ because xbuild doesn't support framework reference assemblies.
<Compile Remove="@(CorrectCasedItem)" Condition=" '$(ManagedDesignTimeBuild)' == 'True' And '%(CorrectCasedItem.Identity)' != '' "/>
<Compile Include="$(_AndroidManagedResourceDesignerFile)" Condition=" '$(ManagedDesignTimeBuild)' == 'True' And Exists ('$(_AndroidManagedResourceDesignerFile)')" />
</ItemGroup>
<WriteLinesToFile
Condition="Exists ('$(_AndroidManagedResourceDesignerFile)')"
File="$(IntermediateOutputPath)$(CleanFile)"
Lines="$([System.IO.Path]::GetFullPath('$(_AndroidManagedResourceDesignerFile)'))"
Overwrite="false" />
</Target>

<!-- Resource Build -->
Expand Down Expand Up @@ -1188,6 +1186,9 @@ because xbuild doesn't support framework reference assemblies.
AssemblyIdentityMapFile="$(_AndroidLibrayProjectAssemblyMapFile)"
OutputImportDirectory="$(_AndroidLibrayProjectIntermediatePath)">
</ResolveLibraryProjectImports>
<ItemGroup>
<FileWrites Include="$(_AndroidLibraryProjectImportsCache)" />
</ItemGroup>
</Target>

<Target Name="_ExtractLibraryProjectImports" DependsOnTargets="_ResolveLibraryProjectImports">
Expand Down Expand Up @@ -1249,6 +1250,9 @@ because xbuild doesn't support framework reference assemblies.
<GetImportedLibraries TargetDirectory="$(_AndroidLibrayProjectIntermediatePath)"
CacheFile="$(_AndroidLibraryImportsCache)">
</GetImportedLibraries>
<ItemGroup>
<FileWrites Include="$(_AndroidLibraryImportsCache)" />
</ItemGroup>
</Target>

<Target Name="_GetLibraryImports" DependsOnTargets="$(_GetLibraryImportsDependsOnTargets)">
Expand Down Expand Up @@ -2675,6 +2679,26 @@ because xbuild doesn't support framework reference assemblies.
<Delete Files="@(_OutputDeploymentFiles)"/>
</Target>

<!-- IncrementalClean work arounds for MSBuild and xbuild -->
<Target Name="_RegisterAndroidFilesWithFileWrites" BeforeTargets="IncrementalClean" Condition=" '$(_IsRunningXBuild)' != 'true' ">
<CreateItem Include="$(OutDir)*.pdb;$(OutDir)*.dll;$(OutDir)*.dll.mdb;$(MonoAndroidIntermediateAssemblyDir)*.dll.mdb;$(MonoAndroidIntermediateAssemblyDir)*.pdb;$(MonoAndroidLinkerInputDir)*.dll.mdb;$(MonoAndroidLinkerInputDir)*.pdb;$(_AndroidManagedResourceDesignerFile)">
<Output TaskParameter="Include" ItemName="_FilesToRegister" />
</CreateItem>
<CreateItem Include="$([System.IO.Path]::GetFullPath('%(_FilesToRegister.Identity)'))"
Condition="Exists('%(_FilesToRegister.Identity)')">
<Output TaskParameter="Include" ItemName="_CleanCurrentFileWrites" />
</CreateItem>
</Target>

<Target Name="_OverrideXbuildCleanFileWrites" BeforeTargets="_GetCleanFileWrites" Condition=" '$(_IsRunningXBuild)' == 'true' ">
<CreateItem Include="$(_AndroidDesignTimeResDirIntermediate)*.cache;$(_AndroidDesignTimeResDirIntermediate)*.cs;">
<Output TaskParameter="Include" ItemName="_FilesToRegister" />
</CreateItem>
<ItemGroup>
<PreviousFileWrites Remove="$([System.IO.Path]::GetFullPath('%(_FilesToRegister.Identity)'))" />
</ItemGroup>
</Target>

<Target Name="_CleanMonoAndroidIntermediateDir" DependsOnTargets="_CleanGeneratedDeploymentFiles;_CleanMsymArchive">
<RemoveDirFixed Directories="$(MonoAndroidIntermediate)android" Condition="Exists ('$(MonoAndroidIntermediate)android')" />
<!-- FIXME: remove this extraneous rmdir after a few release cycles since we release the one we killed it. -->
Expand Down

0 comments on commit 0cec603

Please sign in to comment.