Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Xamarin.Android.Build.Tasks] clean intermediates if NuGets change
Context: dotnet#1741 Fixes: dotnet#1828 PR dotnet#1741 is a good attempt at fixing this, but... - It is a little heavy handed and basically "nukes the world". - It does not reproduce an issue in a test and "fix it", it fixes an "unknown" #deletebinobj problem. I also have a few nitpicks about PR dotnet#1741: - It only comes into effect if `BuildingInsideVisualStudio` is `True`. We should also fix command-line builds. - The `$(ProjectLockFile).stamp` file isn't added to `FileWrites`. So let's improve on dotnet#1741! As it had some good ideas, we just need to narrow its focus. First, I reproduced a real issue in a test with the following scenario: - Create a Xamarin.Forms 2.3.4 app that uses the 25.4.x support libraries - Build it - Update the NuGets to Xamarin.Forms 3.0.x and the 27.x support libraries - Build again - Stuff breaks... namely the following message: bin\Debug\lib\xamarin.android\xbuild\Xamarin\Android\Xamarin.Android.Common.targets(2153,3): error MSB4018: The "GenerateJavaStubs" task failed unexpectedly. System.IO.FileNotFoundException: Could not load assembly 'System.IO, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'. Perhaps it doesn't exist in the Mono for Android profile? File name: 'System.IO.dll' at Java.Interop.Tools.Cecil.DirectoryAssemblyResolver.Resolve(AssemblyNameReference reference, ReaderParameters parameters) in external\Java.Interop\src\Java.Interop.Tools.Cecil\Java.Interop.Tools.Cecil\DirectoryAssemblyResolver.cs:line 241 at Java.Interop.Tools.Cecil.DirectoryAssemblyResolver.Resolve(AssemblyNameReference reference) in external\Java.Interop\src\Java.Interop.Tools.Cecil\Java.Interop.Tools.Cecil\DirectoryAssemblyResolver.cs:line 191 at Mono.Cecil.MetadataResolver.Resolve(TypeReference type) in external\mono\external\cecil\Mono.Cecil\MetadataResolver.cs:line 101 at Mono.Cecil.ModuleDefinition.Resolve(TypeReference type) in external\mono\external\cecil\Mono.Cecil\ModuleDefinition.cs:line 774 at Mono.Cecil.TypeReference.Resolve() in external\mono\external\cecil\Mono.Cecil\TypeReference.cs:line 280 at Java.Interop.Tools.Cecil.TypeDefinitionRocks.GetBaseType(TypeDefinition type) in external\Java.Interop\src\Java.Interop.Tools.Cecil\Java.Interop.Tools.Cecil\TypeDefinitionRocks.cs:line 14 at Java.Interop.Tools.Cecil.TypeDefinitionRocks.<GetTypeAndBaseTypes>d__1.MoveNext() in external\Java.Interop\src\Java.Interop.Tools.Cecil\Java.Interop.Tools.Cecil\TypeDefinitionRocks.cs:line 21 at System.Linq.Enumerable.Any[TSource](IEnumerable`1 source, Func`2 predicate) at Java.Interop.Tools.Cecil.TypeDefinitionRocks.IsSubclassOf(TypeDefinition type, String typeName) in external\Java.Interop\src\Java.Interop.Tools.Cecil\Java.Interop.Tools.Cecil\TypeDefinitionRocks.cs:line 55 at Java.Interop.Tools.JavaCallableWrappers.JavaTypeScanner.AddJavaTypes(List`1 javaTypes, TypeDefinition type) in external\Java.Interop\src\Java.Interop.Tools.JavaCallableWrappers\Java.Interop.Tools.JavaCallableWrappers\JavaTypeScanner.cs:line 46 at Java.Interop.Tools.JavaCallableWrappers.JavaTypeScanner.GetJavaTypes(IEnumerable`1 assemblies, IAssemblyResolver resolver) in external\Java.Interop\src\Java.Interop.Tools.JavaCallableWrappers\Java.Interop.Tools.JavaCallableWrappers\JavaTypeScanner.cs:line 36 at Xamarin.Android.Tasks.GenerateJavaStubs.Run(DirectoryAssemblyResolver res) in src\Xamarin.Android.Build.Tasks\Tasks\GenerateJavaStubs.cs:line 138 at Xamarin.Android.Tasks.GenerateJavaStubs.Execute() in src\Xamarin.Android.Build.Tasks\Tasks\GenerateJavaStubs.cs:line 91 at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute() at Microsoft.Build.BackEnd.TaskBuilder.<ExecuteInstantiatedTask>d__26.MoveNext() [bin\TestDebug\temp\BuildAfterUpgradingNuget\UnnamedProject.csproj] The real problem here though is that many of the intermediate files in `obj\Debug\lp` (among others) are out of sync. Namely we can see messages like this from the `ResolveLibraryProjectImports` MSBuild task in the build log: Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.animated.vector.drawable\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.Animated.Vector.Drawable.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.annotations\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.Annotations.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.compat\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.Compat.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.core.ui\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.Core.UI.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.core.utils\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.Core.Utils.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.design\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.Design.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.fragment\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.Fragment.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.media.compat\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.Media.Compat.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.transition\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.Transition.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.v4\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.v4.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.v7.appcompat\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.v7.AppCompat.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.v7.cardview\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.v7.CardView.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.v7.mediarouter\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.v7.MediaRouter.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.v7.palette\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.v7.Palette.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.v7.recyclerview\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.v7.RecyclerView.dll: extracted files are up to date Skipped resource lookup for C:\Users\myuser\.nuget\packages\xamarin.android.support.vector.drawable\27.0.2.1\lib\MonoAndroid81\Xamarin.Android.Support.Vector.Drawable.dll: extracted files are up to date These are *bad*, since the extracted files were from the 25.4.x support libraries! It is happening because the timestamps of these system-wide `%UserProfile%\.nuget` NuGet packages are quite old. So a solution for now, based on dotnet#1741: - When NuGet packages change - Clean some subset of files/directories -- not a full `Clean` I borrowed the logic for calculating `$(_NuGetAssetsFile)` from dotnet#1741, since it was working pretty well. I added a `_CleanIntermediateIfNuGetsChange` MSBuild target that runs the `_CleanMonoAndroidIntermediateDir` target as this was the smallest deletion I could figure out that fixes the problem. At first I tried deleting other subsets of files/directories, but couldn't find a combination that worked. This change does have some impact on build times, when `_CleanIntermediateIfNuGetsChange` runs and deletes files, it takes 1-2 seconds on my machine for the test case. There will also be further build time taken from other targets that run because files were deleted. However, we would likely prefer a slightly slower, correct build, than a faster incorrect one... It is certaining going to be faster than the `Build`, error message, `Rebuild` cycle -- or nuking `bin` and `obj`. Down the road, we could consider some other change to refactor how `obj\Debug\lp` is generated and make it resilient to NuGet changes.
- Loading branch information