dotnet / maui

.NET MAUI is the .NET Multi-platform App UI, a framework for building native device applications spanning mobile, tablet, and desktop.
https://dot.net/maui
MIT License
22.12k stars 1.73k forks source link

Publish error when using generic class for DataType of DataTemplate in XAML #19035

Open SokoFromNZ opened 11 months ago

SokoFromNZ commented 11 months ago

Description

When publishing (build a release) for Android I get an Microsoft.Android.Sdk.Aot.targets(91,5): error : Precompiling failed error. I'm using Visual Studio 2022 v17.8.1 Enterprise on an Win11 machine. Running the code as Debug build from VS works.

Steps to Reproduce

  1. Create a default MAUI App via File ->New Project
  2. Add this new class in the root directory:
    public class MyGenericItem<T>
    {
    public string Label { get;}
    public T Data { get; }
    public MyGenericItem(T data, string label)
    {
        Data = data;
        Label = label;
    }
    }
  3. Add the following resource to existing MainPage.xaml ContentPage:
    ...
    <ContentPage.Resources>
        <DataTemplate x:Key="dataTemplate" x:DataType="local:MyGenericItem`1">
            <Grid>
                <Label Text="{Binding Label}" />
            </Grid>
        </DataTemplate>
    </ContentPage.Resources>
    ...
  4. Run this publish command from a CLI in the root:
    dotnet.exe publish -c:Release -f:net8.0-android
  5. publish exits with this error
    C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.43\targets\Microsoft.Android.Sdk.Aot.targets(109,5): error : Precompiling failed for c:\Users\soko\Desktop\MauiPublishAotError\obj\Release\net8.0-android\android-x86\linked\MauiPublishAotError.dll with exit code -1073740791. [c:\Users\soko\Desktop\MauiPublishAotError\MauiPublishAotError.csproj::TargetFramework=net8.0-android]
    C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.43\targets\Microsoft.Android.Sdk.Aot.targets(109,5): error : Mono Ahead of Time compiler - compiling assembly c:\Users\soko\Desktop\MauiPublishAotError\obj\Release\net8.0-android\android-x86\linked\MauiPublishAotError.dll [c:\Users\soko\Desktop\MauiPublishAotError\MauiPublishAotError.csproj::TargetFramework=net8.0-android]
    C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.43\targets\Microsoft.Android.Sdk.Aot.targets(109,5): error : AOTID B4FB99BD-7643-9D12-5EF1-5DC1A60D8760 [c:\Users\soko\Desktop\MauiPublishAotError\MauiPublishAotError.csproj::TargetFramework=net8.0-android]
    C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.43\targets\Microsoft.Android.Sdk.Aot.targets(109,5): error : * Assertion at D:\a\_work\1\s\src\mono\mono\mini\method-to-ir.c:6465, condition `!sig->has_type_parameters' not met [c:\Users\soko\Desktop\MauiPublishAotError\MauiPublishAotError.csproj::TargetFramework=net8.0-android]
    C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.43\targets\Microsoft.Android.Sdk.Aot.targets(109,5): error : Unable to compile method 'object MauiPublishAotError.MainPage/<InitializeComponent>_anonXamlCDataTemplate_0:LoadDataTemplate ()' due to: 'Method with open type while not compiling gshared'. [c:\Users\soko\Desktop\MauiPublishAotError\MauiPublishAotError.csproj::TargetFramework=net8.0-android]

Link to public reproduction project repository

No response

Version with bug

8.0.3

Is this a regression from previous behavior?

Not sure, did not test other versions

Last version that worked well

Unknown/Other

Affected platforms

Android, I was not able test on other platforms

Affected platform versions

No response

Did you find any workaround?

No workaround I can think of.

Relevant log output

No response

drasticactions commented 10 months ago

You should be able to work around it by disabling XamlC on the given page.

[XamlCompilation(XamlCompilationOptions.Skip)]
public partial class MainPage : ContentPage

Issues with Mono AOT have been mentioned in the past for Xamarin.Forms (https://github.com/xamarin/Xamarin.Forms/issues/1497) as well. I'm not sure if it's Linker related, or XamlC, maybe both? CC @jonathanpeppers @StephaneDelcroix

SokoFromNZ commented 10 months ago

Is there any disadvantage of your work around compared to a working Mono AOT compilation?

drasticactions commented 10 months ago

Is there any disadvantage of your work around compared to a working Mono AOT compilation?

XamlC is compiled XAML. The Linker is blowing up on the compiled XAML since, I think, it's trying to access parts that are being linked away. My code turns off XamlC, so that I believe would cause your XAML to be built at runtime (I could be wrong on that, @StephaneDelcroix would know more), so I imagine there could a performance hit depending on the complexity of the page and/or code you have it on. But in terms of specific drop off, I don't know, it depends.

That said, I do think there's a legit issue with how that code is being handled by XamlC and/or AOT.

The other thing you could do is turn off XamlC specifically for Android on that page

#if ANDROID
[XamlCompilation(XamlCompilationOptions.Skip)]
#endif
public partial class MainPage : ContentPage

So it would keep the other platforms using the compiled xaml

PureWeen commented 10 months ago

@jonathanpeppers thoughts ?

jonathanpeppers commented 10 months ago

@SokoFromNZ can you share a .binlog of the error? https://aka.ms/binlog

Does turning off XamlC fix it? or not? That is also a huge clue.

SokoFromNZ commented 10 months ago

msbuild.zip here you are. the attribute fixes the issue

jonathanpeppers commented 10 months ago

Looking at the error, I suspect the assembly somehow has invalid IL:

C:\Program Files\dotnet\packs\Microsoft.Android.Sdk.Windows\34.0.43\targets\Microsoft.Android.Sdk.Aot.targets(109,5): Precompiling failed for C:\Users\soko\Desktop\MauiPublishAotError\obj\Release\net8.0-android\android-arm\linked\MauiPublishAotError.dll with exit code -1073740791.
Mono Ahead of Time compiler - compiling assembly C:\Users\soko\Desktop\MauiPublishAotError\obj\Release\net8.0-android\android-arm\linked\MauiPublishAotError.dll
AOTID D36F7652-F57B-BFE8-C96C-CAFE7BF3AC1B
* Assertion at D:\a\_work\1\s\src\mono\mono\mini\method-to-ir.c:6465, condition `!sig->has_type_parameters' not met
Unable to compile method 'object MauiPublishAotError.MainPage/<InitializeComponent>_anonXamlCDataTemplate_0:LoadDataTemplate ()' due to: 'Method with open type while not compiling gshared'. [C:\Users\soko\Desktop\MauiPublishAotError\MauiPublishAotError.csproj]

Can you share C:\Users\soko\Desktop\MauiPublishAotError\obj\Release\net8.0-android\android-arm\linked\MauiPublishAotError.dll?

It's possible some platforms accept this form of slightly invalid IL, while the Mono AOT compiler does not.

In either case, I think this points to a XamlC issue if turning that off for one page fixes it.

SokoFromNZ commented 10 months ago

MauiPublishAotError.zip sure

jonathanpeppers commented 10 months ago

The method itself seems like it is missing a type parameter:

image

I think this should say MyGenericItem<T> P_0, and the method should also have a type parameter?

The generic type itself looks OK:

image

SokoFromNZ commented 10 months ago

So the question stands which source code generates the first screenshot out of the second one. There is the nasty bug :)

jonathanpeppers commented 10 months ago

@StephaneDelcroix is probably best to answer that, it's likely just the code in XamlC that generates typed bindings.

Honestly, I don't see how this is even useable from a developer's perspective: x:DataType="local:MyGenericItem`1"

Is this something that should even work? How would a regular Joe know to put "`1"?

SokoFromNZ commented 10 months ago

A regular Joe I am not ;) https://learn.microsoft.com/en-us/dotnet/api/system.codedom.codetypereference.basetype?view=dotnet-plat-ext-8.0&redirectedfrom=MSDN#representation-of-generic-types Generic types are formatted with the name of the type followed by a grave accent ("`") followed by a count of the generic type arguments.

Also here: https://stackoverflow.com/questions/10005187/how-to-reference-a-generic-type-in-the-datatype-attribute-of-a-datatemplate/70021008#70021008

Actually I'm curious why a debug build works fine?! As it doesn't seem to be an AOT issue and more an XamlC issue. Is there a different XamlC for Debug/Release?

jonathanpeppers commented 10 months ago

In Debug builds, XamlC is "validate-only" mode, so it doesn't write any IL.

ghost commented 10 months ago

We've added this issue to our backlog, and we will work to address it as time and resources allow. If you have any additional information or questions about this issue, please leave a comment. For additional info about issue management, please read our Triage Process.