Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] skip XA1034 logic in some cases (dotnet…
Browse files Browse the repository at this point in the history
…#7680)

After profiling a build for a `dotnet new maui` app, I noticed:

    193.41ms xamarin.android.build.tasks!Xamarin.Android.Tasks.MonoAndroidHelper.HasResourceDesignerAssemblyReference()

Which equates to:

    Top 10 most expensive tasks
    ...
    AppendCustomMetadataToItemGroup = 204 ms

In dc3ccf2, we added this check to emit `XA1034` when
`$(AndroidUseDesignerAssembly)` is false. And so we don't actually
need to validate this value when it is `true` (the default).

I moved the logic from the `<AppendCustomMetadataToItemGroup/>`
MSBuild task to a new `<CheckForInvalidDesignerConfig/>` task. In most
projects, it will be completely skipped:

    Target "_CheckForInvalidDesignerConfig" skipped, due to false condition; ( '$(AndroidUseDesignerAssembly)' != 'True' ) was evaluated as ( 'true' != 'True' ).

After these changes, I get a much better number in projects with
default settings:

    AppendCustomMetadataToItemGroup = 2 ms

Just by moving the task around, it is faster in general:

    CheckForInvalidDesignerConfig = 11 ms

This is due to less assemblies passed in than before:

    Assemblies="@(_MonoAndroidReferencePath);@(_MonoAndroidReferenceDependencyPaths)"

While previously, we were checking *all* assemblies.
  • Loading branch information
jonathanpeppers authored Jan 11, 2023
1 parent c92ae5e commit 8c24b8f
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ Copyright (C) 2016 Xamarin. All rights reserved.
<UsingTask TaskName="Xamarin.Android.Tasks.GenerateResourceDesignerAssembly" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
<UsingTask TaskName="Xamarin.Android.Tasks.GenerateResourceCaseMap" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
<UsingTask TaskName="Xamarin.Android.Tasks.GenerateRtxt" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />
<UsingTask TaskName="Xamarin.Android.Tasks.CheckForInvalidDesignerConfig" AssemblyFile="Xamarin.Android.Build.Tasks.dll" />

<PropertyGroup>
<AndroidUseDesignerAssembly Condition=" '$(AndroidUseDesignerAssembly)' == '' ">False</AndroidUseDesignerAssembly>
Expand Down Expand Up @@ -142,15 +143,7 @@ Copyright (C) 2016 Xamarin. All rights reserved.
<Target Name="_CheckForInvalidDesignerConfig"
Condition=" '$(AndroidUseDesignerAssembly)' != 'True' "
DependsOnTargets="_AddAndroidCustomMetaData">
<ItemGroup>
<_ErrorItems Include="@(_MonoAndroidReferencePath)" Condition=" '%(_MonoAndroidReferencePath.HasResourceDesignerAssemblyReference)' == 'True' "/>
<_ErrorItems Include="@(_MonoAndroidReferenceDependencyPaths)" Condition=" '%(_MonoAndroidReferenceDependencyPaths.HasResourceDesignerAssemblyReference)' == 'True' "/>
</ItemGroup>
<AndroidError Code="XA1034"
ResourceName="XA1034"
FormatArguments="%(_ErrorItems.FullPath)"
Condition=" '@(_ErrorItems->Count())' != '0' "
/>
<CheckForInvalidDesignerConfig Assemblies="@(_MonoAndroidReferencePath);@(_MonoAndroidReferenceDependencyPaths)" />
</Target>

<PropertyGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ public override bool RunTask ()
foreach (var item in Inputs) {
var fn = Path.GetFileNameWithoutExtension (item.ItemSpec);
output.Add (item);
var md = item.GetMetadata ("HasResourceDesignerAssemblyReference");
if (string.IsNullOrEmpty (md)) {
var b = MonoAndroidHelper.HasResourceDesignerAssemblyReference (item);
item.SetMetadata ("HasResourceDesignerAssemblyReference", MonoAndroidHelper.HasResourceDesignerAssemblyReference (item).ToString ());
}
List<ITaskItem> metaDataList;
if (!metaData.TryGetValue (fn, out metaDataList))
continue;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using Microsoft.Android.Build.Tasks;
using Microsoft.Build.Framework;
using Microsoft.Build.Utilities;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.IO;

namespace Xamarin.Android.Tasks
{
/// <summary>
/// Emits XA1034 is an assembly has a reference to _Microsoft.Android.Resource.Designer.dll
/// * NOTE: only called when $(AndroidUseDesignerAssembly) is false
/// </summary>
public class CheckForInvalidDesignerConfig : AndroidTask
{
public override string TaskPrefix => "CIRF";

public ITaskItem[] Assemblies { get; set; }

public override bool RunTask ()
{
if (Assemblies == null)
return true;

foreach (var assembly in Assemblies) {
if (HasResourceDesignerAssemblyReference (assembly)) {
Log.LogCodedError ("XA1034", Properties.Resources.XA1034, assembly);
}
}

return !Log.HasLoggedErrors;
}

static bool HasResourceDesignerAssemblyReference (ITaskItem assembly)
{
if (!File.Exists (assembly.ItemSpec)) {
return false;
}
using var pe = new PEReader (File.OpenRead (assembly.ItemSpec));
var reader = pe.GetMetadataReader ();
return HasResourceDesignerAssemblyReference (reader);
}

static bool HasResourceDesignerAssemblyReference (MetadataReader reader)
{
foreach (var handle in reader.AssemblyReferences) {
var reference = reader.GetAssemblyReference (handle);
var name = reader.GetString (reference.Name);
if (string.CompareOrdinal (name, "_Microsoft.Android.Resource.Designer") == 0) {
return true;
}
}
return false;
}
}
}
22 changes: 0 additions & 22 deletions src/Xamarin.Android.Build.Tasks/Utilities/MonoAndroidHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -325,28 +325,6 @@ public static bool HasMonoAndroidReference (MetadataReader reader)
return false;
}

public static bool HasResourceDesignerAssemblyReference (ITaskItem assembly)
{
if (!File.Exists (assembly.ItemSpec)) {
return false;
}
using var pe = new PEReader (File.OpenRead (assembly.ItemSpec));
var reader = pe.GetMetadataReader ();
return HasResourceDesignerAssemblyReference (reader);
}

public static bool HasResourceDesignerAssemblyReference (MetadataReader reader)
{
foreach (var handle in reader.AssemblyReferences) {
var reference = reader.GetAssemblyReference (handle);
var name = reader.GetString (reference.Name);
if (string.CompareOrdinal (name, "_Microsoft.Android.Resource.Designer") == 0) {
return true;
}
}
return false;
}

public static bool IsReferenceAssembly (string assembly)
{
using (var stream = File.OpenRead (assembly))
Expand Down

0 comments on commit 8c24b8f

Please sign in to comment.