diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/DesignerTests.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/DesignerTests.cs index c8288443d5a..ec42201ab0c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/DesignerTests.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/DesignerTests.cs @@ -90,7 +90,8 @@ public CustomTextView(Context context, IAttributeSet attributes) : base(context, using (var libb = CreateDllBuilder (Path.Combine (path, lib.ProjectName), false, false)) using (var appb = CreateApkBuilder (Path.Combine (path, proj.ProjectName), false, false)) { // Save the library project, but don't build it yet - libb.Save (lib); + libb.Save (lib, saveProject: true); + FileAssert.Exists (Path.Combine(Root, path, lib.ProjectName, lib.ProjectFilePath)); appb.BuildLogFile = "build1.log"; appb.Target = target; Assert.IsTrue (appb.Build (proj, parameters: DesignerParameters), $"build should have succeeded for target `{target}`"); @@ -104,10 +105,10 @@ public CustomTextView(Context context, IAttributeSet attributes) : base(context, Assert.IsNotNull (doc.Element ("LinearLayout").Element ("unnamedproject.CustomTextView"), "unnamedproject.CustomTextView should have not been replaced with a $(Hash).CustomTextView"); // Build the library project now - Assert.IsTrue (libb.Build (lib, doNotCleanupOnUpdate: true), "library build should have succeeded."); + Assert.IsTrue (libb.Build (lib, doNotCleanupOnUpdate: true, saveProject: true), "library build should have succeeded."); appb.Target = "Build"; appb.BuildLogFile = "build2.log"; - Assert.IsTrue (appb.Build (proj, doNotCleanupOnUpdate: true), "app build should have succeeded."); + Assert.IsTrue (appb.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "app build should have succeeded."); Assert.IsTrue (appb.Output.AreTargetsAllBuilt ("_UpdateAndroidResgen"), "_UpdateAndroidResgen should have run completely."); Assert.IsTrue (appb.Output.AreTargetsAllBuilt ("_Foo"), "_Foo should have run completely"); doc = XDocument.Load (customViewPath); @@ -117,7 +118,16 @@ public CustomTextView(Context context, IAttributeSet attributes) : base(context, "unnamedproject.CustomTextView should have been replaced with a $(Hash).CustomTextView"); appb.Target = target; appb.BuildLogFile = "build3.log"; - Assert.IsTrue (appb.Build (proj, parameters: DesignerParameters, doNotCleanupOnUpdate: true), $"build should have succeeded for target `{target}`"); + Assert.IsTrue (appb.DesignTimeBuild (proj, parameters: DesignerParameters, doNotCleanupOnUpdate: true), $"build should have succeeded for target `{target}`"); + Assert.IsFalse (appb.Output.AreTargetsAllSkipped ("_UpdateAndroidResgen"), "_UpdateAndroidResgen should not have been skipped."); + Assert.IsTrue (appb.Output.AreTargetsAllBuilt ("_Foo"), "_Foo should have run completely"); + doc = XDocument.Load (customViewPath); + Assert.IsNull (doc.Element ("LinearLayout").Element ("UnnamedProject.CustomTextView"), + "UnnamedProject.CustomTextView should have been replaced with a $(Hash).CustomTextView"); + Assert.IsNull (doc.Element ("LinearLayout").Element ("unnamedproject.CustomTextView"), + "unnamedproject.CustomTextView should have been replaced with a $(Hash).CustomTextView"); + appb.BuildLogFile = "build4.log"; + Assert.IsTrue (appb.DesignTimeBuild (proj, parameters: DesignerParameters, doNotCleanupOnUpdate: true), $"build should have succeeded for target `{target}`"); Assert.IsTrue (appb.Output.AreTargetsAllSkipped ("_UpdateAndroidResgen"), "_UpdateAndroidResgen should have been skipped."); Assert.IsTrue (appb.Output.AreTargetsAllBuilt ("_Foo"), "_Foo should have run completely"); doc = XDocument.Load (customViewPath); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs index 55c05640ea6..eba5ef7313b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/IncrementalBuildTest.cs @@ -105,6 +105,11 @@ public void CheckNothingIsDeletedByIncrementalClean ([Values (true, false)] bool File.SetLastWriteTimeUtc (file, DateTime.UtcNow); } Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "Second should have succeeded"); + b.Output.AssertTargetIsNotSkipped ("_CleanMonoAndroidIntermediateDir"); + var stampFiles = Path.Combine (intermediate, "stamp", "_ResolveLibraryProjectImports.stamp"); + FileAssert.Exists (stampFiles, $"{stampFiles} should exists!"); + var libraryProjectImports = Path.Combine (intermediate, "libraryprojectimports.cache"); + FileAssert.Exists (libraryProjectImports, $"{libraryProjectImports} should exists!"); //No changes Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "Third should have succeeded"); @@ -827,6 +832,7 @@ public void ResolveLibraryProjectImports () b.BuildLogFile = "build2.log"; Assert.IsTrue (b.Build (proj), "second build should have succeeded."); + b.Output.AssertTargetIsNotSkipped ("_ResolveLibraryProjectImports"); FileAssert.Exists (cacheFile); var actual = ReadCache (cacheFile); CollectionAssert.AreEqual (actual.Jars.Select (j => j.ItemSpec).OrderBy (j => j), @@ -867,6 +873,22 @@ public void ResolveLibraryProjectImports () foreach (var targetName in targets) { Assert.IsTrue (b.Output.IsTargetSkipped (targetName), $"`{targetName}` should be skipped!"); } + + var filesToTouch = new [] { + Path.Combine (intermediate, "build.props"), + Path.Combine (intermediate, $"{proj.ProjectName}.pdb"), + }; + foreach (var file in filesToTouch) { + FileAssert.Exists (file); + File.SetLastWriteTimeUtc (file, DateTime.UtcNow); + } + + b.BuildLogFile = "build5.log"; + Assert.IsTrue (b.Build (proj), "fifth build should have succeeded."); + b.Output.AssertTargetIsNotSkipped ("_CleanMonoAndroidIntermediateDir"); + b.Output.AssertTargetIsNotSkipped ("_ResolveLibraryProjectImports"); + FileAssert.Exists (cacheFile); + FileAssert.Exists (stamp); } } @@ -1157,13 +1179,16 @@ public void DesignTimeBuild () var proj = new XamarinAndroidApplicationProject (); using (var b = CreateApkBuilder (Path.Combine ("temp", $"{nameof (IncrementalBuildTest)}{TestName}"))) { Assert.IsTrue (b.DesignTimeBuild (proj), "first dtb should have succeeded."); + var target = "_ResolveLibraryProjectImports"; + Assert.IsFalse (b.Output.IsTargetSkipped (target), $"`{target}` should not have been skipped."); // DesignTimeBuild=true lowercased var parameters = new [] { "DesignTimeBuild=true" }; Assert.IsTrue (b.RunTarget (proj, "Compile", doNotCleanupOnUpdate: true, parameters: parameters), "second dtb should have succeeded."); - var target = "_ResolveLibraryProjectImports"; Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should have been skipped."); Assert.IsTrue (b.RunTarget (proj, "UpdateGeneratedFiles", doNotCleanupOnUpdate: true, parameters: parameters), "UpdateGeneratedFiles should have succeeded."); Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should have been skipped."); + Assert.IsTrue (b.Build (proj, doNotCleanupOnUpdate: true, saveProject: false), "full build should have succeeded."); + Assert.IsFalse (b.Output.IsTargetSkipped (target), $"`{target}` should not have been skipped."); } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index df1bf28d741..f896c51896f 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -910,13 +910,18 @@ because xbuild doesn't support framework reference assemblies. False <_AndroidBuildPropertiesCacheExists Condition=" Exists('$(_AndroidBuildPropertiesCache)') ">True <_NuGetAssetsFile Condition=" Exists('$(ProjectAssetsFile)') ">$(ProjectAssetsFile) - <_NuGetAssetsFile Condition=" Exists('$(ProjectLockFile)') ">$(ProjectLockFile) + <_NuGetAssetsFile Condition=" '$(_NuGetAssetsFile)' == '' and Exists('$(ProjectLockFile)') ">$(ProjectLockFile) <_NuGetAssetsFile Condition=" '$(_NuGetAssetsFile)' == '' and Exists('packages.config') ">packages.config - <_NuGetAssetsTimestamp Condition=" '$(_NuGetAssetsFile)' != '' ">$([System.IO.File]::GetLastWriteTime('$(_NuGetAssetsFile)').Ticks) <_TypeMapKind Condition=" '$(AndroidIncludeDebugSymbols)' != 'True' ">mvid <_TypeMapKind Condition=" '$(AndroidIncludeDebugSymbols)' == 'True' And '$(_InstantRunEnabled)' == 'True' ">strings-files <_TypeMapKind Condition=" '$(AndroidIncludeDebugSymbols)' == 'True' And '$(_InstantRunEnabled)' != 'True' ">strings-asm + + + <_PropertyCacheItems Include="AotAssemblies=$(AotAssemblies)" /> @@ -945,7 +950,7 @@ because xbuild doesn't support framework reference assemblies. <_PropertyCacheItems Include="OS=$(OS)" /> <_PropertyCacheItems Include="AndroidIncludeDebugSymbols=$(AndroidIncludeDebugSymbols)" /> <_PropertyCacheItems Include="AndroidPackageNamingPolicy=$(AndroidPackageNamingPolicy)" /> - <_PropertyCacheItems Include="_NuGetAssetsTimestamp=$(_NuGetAssetsTimestamp)" /> + <_PropertyCacheItems Include="_NuGetAssetsFileHash=%(_NuGetAssetsFileHash.FileHash)" /> <_PropertyCacheItems Include="TypeMapKind=$(_TypeMapKind)" /> <_PropertyCacheItems Include="AndroidManifestPlaceholders=$(AndroidManifestPlaceholders)" /> <_PropertyCacheItems Include="ProjectFullPath=$(MSBuildProjectFullPath)" /> diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DesignTime.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DesignTime.targets index 00f3f2cfdd5..4569f574869 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DesignTime.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.DesignTime.targets @@ -13,45 +13,50 @@ This file is used by all project types, including binding projects. <_AndroidIntermediateDesignTimeBuildDirectory>$(IntermediateOutputPath)designtime\ + <_AndroidIntermediateDesignTimeStampDirectory>$(_AndroidIntermediateDesignTimeBuildDirectory)stamp\ <_AndroidDesignTimeBuildPropertiesCache>$(_AndroidIntermediateDesignTimeBuildDirectory)build.props <_AndroidLibraryImportsDesignTimeCache>$(_AndroidIntermediateDesignTimeBuildDirectory)libraryimports.cache <_AndroidLibraryProjectImportsDesignTimeCache>$(_AndroidIntermediateDesignTimeBuildDirectory)libraryprojectimports.cache <_AndroidManagedResourceDesignerFile>$(_AndroidIntermediateDesignTimeBuildDirectory)$(_AndroidResourceDesigner) - - - - <_AndroidMSBuildAllProjects Include="$(MSBuildAllProjects)" Exclude="$(MSBuildProjectFullPath).user" /> - + false + - + true true True False + <_AndroidStampDirectory Condition=" '$(DesignTimeBuild)' == 'true' ">$(_AndroidIntermediateDesignTimeStampDirectory) <_AndroidLibraryImportsCache Condition=" '$(DesignTimeBuild)' == 'true' And !Exists ('$(_AndroidLibraryImportsCache)') ">$(_AndroidLibraryImportsDesignTimeCache) <_AndroidLibraryProjectImportsCache Condition=" '$(DesignTimeBuild)' == 'true' And !Exists ('$(_AndroidLibraryProjectImportsCache)') ">$(_AndroidLibraryProjectImportsDesignTimeCache) <_AndroidBuildPropertiesCache Condition=" '$(DesignTimeBuild)' == 'true' ">$(_AndroidDesignTimeBuildPropertiesCache) + <_GeneratorStampFile Condition=" '$(DesignTimeBuild)' == 'true' And !Exists('$(_GeneratorStampFile)') ">$(_AndroidIntermediateDesignTimeStampDirectory)generator.stamp + <_AndroidResgenFlagFile Condition=" '$(DesignTimeBuild)' == 'true' And !Exists('$(_AndroidResgenFlagFile)') ">$(_AndroidIntermediateDesignTimeBuildDirectory)R.cs.flag +