Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[net9-pre3] Enabling ILLink causes the build to fail on Application attribute #8914

Closed
tranb3r opened this issue Apr 30, 2024 · 4 comments · Fixed by #8936
Closed

[net9-pre3] Enabling ILLink causes the build to fail on Application attribute #8914

tranb3r opened this issue Apr 30, 2024 · 4 comments · Fixed by #8936
Assignees
Labels
Area: App+Library Build Issues when building Library projects or Application projects. needs-triage Issues that need to be assigned.

Comments

@tranb3r
Copy link

tranb3r commented Apr 30, 2024

Android application type

.NET Android (net7.0-android, net8.0-android, etc.)

Affected platform version

VS 17.10.0-pre5 / net9-pre3 / xamarin-android 34.99.0-pre3

Description

When building with TrimMode=full, the build fails with the following error:

ILLink : error IL1012: IL Trimmer has encountered an unexpected error. Please report the issue at https://aka.ms/report-illink 
  Fatal error in IL Linker
  Unhandled exception. System.InvalidOperationException: Sequence contains no matching element
     at System.Linq.ThrowHelper.ThrowNoMatchException()
     at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
     at MonoDroid.Tuner.PreserveApplications.PreserveTypeProperty(CustomAttribute attribute, String property) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 69
     at MonoDroid.Tuner.PreserveApplications.PreserveApplicationAttribute(CustomAttribute attribute) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 60
     at MonoDroid.Tuner.PreserveApplications.ProcessAttributeProvider(ICustomAttributeProvider provider) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 55
     at MonoDroid.Tuner.PreserveApplications.ProcessType(TypeDefinition type) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 43
     at MonoDroid.Tuner.PreserveApplications.<Initialize>b__0_1(TypeDefinition type) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 21
     at Mono.Linker.Steps.MarkStep.MarkType(TypeReference reference, DependencyInfo reason, Nullable`1 origin)
     at Mono.Linker.Steps.MarkStep.MarkTypeVisibleToReflection(TypeReference type, TypeDefinition definition, DependencyInfo& reason, MessageOrigin& origin)
     at Mono.Linker.Steps.MarkStep.MarkEntireType(TypeDefinition type, DependencyInfo& reason)
     at Mono.Linker.Steps.MarkStep.MarkEntireAssembly(AssemblyDefinition assembly)
     at Mono.Linker.Steps.MarkStep.MarkAssembly(AssemblyDefinition assembly, DependencyInfo reason)
     at Mono.Linker.Steps.MarkStep.MarkModule(ModuleDefinition module, DependencyInfo reason)
     at Mono.Linker.Steps.MarkStep.ProcessMarkedPending()
     at Mono.Linker.Steps.MarkStep.Initialize()
     at Mono.Linker.Steps.MarkStep.Process(LinkContext context)
     at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step)
     at Mono.Linker.Pipeline.Process(LinkContext context)
     at Mono.Linker.Driver.Run(ILogger customLogger)
     at Mono.Linker.Driver.Main(String[] args)
     at Mono.Linker.Driver.Main(String[] args)
c:\Nuget\microsoft.net.illink.tasks\9.0.0-preview.3.24172.9\build\Microsoft.NET.ILLink.targets(91,5): error NETSDK1144: Optimizing assemblies for size failed. 

Also, if I add null parameters to the Application attribute...

[global::Android.App.ApplicationAttribute(
        ...
        BackupAgent = null,
        ManageSpaceActivity = null
    )]

...it fails later on:

C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.99.0-preview.3.231\tools\Xamarin.Android.Common.targets(1460,3): error XAGJS7001: System.NullReferenceException: Object reference not set to an instance of an object.
   at Xamarin.Android.Manifest.ManifestDocumentElement.ResolveType(String type, ICustomAttributeProvider provider, IAssemblyResolver resolver)
   at Android.App.ApplicationAttribute.<>c.<.cctor>b__114_7(ApplicationAttribute self, ICustomAttributeProvider p, IAssemblyResolver r, TypeDefinitionCache cache)
   at Xamarin.Android.Manifest.ManifestDocumentElement`1.ToAttributeValue(String name, T value, ICustomAttributeProvider provider, IAssemblyResolver resolver, TypeDefinitionCache cache, Int32 targetSdkVersion)
   at Xamarin.Android.Manifest.ManifestDocumentElement`1.ToAttribute(String name, T value, String packageName, ICustomAttributeProvider provider, IAssemblyResolver resolver, TypeDefinitionCache cache, Int32 targetSdkVersion)
   at Xamarin.Android.Manifest.ManifestDocumentElement`1.<>c__DisplayClass8_0.<ToElement>b__1(String e)
   at System.Linq.Enumerable.IteratorSelectIterator`2.MoveNext()
   at System.Linq.Enumerable.IEnumerableWhereIterator`1.MoveNext()
   at System.Xml.Linq.XContainer.AddContentSkipNotify(Object content)
   at Xamarin.Android.Manifest.ManifestDocumentElement`1.ToElement(T value, ICollection`1 specified, String packageName, TypeDefinitionCache cache, ICustomAttributeProvider provider, IAssemblyResolver resolver, Int32 targetSdkVersion)
   at Android.App.ApplicationAttribute.ToElement(IAssemblyResolver resolver, String packageName, TypeDefinitionCache cache)
   at Xamarin.Android.Tasks.ManifestDocument.CreateApplicationElement(XElement manifest, String applicationClass, List`1 subclasses, TypeDefinitionCache cache)
   at Xamarin.Android.Tasks.ManifestDocument.Merge(TaskLoggingHelper log, TypeDefinitionCache cache, List`1 subclasses, String applicationClass, Boolean embed, String bundledWearApplicationName, IEnumerable`1 mergedManifestDocuments)
   at Xamarin.Android.Tasks.GenerateJavaStubs.MergeManifest(NativeCodeGenState codeGenState, Dictionary`2 userAssemblies)
   at Xamarin.Android.Tasks.GenerateJavaStubs.Run(Boolean useMarshalMethods)
   at Xamarin.Android.Tasks.GenerateJavaStubs.RunTask()
   at Microsoft.Android.Build.Tasks.AndroidTask.Execute() in /Users/runner/work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/AndroidTask.cs:line 25

No issue with the same csproj configuration, when using net8.

This similar to a net6 issue: #7301

Here are the binlog for both errors:
binlog.zip

Steps to Reproduce

Have a look at binlogs.

Did you find any workaround?

No response

Relevant log output

No response

@tranb3r tranb3r added Area: App+Library Build Issues when building Library projects or Application projects. needs-triage Issues that need to be assigned. labels Apr 30, 2024
@jonathanpeppers
Copy link
Member

Looking at the code here:
https://github.com/xamarin/xamarin-android/blob/74a90be5b3654173582b8ef455236de9b06508dd/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs#L58-L62

What did your original [global::Android.App.ApplicationAttribute] look like? Just an empty attribute?

@tranb3r
Copy link
Author

tranb3r commented Apr 30, 2024

No, it's not empty, it has several properties:

    [Application(
        Icon = "@mipmap/appicon",
        RoundIcon = "@mipmap/appicon_round",
        NetworkSecurityConfig = "@xml/network_security_config",
        AllowBackup = true
#if DEBUG
        , Debuggable = true
#endif
    )]

As explained, adding BackupAgent=null and ManageSpaceActivity=null will get rid of the first error, but then it fails with the second error.

@jonathanpeppers
Copy link
Member

@tranb3r I have a fix (which will probably be .NET 9 Preview 5) at this point.

It looks like setting these to null:

BackupAgent = null,
ManageSpaceActivity = null

Is actually not valid if it can't find these types:
https://github.com/xamarin/xamarin-android/blob/ce5bbd0f43fd8bf60fade283773932429894d0c5/src/Xamarin.Android.Build.Tasks/Utilities/ManifestDocumentElement.cs#L60-L61
(But would be nice if it didn't throw NRE)

If you put a valid Type, does this workaround for now:

BackupAgent = typeof(Android.App.Backup.BackupAgent),
ManageSpaceActivity = typeof(object)

jonathanpeppers added a commit to jonathanpeppers/xamarin-android that referenced this issue May 9, 2024
Fixes: dotnet#8914

Using a custom application with `TrimMode=full`:

    [Application]
    public class CustomApp : Application
    {
        public CustomApp(IntPtr h, JniHandleOwnership o) : base(h, o) { }
    }

Fails with:

    ILLink : error IL1012: IL Trimmer has encountered an unexpected error. Please report the issue at https://aka.ms/report-illink
    Fatal error in IL Linker
    Unhandled exception. System.InvalidOperationException: Sequence contains no matching element
        at System.Linq.ThrowHelper.ThrowNoMatchException()
        at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
        at MonoDroid.Tuner.PreserveApplications.PreserveTypeProperty(CustomAttribute attribute, String property) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 69
        at MonoDroid.Tuner.PreserveApplications.PreserveApplicationAttribute(CustomAttribute attribute) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 60
        at MonoDroid.Tuner.PreserveApplications.ProcessAttributeProvider(ICustomAttributeProvider provider) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 55
        at MonoDroid.Tuner.PreserveApplications.ProcessType(TypeDefinition type) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 43
        at MonoDroid.Tuner.PreserveApplications.<Initialize>b__0_1(TypeDefinition type) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 21
        at Mono.Linker.Steps.MarkStep.MarkType(TypeReference reference, DependencyInfo reason, Nullable`1 origin)
        at Mono.Linker.Steps.MarkStep.MarkTypeVisibleToReflection(TypeReference type, TypeDefinition definition, DependencyInfo& reason, MessageOrigin& origin)
        at Mono.Linker.Steps.MarkStep.MarkEntireType(TypeDefinition type, DependencyInfo& reason)
        at Mono.Linker.Steps.MarkStep.MarkEntireAssembly(AssemblyDefinition assembly)
        at Mono.Linker.Steps.MarkStep.MarkAssembly(AssemblyDefinition assembly, DependencyInfo reason)
        at Mono.Linker.Steps.MarkStep.MarkModule(ModuleDefinition module, DependencyInfo reason)
        at Mono.Linker.Steps.MarkStep.ProcessMarkedPending()
        at Mono.Linker.Steps.MarkStep.Initialize()
        at Mono.Linker.Steps.MarkStep.Process(LinkContext context)
        at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step)
        at Mono.Linker.Pipeline.Process(LinkContext context)
        at Mono.Linker.Driver.Run(ILogger customLogger)
        at Mono.Linker.Driver.Main(String[] args)
        at Mono.Linker.Driver.Main(String[] args)
    c:\Nuget\microsoft.net.illink.tasks\9.0.0-preview.3.24172.9\build\Microsoft.NET.ILLink.targets(91,5): error NETSDK1144: Optimizing assemblies for size failed.

I could update an existing `CustomApplicationClassAndMultiDex` test
to reproduce the problem.

What is happening is:

* `TrimMode=full` makes the trimmer way more aggressive.

* `Android.App.ApplicationAttribute` has various unused members trimmed
  away.

* `BackupAgent` and `ManageSpaceActivity` properties are trimmed away.

* Custom trimmer step throws an exception when trying to access these
  trimmed properties.

The trimmer step *already* handles cases where it can't load the types
and happily continues on. We should just do the same if the properties
are not found: as it would mean a customer didn't set them.

As a workaround, @tranb3r tried:

    [global::Android.App.ApplicationAttribute(
        ...
        BackupAgent = null,
        ManageSpaceActivity = null
    )]

But this results in a `NullReferenceException` in `ManifestDocumentElement`:

    C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.99.0-preview.3.231\tools\Xamarin.Android.Common.targets(1460,3): error XAGJS7001: System.NullReferenceException: Object reference not set to an instance of an object.
    at Xamarin.Android.Manifest.ManifestDocumentElement.ResolveType(String type, ICustomAttributeProvider provider, IAssemblyResolver resolver)
    at Android.App.ApplicationAttribute.<>c.<.cctor>b__114_7(ApplicationAttribute self, ICustomAttributeProvider p, IAssemblyResolver r, TypeDefinitionCache cache)
    at Xamarin.Android.Manifest.ManifestDocumentElement`1.ToAttributeValue(String name, T value, ICustomAttributeProvider provider, IAssemblyResolver resolver, TypeDefinitionCache cache, Int32 targetSdkVersion)
    at Xamarin.Android.Manifest.ManifestDocumentElement`1.ToAttribute(String name, T value, String packageName, ICustomAttributeProvider provider, IAssemblyResolver resolver, TypeDefinitionCache cache, Int32 targetSdkVersion)
    at Xamarin.Android.Manifest.ManifestDocumentElement`1.<>c__DisplayClass8_0.<ToElement>b__1(String e)
    at System.Linq.Enumerable.IteratorSelectIterator`2.MoveNext()
    at System.Linq.Enumerable.IEnumerableWhereIterator`1.MoveNext()
    at System.Xml.Linq.XContainer.AddContentSkipNotify(Object content)
    at Xamarin.Android.Manifest.ManifestDocumentElement`1.ToElement(T value, ICollection`1 specified, String packageName, TypeDefinitionCache cache, ICustomAttributeProvider provider, IAssemblyResolver resolver, Int32 targetSdkVersion)
    at Android.App.ApplicationAttribute.ToElement(IAssemblyResolver resolver, String packageName, TypeDefinitionCache cache)
    at Xamarin.Android.Tasks.ManifestDocument.CreateApplicationElement(XElement manifest, String applicationClass, List`1 subclasses, TypeDefinitionCache cache)
    at Xamarin.Android.Tasks.ManifestDocument.Merge(TaskLoggingHelper log, TypeDefinitionCache cache, List`1 subclasses, String applicationClass, Boolean embed, String bundledWearApplicationName, IEnumerable`1 mergedManifestDocuments)
    at Xamarin.Android.Tasks.GenerateJavaStubs.MergeManifest(NativeCodeGenState codeGenState, Dictionary`2 userAssemblies)
    at Xamarin.Android.Tasks.GenerateJavaStubs.Run(Boolean useMarshalMethods)
    at Xamarin.Android.Tasks.GenerateJavaStubs.RunTask()
    at Microsoft.Android.Build.Tasks.AndroidTask.Execute() in /Users/runner/work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/AndroidTask.cs:line 25

These does not appear to be valid settings *anyway*, but I updated the
code so it would throw a more appropriate `ArgumentException` instead
of `NullReferenceException` in a random location inside the method.
@tranb3r
Copy link
Author

tranb3r commented May 13, 2024

Thank you @jonathanpeppers , the workaround seems to work.

jonathanpeppers added a commit that referenced this issue May 13, 2024
Fixes: #8914

Using a custom application with `TrimMode=full`:

    [Application]
    public class CustomApp : Application
    {
        public CustomApp(IntPtr h, JniHandleOwnership o) : base(h, o) { }
    }

Fails with:

    ILLink : error IL1012: IL Trimmer has encountered an unexpected error. Please report the issue at https://aka.ms/report-illink
    Fatal error in IL Linker
    Unhandled exception. System.InvalidOperationException: Sequence contains no matching element
        at System.Linq.ThrowHelper.ThrowNoMatchException()
        at System.Linq.Enumerable.First[TSource](IEnumerable`1 source, Func`2 predicate)
        at MonoDroid.Tuner.PreserveApplications.PreserveTypeProperty(CustomAttribute attribute, String property) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 69
        at MonoDroid.Tuner.PreserveApplications.PreserveApplicationAttribute(CustomAttribute attribute) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 60
        at MonoDroid.Tuner.PreserveApplications.ProcessAttributeProvider(ICustomAttributeProvider provider) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 55
        at MonoDroid.Tuner.PreserveApplications.ProcessType(TypeDefinition type) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 43
        at MonoDroid.Tuner.PreserveApplications.<Initialize>b__0_1(TypeDefinition type) in /Users/runner/work/1/s/xamarin-android/src/Microsoft.Android.Sdk.ILLink/PreserveApplications.cs:line 21
        at Mono.Linker.Steps.MarkStep.MarkType(TypeReference reference, DependencyInfo reason, Nullable`1 origin)
        at Mono.Linker.Steps.MarkStep.MarkTypeVisibleToReflection(TypeReference type, TypeDefinition definition, DependencyInfo& reason, MessageOrigin& origin)
        at Mono.Linker.Steps.MarkStep.MarkEntireType(TypeDefinition type, DependencyInfo& reason)
        at Mono.Linker.Steps.MarkStep.MarkEntireAssembly(AssemblyDefinition assembly)
        at Mono.Linker.Steps.MarkStep.MarkAssembly(AssemblyDefinition assembly, DependencyInfo reason)
        at Mono.Linker.Steps.MarkStep.MarkModule(ModuleDefinition module, DependencyInfo reason)
        at Mono.Linker.Steps.MarkStep.ProcessMarkedPending()
        at Mono.Linker.Steps.MarkStep.Initialize()
        at Mono.Linker.Steps.MarkStep.Process(LinkContext context)
        at Mono.Linker.Pipeline.ProcessStep(LinkContext context, IStep step)
        at Mono.Linker.Pipeline.Process(LinkContext context)
        at Mono.Linker.Driver.Run(ILogger customLogger)
        at Mono.Linker.Driver.Main(String[] args)
        at Mono.Linker.Driver.Main(String[] args)
    c:\Nuget\microsoft.net.illink.tasks\9.0.0-preview.3.24172.9\build\Microsoft.NET.ILLink.targets(91,5): error NETSDK1144: Optimizing assemblies for size failed.

I could update an existing `CustomApplicationClassAndMultiDex` test
to reproduce the problem.

What is happening is:

* `TrimMode=full` makes the trimmer way more aggressive.

* `Android.App.ApplicationAttribute` has various unused members trimmed
  away.

* `BackupAgent` and `ManageSpaceActivity` properties are trimmed away.

* Custom trimmer step throws an exception when trying to access these
  trimmed properties.

The trimmer step *already* handles cases where it can't load the types
and happily continues on. We should just do the same if the properties
are not found: as it would mean a customer didn't set them.

As a workaround, @tranb3r tried:

    [global::Android.App.ApplicationAttribute(
        ...
        BackupAgent = null,
        ManageSpaceActivity = null
    )]

But this results in a `NullReferenceException` in `ManifestDocumentElement`:

    C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.99.0-preview.3.231\tools\Xamarin.Android.Common.targets(1460,3): error XAGJS7001: System.NullReferenceException: Object reference not set to an instance of an object.
    at Xamarin.Android.Manifest.ManifestDocumentElement.ResolveType(String type, ICustomAttributeProvider provider, IAssemblyResolver resolver)
    at Android.App.ApplicationAttribute.<>c.<.cctor>b__114_7(ApplicationAttribute self, ICustomAttributeProvider p, IAssemblyResolver r, TypeDefinitionCache cache)
    at Xamarin.Android.Manifest.ManifestDocumentElement`1.ToAttributeValue(String name, T value, ICustomAttributeProvider provider, IAssemblyResolver resolver, TypeDefinitionCache cache, Int32 targetSdkVersion)
    at Xamarin.Android.Manifest.ManifestDocumentElement`1.ToAttribute(String name, T value, String packageName, ICustomAttributeProvider provider, IAssemblyResolver resolver, TypeDefinitionCache cache, Int32 targetSdkVersion)
    at Xamarin.Android.Manifest.ManifestDocumentElement`1.<>c__DisplayClass8_0.<ToElement>b__1(String e)
    at System.Linq.Enumerable.IteratorSelectIterator`2.MoveNext()
    at System.Linq.Enumerable.IEnumerableWhereIterator`1.MoveNext()
    at System.Xml.Linq.XContainer.AddContentSkipNotify(Object content)
    at Xamarin.Android.Manifest.ManifestDocumentElement`1.ToElement(T value, ICollection`1 specified, String packageName, TypeDefinitionCache cache, ICustomAttributeProvider provider, IAssemblyResolver resolver, Int32 targetSdkVersion)
    at Android.App.ApplicationAttribute.ToElement(IAssemblyResolver resolver, String packageName, TypeDefinitionCache cache)
    at Xamarin.Android.Tasks.ManifestDocument.CreateApplicationElement(XElement manifest, String applicationClass, List`1 subclasses, TypeDefinitionCache cache)
    at Xamarin.Android.Tasks.ManifestDocument.Merge(TaskLoggingHelper log, TypeDefinitionCache cache, List`1 subclasses, String applicationClass, Boolean embed, String bundledWearApplicationName, IEnumerable`1 mergedManifestDocuments)
    at Xamarin.Android.Tasks.GenerateJavaStubs.MergeManifest(NativeCodeGenState codeGenState, Dictionary`2 userAssemblies)
    at Xamarin.Android.Tasks.GenerateJavaStubs.Run(Boolean useMarshalMethods)
    at Xamarin.Android.Tasks.GenerateJavaStubs.RunTask()
    at Microsoft.Android.Build.Tasks.AndroidTask.Execute() in /Users/runner/work/1/s/xamarin-android/external/xamarin-android-tools/src/Microsoft.Android.Build.BaseTasks/AndroidTask.cs:line 25

These does not appear to be valid settings *anyway*, but I updated the
code so it would throw a more appropriate `ArgumentException` instead
of `NullReferenceException` in a random location inside the method.
@github-actions github-actions bot locked and limited conversation to collaborators Jun 13, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Area: App+Library Build Issues when building Library projects or Application projects. needs-triage Issues that need to be assigned.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants