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

How to create a self-contained native executable. #281

Closed
devosalain opened this issue Mar 15, 2023 · 7 comments
Closed

How to create a self-contained native executable. #281

devosalain opened this issue Mar 15, 2023 · 7 comments

Comments

@devosalain
Copy link

I witched to gentoo-linux as development environment:
I tried in the project file

         <SelfContained>true</SelfContained>
	<PublishSingleFile>True</PublishSingleFile>
	<PublishTrimmed>true</PublishTrimmed>
	<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>

dotnet publish
& run the application returns:

./NewApp 
Unhandled exception. Avalonia.Markup.Xaml.XamlLoadException: No precompiled XAML found for avares://Avalonia.Themes.Fluent/Accents/AccentColors.xaml (baseUri: ), make sure to specify x:Class and include your XAML file as AvaloniaResource
   at Avalonia.Markup.Xaml.AvaloniaXamlLoader.Load(Uri, Uri ) in /_/src/Markup/Avalonia.Markup.Xaml/AvaloniaXamlLoader.cs:line 74
   at Avalonia.Markup.Xaml.Styling.StyleInclude.get_Loaded() in /_/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs:line 54
   at Avalonia.Markup.Xaml.Styling.StyleInclude.Avalonia.Controls.IResourceProvider.AddOwner(IResourceHost) in /_/src/Markup/Avalonia.Markup.Xaml/Styling/StyleInclude.cs:line 98
   at Avalonia.Styling.Styles.Avalonia.Controls.IResourceProvider.AddOwner(IResourceHost) in /_/src/Avalonia.Styling/Styling/Styles.cs:line 240
   at Avalonia.Styling.Styles.Avalonia.Controls.IResourceProvider.AddOwner(IResourceHost) in /_/src/Avalonia.Styling/Styling/Styles.cs:line 240
   at Avalonia.Themes.Fluent.FluentTheme.Avalonia.Controls.IResourceProvider.AddOwner(IResourceHost) in /_/src/Avalonia.Themes.Fluent/FluentTheme.cs:line 142
   at Avalonia.Styling.Styles.<OnCollectionChanged>g__Add|52_1(IList) in /_/src/Avalonia.Styling/Styling/Styles.cs:line 289
   at Avalonia.Styling.Styles.OnCollectionChanged(Object, NotifyCollectionChangedEventArgs) in /_/src/Avalonia.Styling/Styling/Styles.cs:line 318
   at Avalonia.Collections.AvaloniaList`1.NotifyAdd(T, Int32) in /_/src/Avalonia.Base/Collections/AvaloniaList.cs:line 681
   at Avalonia.Collections.AvaloniaList`1.Add(T) in /_/src/Avalonia.Base/Collections/AvaloniaList.cs:line 205
   at Avalonia.Styling.Styles.Add(IStyle) in /_/src/Avalonia.Styling/Styling/Styles.cs:line 201
   at NewApp.App.Initialize() in /home/x/avalonia/NewApp/Program.fs:line 25
   at Avalonia.Controls.AppBuilderBase`1.Setup() in /_/src/Avalonia.Controls/AppBuilderBase.cs:line 310
   at Avalonia.Controls.AppBuilderBase`1.SetupWithLifetime(IApplicationLifetime) in /_/src/Avalonia.Controls/AppBuilderBase.cs:line 179
   at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime[T](T, String[], ShutdownMode ) in /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs:line 208
   at NewApp.Program.main(String[]) in /home/x/avalonia/NewApp/Program.fs:line 37
Aborted
x@gentoo ~/avalonia/NewApp $ 

@JaggerJo
Copy link
Member

JaggerJo commented Mar 15, 2023

I recommend to not use the templates (they are out of date), but take a look at the getting started section of
the docs.

You could also clone the repository and check out the examples.

Let me know if you encounter any issues.

@Numpsy
Copy link
Collaborator

Numpsy commented Mar 15, 2023

Which versions of Avalonia and/or FuncUI? (there have been a lot of changes that effect trimming in Avalonia 11, including some to resolve styles at build time to avoid the linker trimming them)

FWIW, I've had single file apps working with FuncUI in both .NET 6 and 7, though I currently have <TrimMode>partial</TrimMode> in my .NET 7 app because of issues elsewhere

@devosalain
Copy link
Author

devosalain commented Mar 15, 2023

Thanks Numpsy, with : < TrimMode > partial< / TrimMode > it worked fine !!!
However, It would be nice to know some more info, what could be the issue without this line, or why it is needed ?

@Numpsy
Copy link
Collaborator

Numpsy commented Mar 17, 2023

I believe that the issue with the themes/styles is that the trimmer can't understand things that are only referenced dynamically (e.g. via xaml that's loaded at runtime), so it decides they're unused and removes them. (Setting TrimMode is one way of avoiding that, as it means that only assemblies that are explicitly marked as trimmable will be trimmed).

Avalonia 11 has been getting some changes to help with this by resolving the styles at compile time and using compiled xaml to create strong references to everyting, so that they won't be trimmed. However, I don't know if that's all done yet, or of there might yet be anything in FuncUI that needs tweaking or annotating as well.

Another approach to the problem is to leave the TrimMode set to Full and use the per assembly settings documented at https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options?pivots=dotnet-7-0#root-assemblies to keep specific ones - The Avalonia web assembly control catalog sample at https://github.com/AvaloniaUI/Avalonia/tree/master/samples/ControlCatalog.Browser does that with a Roots.xml file

@Numpsy
Copy link
Collaborator

Numpsy commented Mar 31, 2023

A bit more info on this, as i'm looking at it again, and can use the control catalog sample as an example now:

Say that you have something like this:

image

Where it loads the styles dynamically.
Because of the way that FluentTheme is a class, and the way that it's been implemented in Avalona 11 P5+ in a way that tries to be trim friendly, you can publish a trimmed version of the app and the Theme will be retained.

However, because the local styles are only referenced by a string, and the linker can't understand that, the style data can be removed, so you get the ops exception:

Description: The process was terminated due to an unhandled exception.
Exception Info: Avalonia.Markup.Xaml.XamlLoadException: No precompiled XAML found for avares://Avalonia.FuncUI.ControlCatalog/Styles/TabControl.xaml (baseUri: ), make sure to specify x:Class and include your XAML file as AvaloniaResource

However, as of Avalona 11 P5, it now has the ability to resolve styles specified in xaml at compile time and inject hard references to those in the binary, so that they won't be trimmed. So if you have xaml like this:

<Application xmlns="https://github.com/avaloniaui"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             x:Class="Avalonia.FuncUI.ControlCatalog.App">
    <Application.Styles>
        <FluentTheme />
        <StyleInclude Source="avares://Avalonia.FuncUI.ControlCatalog/Styles/TabControl.xaml"/>
    </Application.Styles>
</Application>

and change the startup code to this

type App() =
    inherit Application()

    override this.Initialize() =
        Avalonia.Markup.Xaml.AvaloniaXamlLoader.Load(this)

The the styles get retained.
It's an extra moving part rather than all being in code, but it does also have the advantage that you'll get a build error if the styles are unavailable rather than it falling over at runtime.

@Numpsy
Copy link
Collaborator

Numpsy commented Mar 31, 2023

On the subject of the control catalog, if I build it as .NET 7 with full trimming then I get this:

Exception Info: System.NullReferenceException: Object reference not set to an instance of an object.
   at Microsoft.FSharp.Reflection.Impl.getUnionTagReader@561-3.Invoke(Object) in D:\a\_work\1\s\src\FSharp.Core\reflect.fs:line 561
   at Microsoft.FSharp.Reflection.FSharpValue.GetUnionFields(Object, Type, FSharpOption`1 ) in D:\a\_work\1\s\src\FSharp.Core\reflect.fs:line 1399
   at Microsoft.FSharp.Text.StructuredPrintfImpl.ReflectUtils.Value.GetValueInfoOfObject$cont@527(BindingFlags, Object, Type, Unit) in D:\a\_work\1\s\src\Compiler\Utilities\sformat.fs:line 528
   at Microsoft.FSharp.Text.StructuredPrintfImpl.ReflectUtils.Value.GetValueInfoOfObject(BindingFlags, Object) in D:\a\_work\1\s\src\Compiler\Utilities\sformat.fs:line 520
   at Microsoft.FSharp.Text.StructuredPrintfImpl.ReflectUtils.Value.GetValueInfo[a](BindingFlags, a, Type) in D:\a\_work\1\s\src\Compiler\Utilities\sformat.fs:line 581
   at Microsoft.FSharp.Text.StructuredPrintfImpl.Display.ObjectGraphFormatter.objL(ShowMode, Int32, Precedence, Object, Type) in D:\a\_work\1\s\src\Compiler\Utilities\sformat.fs:line 986
   at Microsoft.FSharp.Text.StructuredPrintfImpl.Display.ObjectGraphFormatter.Format[a](ShowMode, a, Type) in D:\a\_work\1\s\src\Compiler\Utilities\sformat.fs:line 1520
   at Microsoft.FSharp.Text.StructuredPrintfImpl.Display.anyToStringForPrintf[T](FormatOptions, BindingFlags, T, Type) in D:\a\_work\1\s\src\Compiler\Utilities\sformat.fs:line 1648
   at Microsoft.FSharp.Core.PrintfImpl.ObjectPrinter.GenericToStringCore[T](T, FormatOptions, BindingFlags) in D:\a\_work\1\s\src\FSharp.Core\printf.fs:line 937
   at Microsoft.FSharp.Core.PrintfImpl.GenericToString@976-3.Invoke(Object) in D:\a\_work\1\s\src\FSharp.Core\printf.fs:line 978
   at Microsoft.FSharp.Core.PrintfImpl.TwoStepWithArg@524-1.Invoke(A, B) in D:\a\_work\1\s\src\FSharp.Core\printf.fs:line 529
   at Elmish.Log.toConsole[a](String, a)
   at Elmish.ProgramModule.withConsoleTrace@78-2.Invoke(model)
   at Elmish.ProgramModule.runWithDispatch[msg,arg,model,view](FSharpFunc`2, arg, Program`4)
   at Avalonia.FuncUI.ControlCatalog.App.OnFrameworkInitializationCompleted() in S:\GitHubForks\MyFuncUI\src\Avalonia.FuncUI.ControlCatalog\Avalonia.FuncUI.ControlCatalog\ControlCatalog.fs:line 45
   at Avalonia.AppBuilder.Setup() in /_/src/Avalonia.Controls/AppBuilder.cs:line 265
   at Avalonia.AppBuilder.SetupWithLifetime(IApplicationLifetime) in /_/src/Avalonia.Controls/AppBuilder.cs:line 162
   at Avalonia.ClassicDesktopStyleApplicationLifetimeExtensions.StartWithClassicDesktopLifetime(AppBuilder, String[], ShutdownMode ) in /_/src/Avalonia.Controls/ApplicationLifetimes/ClassicDesktopStyleApplicationLifetime.cs:line 213
   at Avalonia.FuncUI.ControlCatalog.Program.main(String[]) in S:\GitHubForks\MyFuncUI\src\Avalonia.FuncUI.ControlCatalog\Avalonia.FuncUI.ControlCatalog.Desktop\Main.fs:line 9

though that sounds like Elmish trying to do reflection based log formatting on things that have been trimmed, rather than a FuncUI specific thing (something else to watch out for with trimming though)

@JaggerJo
Copy link
Member

JaggerJo commented Jul 3, 2023

Closing this as the question is not related to FuncUI

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants