From b159b9868dc4dac10f3166a3fa02255c3dbf40c1 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Fri, 18 Oct 2024 08:35:57 +0100 Subject: [PATCH 01/21] Rework Design Time Build to use .aar files directly. --- .../Steps/Step_CopyExtraResultFilesForCI.cs | 1 + .../Android/Xamarin.Android.Aapt2.targets | 2 +- .../Xamarin.Android.Resource.Designer.targets | 38 +++- ...osoft.Android.Sdk.AndroidLibraries.targets | 2 +- ...oft.Android.Sdk.AssemblyResolution.targets | 2 + .../Microsoft.Android.Sdk.BuildOrder.targets | 8 +- .../targets/Microsoft.Android.Sdk.targets | 3 +- .../Tasks/GenerateResourceCaseMap.cs | 37 ++++ .../Tasks/GenerateRtxt.cs | 4 +- .../Xamarin.Android.Build.Tests/BuildTest.cs | 17 +- .../IncrementalBuildTest.cs | 17 +- .../Utilities/FileResourceParser.cs | 169 +++++++++++------- .../Xamarin.Android.Common.targets | 8 +- .../Tests/PerformanceTest.cs | 21 +++ .../MSBuildDeviceIntegration.csv | 1 + 15 files changed, 239 insertions(+), 91 deletions(-) diff --git a/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs b/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs index fd88a337d04..be286992a62 100644 --- a/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs +++ b/build-tools/xaprepare/xaprepare/Steps/Step_CopyExtraResultFilesForCI.cs @@ -90,6 +90,7 @@ void CopyExtraBuildFiles (string destinationRoot, Context context) "*log", "TestOutput-*.txt", "Timing_*", + "*.runsettings", }; void CopyExtraTestFiles (string destinationRoot, Context context) diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets index d1bfde205de..be0c6c61539 100644 --- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Aapt2.targets @@ -27,7 +27,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. - + <_SetLatestTargetFrameworkVersionDependsOnTargets> $(_SetLatestTargetFrameworkVersionDependsOnTargets); _CreateAapt2VersionCache; diff --git a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets index 3fa46d4a2b9..e9636fc9521 100644 --- a/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets +++ b/src/Xamarin.Android.Build.Tasks/MSBuild/Xamarin/Android/Xamarin.Android.Resource.Designer.targets @@ -45,6 +45,8 @@ Copyright (C) 2016 Xamarin. All rights reserved. per TargetFramework. --> <_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' And '$(_OuterIntermediateOutputPath)' != '' ">$(_OuterIntermediateOutputPath) + <_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' And '$(_OuterIntermediateOutputPath)' != '' And '$(AndroidUseDesignerAssembly)' == 'True' And '$(DesignTimeBuild)' == 'true' ">$(_OuterIntermediateOutputPath)designtime\ + <_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' And '$(AndroidUseDesignerAssembly)' == 'True' And '$(DesignTimeBuild)' == 'true' ">$(IntermediateOutputPath)designtime\ <_DesignerIntermediateOutputPath Condition=" '$(_DesignerIntermediateOutputPath)' == '' ">$(IntermediateOutputPath) <_GenerateResourceDesignerAssemblyOutput>$(_DesignerIntermediateOutputPath)$(_DesignerAssemblyName).dll <_GenerateResourceDesignerClassFile Condition=" '$(Language)' == 'F#' ">$(_DesignerIntermediateOutputPath)_$(_DesignerAssemblyName).fs @@ -56,15 +58,44 @@ Copyright (C) 2016 Xamarin. All rights reserved. + + + <_ProjectReferenceResourceDirectory Include="$(MSBuildProjectDirectory)\$(MonoAndroidResourcePrefix)" + StampFile="$(MSBuildProjectFile)" + Condition="!Exists('$(OutputPath)$(TargetName).aar')" + /> + + + + + + + + + + + + + <_DesignTimeAarFiles Include="@(AndroidAarLibrary)" Condition=" '@(LibraryResourceDirectories->Count())' == '0' " /> + + + <_BuildResourceDesignerDependsOn> _SetupDesignerProperties; + _ResolveAars; + _CalculateDesignTimeAars; _GenerateResourceCaseMap; _GenerateRtxt; _GenerateResourceDesignerIntermediateClass; diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets index 14b9e8c2dee..e678933ab8b 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AndroidLibraries.targets @@ -18,7 +18,7 @@ projects. <_AarOutputPath>$(OutputPath)$(TargetName).aar - + <_AarSearchDirectory Include="@(_ReferencePath->'%(RootDir)%(Directory)')" /> <_AarSearchDirectory Include="@(_ReferenceDependencyPaths->'%(RootDir)%(Directory)')" /> diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets index 5bb9041cb5f..afda07d8c7d 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.AssemblyResolution.targets @@ -90,6 +90,7 @@ _ResolveAssemblies MSBuild target. <_AdditionalProperties> _ComputeFilesToPublishForRuntimeIdentifiers=true ;SelfContained=true + ;DesignTimeBuild=$(DesignTimeBuild) ;AppendRuntimeIdentifierToOutputPath=true ;ResolveAssemblyReferencesFindRelatedSatellites=false ;SkipCompilerExecution=true @@ -105,6 +106,7 @@ _ResolveAssemblies MSBuild target. <_ProjectToBuild Include="$(MSBuildProjectFile)" AdditionalProperties="RuntimeIdentifier=%(_RIDs.Identity);$(_AdditionalProperties)" /> diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets index ee627e65d03..e9f450b2398 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets @@ -112,14 +112,9 @@ properties that determine build ordering. $(CoreResolveReferencesDependsOn); UpdateAndroidResources; - _BuildResourceDesigner; UpdateAndroidInterfaceProxies; _CheckForInvalidDesignerConfig; - - $(DesignTimeResolveAssemblyReferencesDependsOn); - _BuildResourceDesigner; - <_UpdateAndroidResourcesDependsOn> $(CoreResolveReferencesDependsOn); _CreatePropertiesCache; @@ -127,7 +122,6 @@ properties that determine build ordering. _ComputeAndroidResourcePaths; _UpdateAndroidResgen; _CreateAar; - _BuildResourceDesigner; _SetupMSBuildAllProjects; @@ -142,9 +136,9 @@ properties that determine build ordering. _CollectGeneratedManagedBindingFiles; _ClearGeneratedManagedBindings; AddBindingsToCompile; + $(CompileDependsOn); _BuildResourceDesigner; _AddResourceDesignerFiles; - $(CompileDependsOn); _CheckAndroidHttpClientHandlerType; diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets index 149c3ae323b..995fe2368c6 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets @@ -27,6 +27,7 @@ - + diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs index bf6aa0563aa..fff2ed70673 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs @@ -6,6 +6,8 @@ using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Microsoft.Android.Build.Tasks; +using Xamarin.Android.Tools; +using Xamarin.Tools.Zip; namespace Xamarin.Android.Tasks { @@ -22,6 +24,8 @@ public class GenerateResourceCaseMap : AndroidTask public ITaskItem[] AdditionalResourceDirectories { get; set; } + public string[] AarLibraries { get; set; } + [Required] public ITaskItem OutputFile { get; set; } @@ -64,6 +68,39 @@ public override bool RunTask () AddRename (tok [1].Replace ('/', Path.DirectorySeparatorChar), tok [0].Replace ('/', Path.DirectorySeparatorChar)); } } + var resmap = ".net/__res_name_case_map.txt"; + foreach (var aar in AarLibraries ?? Array.Empty()) { + Log.LogDebugMessage ($"Processing Aar file {aar}"); + if (!File.Exists (aar)) { + Log.LogDebugMessage ($"Skipping non-existent aar: {aar}"); + continue; + } + using (var file = File.OpenRead (aar)) { + using var zip = ZipArchive.Open (file); + if (!zip.ContainsEntry (resmap)) { + Log.LogDebugMessage ($"Skipping non-existent file: {resmap}"); + continue; + } + ZipEntry entry = zip.ReadEntry (resmap); + Log.LogDebugMessage ($"Found: {entry.FullName}"); + var ms = MemoryStreamPool.Shared.Rent (); + try { + entry.Extract (ms); + ms.Position = 0; + using var reader = new StreamReader (ms); + string line; + // Read each line until the end of the file + while ((line = reader.ReadLine()) != null) { + if (string.IsNullOrEmpty (line)) + continue; + string [] tok = line.Split (';'); + AddRename (tok [1].Replace ('/', Path.DirectorySeparatorChar), tok [0].Replace ('/', Path.DirectorySeparatorChar)); + } + } finally { + MemoryStreamPool.Shared.Return (ms); + } + } + } if (MonoAndroidHelper.SaveMapFile (BuildEngine4, Path.GetFullPath (OutputFile.ItemSpec), resource_fixup)) { Log.LogDebugMessage ($"Writing to: {OutputFile.ItemSpec}"); diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs index 563318d357c..5de36f9cd7c 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateRtxt.cs @@ -17,6 +17,8 @@ public class GenerateRtxt : AndroidTask public string ResourceDirectory { get; set; } public string[] AdditionalResourceDirectories { get; set; } + public string[] AarLibraries { get; set; } + public string JavaPlatformJarPath { get; set; } public string ResourceFlagFile { get; set; } @@ -31,7 +33,7 @@ public override bool RunTask () var javaPlatformDirectory = string.IsNullOrEmpty (JavaPlatformJarPath) ? "" : Path.GetDirectoryName (JavaPlatformJarPath); var parser = new FileResourceParser () { Log = Log, JavaPlatformDirectory = javaPlatformDirectory, ResourceFlagFile = ResourceFlagFile}; - var resources = parser.Parse (ResourceDirectory, AdditionalResourceDirectories, resource_fixup); + var resources = parser.Parse (ResourceDirectory, AdditionalResourceDirectories, AarLibraries, resource_fixup); // only update if it changed. writer.Write (RTxtFile, resources); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs index 47f6c3dbff5..48c1ed3685b 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BuildTest.cs @@ -752,6 +752,7 @@ public void BuildAfterUpgradingNuget () } [Test] + [Category ("SmokeTests")] public void BuildInDesignTimeMode ([Values(false, true)] bool useManagedParser) { var proj = new XamarinAndroidApplicationProject () { @@ -762,20 +763,20 @@ public void BuildInDesignTimeMode ([Values(false, true)] bool useManagedParser) builder.Target = "UpdateAndroidResources"; 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."); + Assert.IsFalse (builder.Output.IsTargetSkipped ("_GenerateRtxt"), "target \"_GenerateRtxt\' should have been run."); var intermediate = Path.Combine (Root, builder.ProjectDirectory, proj.IntermediateOutputPath); - var librarycache = Path.Combine (intermediate, "designtime", "libraryprojectimports.cache"); - Assert.IsTrue (File.Exists (librarycache), $"'{librarycache}' should exist."); - librarycache = Path.Combine (intermediate, "libraryprojectimports.cache"); - Assert.IsFalse (File.Exists (librarycache), $"'{librarycache}' should not exist."); + var rTxtFile = Path.Combine (intermediate, "designtime", "R.txt"); + Assert.IsTrue (File.Exists (rTxtFile), $"'{rTxtFile}' should exist."); + rTxtFile = Path.Combine (intermediate, "R.txt"); + Assert.IsFalse (File.Exists (rTxtFile), $"'{rTxtFile}' should not exist."); builder.Build (proj, parameters: new string[] { "DesignTimeBuild=true" }); Assert.IsFalse (builder.Output.IsTargetSkipped ("_CreatePropertiesCache"), "target \"_CreatePropertiesCache\" should have been run."); - Assert.IsTrue (builder.Output.IsTargetSkipped ("_ResolveLibraryProjectImports"), "target \"_ResolveLibraryProjectImports\' should have been skipped."); + Assert.IsTrue (builder.Output.IsTargetSkipped ("_GenerateRtxt"), "target \"_GenerateRtxt\' should have been skipped."); Assert.IsTrue (builder.Clean (proj), "Clean Should have succeeded"); builder.Target = "_CleanDesignTimeIntermediateDir"; Assert.IsTrue (builder.Build (proj), "_CleanDesignTimeIntermediateDir should have succeeded"); - librarycache = Path.Combine (intermediate, "designtime", "libraryprojectimports.cache"); - Assert.IsFalse (File.Exists (librarycache), $"'{librarycache}' should not exist."); + rTxtFile = Path.Combine (intermediate, "designtime", "R.txt"); + Assert.IsFalse (File.Exists (rTxtFile), $"'{rTxtFile}' should not exist."); } } 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 75f45a1d833..32b79d45e83 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 @@ -1199,17 +1199,26 @@ public void DesignTimeBuild () { var proj = new XamarinAndroidApplicationProject (); using (var b = CreateApkBuilder (Path.Combine ("temp", $"{nameof (IncrementalBuildTest)}{TestName}"))) { + b.BuildLogFile = "dtb1.log"; Assert.IsTrue (b.DesignTimeBuild (proj), "first dtb should have succeeded."); - var target = "_ResolveLibraryProjectImports"; + var target = "_GenerateResourceDesignerAssembly"; Assert.IsFalse (b.Output.IsTargetSkipped (target), $"`{target}` should not have been skipped."); + var importsTarget = "_ResolveLibraryProjectImports"; + Assert.IsTrue (b.Output.IsTargetSkipped (importsTarget, defaultIfNotUsed: true), $"`{importsTarget}` should have been skipped."); // DesignTimeBuild=true lowercased var parameters = new [] { "DesignTimeBuild=true" }; + b.BuildLogFile = "compile.log"; Assert.IsTrue (b.RunTarget (proj, "Compile", doNotCleanupOnUpdate: true, parameters: parameters), "second dtb should have succeeded."); - Assert.IsTrue (b.Output.IsTargetSkipped (target), $"`{target}` should have been skipped."); + Assert.IsTrue (b.Output.IsTargetSkipped (target, defaultIfNotUsed: true), $"`{target}` should have been skipped."); + Assert.IsTrue (b.Output.IsTargetSkipped (importsTarget, defaultIfNotUsed: true), $"`{importsTarget}` should have been skipped."); + b.BuildLogFile = "updategeneratedfiles.log"; 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.Output.IsTargetSkipped (target, defaultIfNotUsed: true), $"`{target}` should have been skipped."); + Assert.IsTrue (b.Output.IsTargetSkipped (importsTarget, defaultIfNotUsed: true), $"`{importsTarget}` should have been skipped."); + b.BuildLogFile = "build.log"; 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."); + Assert.IsFalse (b.Output.IsTargetSkipped (importsTarget), $"`{importsTarget}` should not have been skipped."); } } @@ -1234,7 +1243,7 @@ public void DesignTimeBuildSignAndroidPackage () Assert.IsTrue (builder.RunTarget (proj, "SignAndroidPackage", parameters: parameters), $"{proj.ProjectName} should succeed"); builder.Output.AssertTargetIsNotSkipped ("_GenerateResourceCaseMap", occurrence: 2); builder.Output.AssertTargetIsSkipped ("_GenerateRtxt", occurrence: 1); - builder.Output.AssertTargetIsSkipped ("_GenerateResourceDesignerIntermediateClass", occurrence: 1); + builder.Output.AssertTargetIsNotSkipped ("_GenerateResourceDesignerIntermediateClass"); builder.Output.AssertTargetIsSkipped ("_GenerateResourceDesignerAssembly", occurrence: 2); builder.BuildLogFile = "build2.log"; Assert.IsTrue (builder.RunTarget (proj, "SignAndroidPackage", parameters: parameters), $"{proj.ProjectName} should succeed 2"); diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs index cfac54ddb42..709ae2a7dd8 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs @@ -1,5 +1,6 @@ using System; using System.CodeDom; +using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Linq; @@ -11,6 +12,7 @@ using System.Text.RegularExpressions; using Microsoft.Build.Utilities; using Microsoft.Android.Build.Tasks; +using Xamarin.Tools.Zip; namespace Xamarin.Android.Tasks { @@ -43,7 +45,7 @@ protected XDocument LoadPublicXml () { return null; } - public IList Parse (string resourceDirectory, IEnumerable additionalResourceDirectories, Dictionary resourceMap) + public IList Parse (string resourceDirectory, IEnumerable additionalResourceDirectories, IEnumerable aarLibraries, Dictionary resourceMap) { Log.LogDebugMessage ($"Parsing Directory {resourceDirectory}"); publicXml = LoadPublicXml (); @@ -71,6 +73,38 @@ public IList Parse (string resourceDirectory, IEnumerable additionalR Log.LogDebugMessage ($"Skipping non-existent directory: {dir}"); } } + foreach (var aar in aarLibraries ?? Array.Empty()) { + Log.LogDebugMessage ($"Processing Aar file {aar}"); + if (!File.Exists (aar)) { + Log.LogDebugMessage ($"Skipping non-existent aar: {aar}"); + continue; + } + using (var file = File.Open (aar, FileMode.Open, FileAccess.ReadWrite, FileShare.Read)) { + using var zip = ZipArchive.Open (file); + foreach (var entry in zip) { + if (entry.IsDirectory) + continue; + if (!entry.FullName.StartsWith ("res")) + continue; + var ext = Path.GetExtension (entry.FullName); + var path = Directory.GetParent (entry.FullName).Name; + if (ext == ".xml" || ext == ".axml") { + if (string.Compare (path, "raw", StringComparison.OrdinalIgnoreCase) != 0) { + var ms = MemoryStreamPool.Shared.Rent (); + try { + entry.Extract (ms); + ms.Position = 0; + using XmlReader reader = XmlReader.Create (ms); + ProcessXmlFile (reader, resources); + } finally { + MemoryStreamPool.Shared.Return (ms); + } + } + } + ProcessResourceFile (entry.FullName, resources, processXml: false); + } + } + } // now generate the Id's we need in a specific order List declarationIds = new List (); @@ -172,7 +206,7 @@ int GetId (ICollection resources, string identifier) return -1; } - void ProcessResourceFile (string file, Dictionary> resources) + void ProcessResourceFile (string file, Dictionary> resources, bool processXml = true) { Log.LogDebugMessage ($"{nameof(ProcessResourceFile)} {file}"); var fileName = Path.GetFileNameWithoutExtension (file); @@ -181,6 +215,10 @@ void ProcessResourceFile (string file, Dictionary> resour if (fileName.EndsWith (".9", StringComparison.OrdinalIgnoreCase)) fileName = Path.GetFileNameWithoutExtension (fileName); var path = Directory.GetParent (file).Name; + if (!processXml) { + CreateResourceField (path, fileName, resources); + return; + } var ext = Path.GetExtension (file); switch (ext) { case ".xml": @@ -299,8 +337,6 @@ void ProcessStyleable (XmlReader reader, Dictionary> reso fields.Add (r); } } - if (field.Type != RType.Array) - return; arrayMapping.Add (field, fields.ToArray ()); field.Ids = new int [attribs.Count]; @@ -321,72 +357,81 @@ resources [field.ResourceTypeName].Add (new R () { void ProcessXmlFile (string file, Dictionary> resources) { - Log.LogDebugMessage ($"{nameof(ProcessXmlFile)}"); using (var reader = XmlReader.Create (file)) { - while (reader.Read ()) { - if (reader.NodeType == XmlNodeType.Whitespace || reader.NodeType == XmlNodeType.Comment) - continue; - if (reader.IsStartElement ()) { - var elementName = reader.Name; - var elementNS = reader.NamespaceURI; - if (!string.IsNullOrEmpty (elementNS)) { - if (elementNS != "http://schemas.android.com/apk/res/android") - continue; - } - if (elementName == "declare-styleable" || elementName == "configVarying" || elementName == "add-resource") { - ProcessStyleable (reader.ReadSubtree (), resources); + ProcessXmlFile (reader, resources); + } + } + + void ProcessXmlFile (XmlReader reader, Dictionary> resources) + { + Log.LogDebugMessage ($"{nameof(ProcessXmlFile)}"); + while (reader.Read ()) { + if (reader.NodeType == XmlNodeType.Whitespace || reader.NodeType == XmlNodeType.Comment) + continue; + if (reader.IsStartElement ()) { + var elementName = reader.Name; + var elementNS = reader.NamespaceURI; + if (!string.IsNullOrEmpty (elementNS)) { + if (elementNS != "http://schemas.android.com/apk/res/android") continue; + } + if (elementName == "declare-styleable" || elementName == "configVarying" || elementName == "add-resource") { + try { + ProcessStyleable (reader.ReadSubtree (), resources); + } catch (Exception ex) { + Log.LogErrorFromException (ex); } - if (reader.HasAttributes) { - string name = null; - string type = null; - string id = null; - string custom_id = null; - while (reader.MoveToNextAttribute ()) { - if (reader.LocalName == "name") - name = reader.Value; - if (reader.LocalName == "type") - type = reader.Value; - if (reader.LocalName == "id") { - string[] values = reader.Value.Split ('/'); - if (values.Length != 2) { - id = reader.Value.Replace ("@+id/", "").Replace ("@id/", ""); - } else { - if (values [0] != "@+id" && values [0] != "@id" && !values [0].Contains ("android:")) { - custom_id = values [0].Replace ("@", "").Replace ("+", ""); - } - id = values [1]; + continue; + } + if (reader.HasAttributes) { + string name = null; + string type = null; + string id = null; + string custom_id = null; + while (reader.MoveToNextAttribute ()) { + if (reader.LocalName == "name") + name = reader.Value; + if (reader.LocalName == "type") + type = reader.Value; + if (reader.LocalName == "id") { + string[] values = reader.Value.Split ('/'); + if (values.Length != 2) { + id = reader.Value.Replace ("@+id/", "").Replace ("@id/", ""); + } else { + if (values [0] != "@+id" && values [0] != "@id" && !values [0].Contains ("android:")) { + custom_id = values [0].Replace ("@", "").Replace ("+", ""); } - - } - if (reader.LocalName == "inflatedId") { - string inflateId = reader.Value.Replace ("@+id/", "").Replace ("@id/", ""); - var r = new R () { - ResourceTypeName = "id", - Identifier = inflateId, - Id = -1, - }; - Log.LogDebugMessage ($"Adding 1 {r}"); - resources[r.ResourceTypeName].Add (r); + id = values [1]; } + } - if (name?.Contains ("android:") ?? false) - continue; - if (id?.Contains ("android:") ?? false) - continue; - // Move the reader back to the element node. - reader.MoveToElement (); - if (!string.IsNullOrEmpty (name)) { - CreateResourceField (type ?? elementName, name, resources); - } - if (!string.IsNullOrEmpty (custom_id) && !resources.ContainsKey (custom_id)) { - resources.Add (custom_id, new SortedSet (new RComparer ())); - custom_types.Add (custom_id); - } - if (!string.IsNullOrEmpty (id)) { - CreateResourceField (custom_id ?? "id", id.Replace ("-", "_").Replace (".", "_"), resources); + if (reader.LocalName == "inflatedId") { + string inflateId = reader.Value.Replace ("@+id/", "").Replace ("@id/", ""); + var r = new R () { + ResourceTypeName = "id", + Identifier = inflateId, + Id = -1, + }; + Log.LogDebugMessage ($"Adding 1 {r}"); + resources[r.ResourceTypeName].Add (r); } } + if (name?.Contains ("android:") ?? false) + continue; + if (id?.Contains ("android:") ?? false) + continue; + // Move the reader back to the element node. + reader.MoveToElement (); + if (!string.IsNullOrEmpty (name)) { + CreateResourceField (type ?? elementName, name, resources); + } + if (!string.IsNullOrEmpty (custom_id) && !resources.ContainsKey (custom_id)) { + resources.Add (custom_id, new SortedSet (new RComparer ())); + custom_types.Add (custom_id); + } + if (!string.IsNullOrEmpty (id)) { + CreateResourceField (custom_id ?? "id", id.Replace ("-", "_").Replace (".", "_"), resources); + } } } } diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index b5c7c6c7c78..6d8b720066b 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -118,7 +118,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. --> + Condition="Exists('$(MSBuildThisFileDirectory)Xamarin.Installer.Common.props') And '$(DesignTimeBuild)' != 'true'"/> @@ -361,7 +361,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. - + @@ -2865,14 +2865,14 @@ because xbuild doesn't support framework reference assemblies. + Condition="Exists('$(MSBuildThisFileDirectory)Xamarin.Android.Common.Debugging.targets') And '$(DesignTimeBuild)' != 'true' "/> + Condition="Exists('$(MSBuildThisFileDirectory)Xamarin.Installer.Common.targets') And '$(DesignTimeBuild)' != 'true' "/> <_DesignTimeAarFiles Include="@(AndroidAarLibrary)" Condition=" '@(LibraryResourceDirectories->Count())' == '0' " /> + <_DesignTimeAarFiles Include="@(LibraryProjectZip)" Condition="'%(LibraryProjectZip.Extension)' == '.aar' and '@(LibraryResourceDirectories->Count())' == '0'" /> diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets index e9f450b2398..f54dd4f15d6 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.BuildOrder.targets @@ -165,6 +165,7 @@ properties that determine build ordering. _ResolveMonoAndroidSdks; + ResolveAssemblyReferences; _ExtractLibraryProjectImports; _GetLibraryImports; _ExtractAar; diff --git a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs index 0596ab61238..fe617657044 100644 --- a/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs +++ b/src/Xamarin.Android.Build.Tasks/Tasks/GenerateResourceCaseMap.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Text; using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Microsoft.Android.Build.Tasks; @@ -90,7 +91,7 @@ public override bool RunTask () entryStream.CopyTo (ms); } ms.Position = 0; - using (var reader = new StreamReader (ms)) { + using (var reader = new StreamReader (ms, Encoding.UTF8, detectEncodingFromByteOrderMarks: true, bufferSize: -1, leaveOpen: true)) { string line; // Read each line until the end of the file while ((line = reader.ReadLine()) != null) { diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs index 14e72a467b4..483cf4a7848 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs @@ -547,7 +547,7 @@ public void DesignTimeBuild (string classParser) var assemblyFile = Path.Combine (intermediate, proj.ProjectName + ".dll"); using (var assembly = AssemblyDefinition.ReadAssembly (assemblyFile)) { var typeName = "Com.Balysv.Material.Drawable.Menu.MaterialMenuView"; - Assert.IsTrue (assembly.MainModule.Types.Any (t => t.FullName == typeName), $"Type `{typeName}` should exist!"); + Assert.IsTrue (assembly.MainModule.Types.Any (t => t.FullName == typeName), $"Type `{typeName}` should exist in '{assemblyFile}'!"); } } } diff --git a/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs b/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs index 5ea17225085..a5e75a0e4be 100644 --- a/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs +++ b/src/Xamarin.Android.Build.Tasks/Utilities/FileResourceParser.cs @@ -96,9 +96,8 @@ public IList Parse (string resourceDirectory, IEnumerable additionalR entryStream.CopyTo (ms); } ms.Position = 0; - using (XmlReader reader = XmlReader.Create (ms)) { - ProcessXmlFile (reader, resources); - } + using XmlReader reader = XmlReader.Create (ms); + ProcessXmlFile (reader, resources); } finally { MemoryStreamPool.Shared.Return (ms); } diff --git a/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs b/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs index cd9b19acd46..575c85a3dc6 100644 --- a/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs @@ -406,6 +406,7 @@ public void DesignTimeBuild_CSharp_From_Clean () proj.PackageReferences.Add (KnownPackages.AndroidXAppCompat); proj.MainActivity = proj.DefaultMainActivity; using (var builder = CreateBuilderWithoutLogFile ()) { + builder.ThrowOnBuildFailure = false; builder.BuildLogFile = "designtimebuild.log"; builder.Verbosity = LoggerVerbosity.Quiet; builder.Clean (proj); From 365a7b3df0bbececf7ded4aafac045beb7d5b156 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Mon, 20 Jan 2025 10:24:34 +0000 Subject: [PATCH 08/21] fix test. Deprecate AndroidUseManagedDesignTimeResourceGenerator --- .../Xamarin.Android.Common.targets | 5 +++++ .../Xamarin.Android.EmbeddedResource.targets | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 6d8b720066b..279093f49a6 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -548,6 +548,11 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. FormatArguments="AndroidFastDeploymentType;9" Condition=" '$(AndroidFastDeploymentType)' != '' " /> + From 24e5ff38acf6b0def6bcb3099c5ac12d03656ff4 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Mon, 20 Jan 2025 11:41:50 +0000 Subject: [PATCH 09/21] Remove the warnings --- .../Xamarin.Android.Common.targets | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 279093f49a6..6d8b720066b 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -548,11 +548,6 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. FormatArguments="AndroidFastDeploymentType;9" Condition=" '$(AndroidFastDeploymentType)' != '' " /> - Date: Mon, 20 Jan 2025 14:05:08 +0000 Subject: [PATCH 10/21] Exlucde more targets for DTB --- .../targets/Microsoft.Android.Sdk.targets | 5 ++--- .../Xamarin.Android.Common.targets | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets index 995fe2368c6..6e163284cc8 100644 --- a/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets +++ b/src/Xamarin.Android.Build.Tasks/Microsoft.Android.Sdk/targets/Microsoft.Android.Sdk.targets @@ -26,8 +26,7 @@ - + Condition="Exists('$(MSBuildThisFileDirectory)..\tools\Xamarin.Android.Common.Debugging.props') And '$(DesignTimeBuild)' != 'true' "/> + diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index 6d8b720066b..afd49782410 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -364,7 +364,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. - + From 667db9230b91456a05541dac3627b214eb3bab2f Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Mon, 20 Jan 2025 17:54:08 +0000 Subject: [PATCH 11/21] Add more iterations for some Performance tests --- .../Common/ProjectBuilder.cs | 7 ++-- .../Tests/PerformanceTest.cs | 34 ++++++++++++++----- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs index 514c16f7312..c601a43d897 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/ProjectBuilder.cs @@ -101,11 +101,12 @@ public bool UpdateAndroidResources (XamarinProject project, bool doNotCleanupOnU public bool DesignTimeBuild (XamarinProject project, string target = "Compile", bool doNotCleanupOnUpdate = false, string [] parameters = null) { if (parameters == null) { - return RunTarget (project, target, doNotCleanupOnUpdate, parameters: new string [] { "DesignTimeBuild=True" }); + return RunTarget (project, target, doNotCleanupOnUpdate, parameters: new string [] { "DesignTimeBuild=True", "SkipCompilerExecution=true" }); } else { - var designTimeParameters = new string [parameters.Length + 1]; + var designTimeParameters = new string [parameters.Length + 2]; parameters.CopyTo (designTimeParameters, 0); - designTimeParameters [parameters.Length] = "DesignTimeBuild=True"; + designTimeParameters [designTimeParameters.Length - 2] = "DesignTimeBuild=True"; + designTimeParameters [designTimeParameters.Length - 1] = "SkipCompilerExecution=true"; return RunTarget (project, target, doNotCleanupOnUpdate, parameters: designTimeParameters); } } diff --git a/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs b/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs index 575c85a3dc6..33e5ee502ae 100644 --- a/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs @@ -11,6 +11,7 @@ namespace Xamarin.Android.Build.Tests { [TestFixture] + [Category ("Performance")] public class PerformanceTest : DeviceTest { const int Retry = 2; @@ -45,16 +46,29 @@ public static void Setup () } void Profile (ProjectBuilder builder, Action action, [CallerMemberName] string caller = null) + { + Profile (builder, iterations: 1, action: action, caller: caller); + } + + void Profile (ProjectBuilder builder, int iterations, Action action, Action afterRun = null, [CallerMemberName] string caller = null) { if (!csv_values.TryGetValue (caller, out int expected)) { Assert.Fail ($"No timeout value found for a key of {caller}"); } - action (builder); - var actual = GetDurationFromBinLog (builder); - TestContext.Out.WriteLine($"expected: {expected}ms, actual: {actual}ms"); - if (actual > expected) { - Assert.Fail ($"Exceeded expected time of {expected}ms, actual {actual}ms"); + double total = 0; + for (int i=0; i < iterations; i++) { + action (builder); + var actual = GetDurationFromBinLog (builder); + TestContext.Out.WriteLine($"run {i} took: {actual}ms"); + total += actual; + if (afterRun is not null) + afterRun (builder); + } + total /= iterations; + TestContext.Out.WriteLine($"expected: {expected}ms, actual: {total}ms"); + if (total > expected) { + Assert.Fail ($"Exceeded expected time of {expected}ms, actual {total}ms"); } } @@ -346,9 +360,9 @@ public void Build_XAML_Change ([Values (true, false)] bool install) lib.Touch ("MyPage.xaml"); libBuilder.Build (lib, doNotCleanupOnUpdate: true); if (install) { - Profile (appBuilder, b => b.Install (app, doNotCleanupOnUpdate: true), caller); + Profile (appBuilder, b => b.Install (app, doNotCleanupOnUpdate: true), caller: caller); } else { - Profile (appBuilder, b => b.Build (app, doNotCleanupOnUpdate: true), caller); + Profile (appBuilder, b => b.Build (app, doNotCleanupOnUpdate: true), caller: caller); } } } @@ -412,8 +426,10 @@ public void DesignTimeBuild_CSharp_From_Clean () builder.Clean (proj); builder.Restore (proj); builder.AutomaticNuGetRestore = false; - Profile (builder, b => { - b.DesignTimeBuild (proj, "CoreCompile", parameters: new string[] { "BuildingInsideVisualStudio=true", "SkipCompilerExecution=true" }); + Profile (builder, iterations: 10, action: b => { + b.DesignTimeBuild (proj, "CoreCompile", parameters: new string[] { "BuildingInsideVisualStudio=true" }); + }, afterRun: b => { + b.Clean (proj); }); } } From b4a1b2fc79d94dcf64d0a06b89b3991d04f748a6 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 21 Jan 2025 08:31:53 +0000 Subject: [PATCH 12/21] We need javac.targets for DTB --- src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets index afd49782410..6d8b720066b 100644 --- a/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets +++ b/src/Xamarin.Android.Build.Tasks/Xamarin.Android.Common.targets @@ -364,7 +364,7 @@ Copyright (C) 2011-2012 Xamarin. All rights reserved. - + From c77c8cc37ce94138c917eeb1a79a108e7bc5a7e3 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 21 Jan 2025 09:34:18 +0000 Subject: [PATCH 13/21] Fix test to not look for a .dll as they are not built for DTB now --- .../Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs index 483cf4a7848..7e7b749df8f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/BindingBuildTest.cs @@ -544,11 +544,8 @@ public void DesignTimeBuild (string classParser) Assert.IsNotNull (element, "api.xml should contain an `api` element!"); Assert.IsTrue (element.HasElements, "api.xml should contain elements!"); - var assemblyFile = Path.Combine (intermediate, proj.ProjectName + ".dll"); - using (var assembly = AssemblyDefinition.ReadAssembly (assemblyFile)) { - var typeName = "Com.Balysv.Material.Drawable.Menu.MaterialMenuView"; - Assert.IsTrue (assembly.MainModule.Types.Any (t => t.FullName == typeName), $"Type `{typeName}` should exist in '{assemblyFile}'!"); - } + var sourceFile = Path.Combine (intermediate, "generated", "src", "Com.Balysv.Material.Drawable.Menu.MaterialMenuView.cs"); + FileAssert.Exists (sourceFile, $"'{sourceFile}' should have been generated."); } } From b59785ee4ce37b64347e70217e869d44e0702d67 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 21 Jan 2025 13:07:33 +0000 Subject: [PATCH 14/21] Fix test --- .../Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs index 07e6be2bf72..4b3dfa5594a 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/AndroidUpdateResourcesTest.cs @@ -1029,7 +1029,7 @@ public void BuildAppWithManagedResourceParserAndLibraries () Assert.LessOrEqual (libBuilder.LastBuildTime.TotalMilliseconds, maxBuildTimeMs, $"DesignTime build should be less than {maxBuildTimeMs} milliseconds."); Assert.IsFalse (libProj.CreateBuildOutput (libBuilder).IsTargetSkipped ("_ManagedUpdateAndroidResgen"), "Target '_ManagedUpdateAndroidResgen' should have run."); - Assert.IsFalse (appBuilder.DesignTimeBuild (appProj), "Application project should have built"); + Assert.IsTrue (appBuilder.DesignTimeBuild (appProj), "Application project should have built"); 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."); From f0f00691c43321cf2d3b808b0348536eaf18a861 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 21 Jan 2025 13:56:47 +0000 Subject: [PATCH 15/21] add logging --- .../Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs index 52f4a8ba835..4c4e938e092 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs @@ -148,7 +148,12 @@ public static bool UseLocalBuildOutput { } } - public static bool CommercialBuildAvailable => File.Exists (Path.Combine (AndroidMSBuildDirectory, "Xamarin.Android.Common.Debugging.targets")); + public static bool CommercialBuildAvailable { + get { + Console.WriteLine ("DEBUG! checking `{AndroidMSBuildDirectory}` for `Xamarin.Android.Common.Debugging.targets`.") + return File.Exists (Path.Combine (AndroidMSBuildDirectory, "Xamarin.Android.Common.Debugging.targets")); + } + } public static string OSBinDirectory { get { From b294794a812673be30d3848930b1278069d034fd Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 21 Jan 2025 14:42:14 +0000 Subject: [PATCH 16/21] add logging --- .../Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs index 4c4e938e092..812223e5c03 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs @@ -150,7 +150,7 @@ public static bool UseLocalBuildOutput { public static bool CommercialBuildAvailable { get { - Console.WriteLine ("DEBUG! checking `{AndroidMSBuildDirectory}` for `Xamarin.Android.Common.Debugging.targets`.") + Console.WriteLine ("DEBUG! checking `{AndroidMSBuildDirectory}` for `Xamarin.Android.Common.Debugging.targets`."); return File.Exists (Path.Combine (AndroidMSBuildDirectory, "Xamarin.Android.Common.Debugging.targets")); } } From acfbaf5bc4f5fc983fb23370f489ede1a3c3aa1e Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 21 Jan 2025 15:23:17 +0000 Subject: [PATCH 17/21] try this --- .../Xamarin.Android.Build.Tests/Utilities/BaseTest.cs | 4 +++- .../Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs | 9 +++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs index 1ce0280f232..1d3d5dca3fe 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/Utilities/BaseTest.cs @@ -35,7 +35,9 @@ public void AssertCommercialBuild (bool fail = false) { if (!TestEnvironment.CommercialBuildAvailable) { var message = $"'{TestName}' requires a commercial build of .NET for Android."; - if (fail) { + var runningOnCI = false; + bool.TryParse (Environment.GetEnvironmentVariable ("RunningOnCI"), out runningOnCI); + if (fail || runningOnCI) { Assert.Fail (message); } else { Assert.Ignore (message); diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs index 812223e5c03..a52ce07494f 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs @@ -150,8 +150,13 @@ public static bool UseLocalBuildOutput { public static bool CommercialBuildAvailable { get { - Console.WriteLine ("DEBUG! checking `{AndroidMSBuildDirectory}` for `Xamarin.Android.Common.Debugging.targets`."); - return File.Exists (Path.Combine (AndroidMSBuildDirectory, "Xamarin.Android.Common.Debugging.targets")); + var result = File.Exists (Path.Combine (AndroidMSBuildDirectory, "Xamarin.Android.Common.Debugging.targets")); + Console.WriteLine ($"DEBUG! checking `{AndroidMSBuildDirectory}` for `Xamarin.Android.Common.Debugging.targets`: {result}."); + if (!result) { + Console.WriteLine ($"DEBUG! checking `{LocalDotNetAndroidSdkDirectory}\tools` for `Xamarin.Android.Common.Debugging.targets`: {result}."); + result = File.Exists (Path.Combine (LocalDotNetAndroidSdkDirectory, "tools", "Xamarin.Android.Common.Debugging.targets")); + } + return result; } } From dbd059dff118c02d3254b5981e83c357a115e8f6 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 21 Jan 2025 16:00:29 +0000 Subject: [PATCH 18/21] try this --- .../Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs index a52ce07494f..5056f233127 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs @@ -153,8 +153,8 @@ public static bool CommercialBuildAvailable { var result = File.Exists (Path.Combine (AndroidMSBuildDirectory, "Xamarin.Android.Common.Debugging.targets")); Console.WriteLine ($"DEBUG! checking `{AndroidMSBuildDirectory}` for `Xamarin.Android.Common.Debugging.targets`: {result}."); if (!result) { - Console.WriteLine ($"DEBUG! checking `{LocalDotNetAndroidSdkDirectory}\tools` for `Xamarin.Android.Common.Debugging.targets`: {result}."); result = File.Exists (Path.Combine (LocalDotNetAndroidSdkDirectory, "tools", "Xamarin.Android.Common.Debugging.targets")); + Console.WriteLine ($"DEBUG! checking `{LocalDotNetAndroidSdkDirectory}/tools` for `Xamarin.Android.Common.Debugging.targets`: {result}."); } return result; } From af057a507fdc42f4d1131458f36ba16e75b8340e Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 21 Jan 2025 16:13:06 +0000 Subject: [PATCH 19/21] Remove Performance Category --- tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs b/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs index 33e5ee502ae..755c9c8e122 100644 --- a/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs +++ b/tests/MSBuildDeviceIntegration/Tests/PerformanceTest.cs @@ -11,7 +11,7 @@ namespace Xamarin.Android.Build.Tests { [TestFixture] - [Category ("Performance")] + //[Category ("Performance")] public class PerformanceTest : DeviceTest { const int Retry = 2; From 6cde7b5c267a90bed17d3bbbaf2307417bc1e541 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 21 Jan 2025 18:58:21 +0000 Subject: [PATCH 20/21] Add env: --- build-tools/automation/yaml-templates/run-nunit-tests.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build-tools/automation/yaml-templates/run-nunit-tests.yaml b/build-tools/automation/yaml-templates/run-nunit-tests.yaml index 790abf3b7b2..ffa6098ac8b 100644 --- a/build-tools/automation/yaml-templates/run-nunit-tests.yaml +++ b/build-tools/automation/yaml-templates/run-nunit-tests.yaml @@ -21,5 +21,7 @@ steps: continueOnError: true timeoutInMinutes: ${{ parameters.timeoutInMinutes }} retryCountOnTaskFailure: ${{ parameters.retryCountOnTaskFailure }} + env: + RunningOnCI: true - template: /build-tools/automation/yaml-templates/kill-processes.yaml From c71d8d90e69bdfd86b80feff86b7fbb4bfc34416 Mon Sep 17 00:00:00 2001 From: Dean Ellis Date: Tue, 21 Jan 2025 20:34:35 +0000 Subject: [PATCH 21/21] ff --- .../Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs index 5056f233127..52768ef77db 100644 --- a/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs +++ b/src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Common/TestEnvironment.cs @@ -125,14 +125,20 @@ static string GetDotNetAndroidSdkDir (string packsDirectory) "Microsoft.Android.Sdk.Linux"; var sdkDir = Path.Combine (packsDirectory, sdkName); - if (!Directory.Exists (sdkDir)) + if (!Directory.Exists (sdkDir)) { + Console.WriteLine ($"Unable to locate a Microsoft.Android.Sdk in '{sdkDir}'."); return string.Empty; + } var dirs = from d in Directory.GetDirectories (sdkDir) let version = ParseVersion (d) orderby version descending select d; + foreach (var dir in dirs) { + Console.WriteLine ($"DEBUG! found'{dir}'."); + } + return dirs.FirstOrDefault (); }