-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
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
New API for XAML group transformers and AvaloniaRuntimeXamlLoader.LoadGroup #9537
Conversation
…d code with manual IL emit
You can test this PR using the following package version. |
throw new InvalidProgramException("Same XAML file was loaded twice." + | ||
"Make sure there is no x:Class duplicates no files were added to the AvaloniaResource msbuild items group twice."); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@kekekeks as I understand, we don't need this hack anymore.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC it was required for compatibility with pre-.axaml
themes that was achieved via including the same file as EmbeddedResource and AvaloniaResource.
You can test this PR using the following package version. |
@@ -74,7 +74,7 @@ | |||
ReportImportance="$(AvaloniaXamlReportImportance)"/> | |||
<Exec | |||
Condition="'$(_AvaloniaUseExternalMSBuild)' == 'true'" | |||
Command="dotnet msbuild /nodereuse:false $(MSBuildProjectFile) /t:GenerateAvaloniaResources /p:_AvaloniaForceInternalMSBuild=true /p:Configuration=$(Configuration) /p:TargetFramework=$(TargetFramework) /p:BuildProjectReferences=false"/> | |||
Command="dotnet msbuild /nodereuse:false $(MSBuildProjectFile) /t:GenerateAvaloniaResources /p:_AvaloniaForceInternalMSBuild=true /p:Configuration=$(Configuration) /p:TargetFramework=$(TargetFramework) /p:RuntimeIdentifier=$(RuntimeIdentifier) /p:BuildProjectReferences=false"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was causing compile errors with if I change xaml project target framework to "net7.0".
Main msbuild task was running with a runtime identifier set (by default in net7.0), while external msbuild task wasn't (no idea why, haven't checked too deep).
As the result, IntermediateOutputPath was different between these two runs, and resource files were missing.
You can test this PR using the following package version. |
/// <param name="xaml">The string containing the XAML.</param> | ||
/// <param name="configuration">Xaml loader configuration.</param> | ||
/// <returns>The loaded object.</returns> | ||
public static object Load(string xaml, RuntimeXamlLoaderConfiguration configuration) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC it was supposed to be a public API for users who want to load XAML at runtime.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So the idea was to have configuration parameters in a separate class so we can add more of them without breaking compatibility.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I added this configuration parameter couple of weeks ago. So no breaking changes here.
But this configuration shouldn't contain any file source related configs, like RootObject, otherwise it won't be reusable in the LoadGroup methods, where there could be multiple root objects.
...lonia.Markup.Xaml.Loader/CompilerExtensions/GroupTransformers/XamlIncludeGroupTransformer.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mostly lgtm
node); | ||
} | ||
|
||
AssetLoader.RegisterResUriParsers(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe this should happen somewhere in MSBuild task initialization rather than in a transformer. I'm also not quite sure if that's a good idea to pollute MSBuild process with our global state
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will move. Also I don't use avalonia global state here, don't access AssetLoader APIs. Instead only URI scheme configuration is registered in .NET URI parser. Otherwise it will lower case all the links.
You can test this PR using the following package version. |
You can test this PR using the following package version. |
@maxkatz6 Testing this and got following error:
Xaml: <StyleInclude Source="avares://Dock.Avalonia/Themes/DockFluentTheme.axaml" /> |
Don't think so, the |
@maxkatz6 might be some race condition related to this: Avalonia/src/Avalonia.Build.Tasks/CompileAvaloniaXamlTask.cs Lines 39 to 40 in ed2a4a3
|
Btw is this now required for theme files based on
|
Another issue (change?) I found: When I had in xaml file in same assembly: <ResourceInclude Source="avares://Dock.Avalonia/Controls/DocumentTabStripItem.axaml" /> and changed to <ResourceInclude Source="/Controls/DocumentTabStripItem.axaml" /> I got error Error AVLN:0004 Avalonia: Unable to resolve build method "Build:/Themes/Controls/DocumentTabStripItem.axaml" resource on the "Dock.Avalonia" assembly. Line 8, position 10. I needed to add to <AvaloniaResource Include="**/*.axaml" /> Edit: but that (adding AvaloniaResource to csproj) caused another error:
|
Seems like so. When I build same project second time - it works just fine.
@wieslawsoltes
Found the problem. Fixing it.
I don't think it's needed, otherwise you might end up with duplicate avalonia resources. Next error is a result. |
Try changing |
Changing the output path just before CoreCompile and reverting it afterwards might work too. |
Tested #9571 and it's fixed. |
|
Interesting, when I switch to
instead of
it works, so still some issue with |
Fore reference this is generated app code: // Decompiled with JetBrains decompiler
// Type: AvaloniaDemo.Xaml.App
// Assembly: DemoXaml, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 710CC489-2D33-44F9-A635-313141D04CE2
// Assembly location: C:\Users\Administrator\Documents\GitHub\Dock\samples\DemoXaml\bin\Debug\net7.0\DemoXaml.dll
// Compiler-generated code is shown
using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.ApplicationLifetimes;
using Avalonia.Layout;
using Avalonia.Markup.Xaml.Styling;
using Avalonia.Markup.Xaml.XamlIl.Runtime;
using Avalonia.Styling;
using Avalonia.Themes.Fluent;
using CompiledAvaloniaXaml;
using System;
using System.Runtime.InteropServices;
namespace AvaloniaDemo.Xaml
{
public class App : Application
{
private static Action<object> \u0021XamlIlPopulateOverride;
public override void Initialize()
{
App.\u0021XamlIlPopulateTrampoline(this);
}
public override void OnFrameworkInitializationCompleted()
{
if (this.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime applicationLifetime1)
applicationLifetime1.MainWindow = (Window) new MainWindow();
if (this.ApplicationLifetime is ISingleViewApplicationLifetime applicationLifetime2)
applicationLifetime2.MainView = (Control) new MainView();
base.OnFrameworkInitializationCompleted();
}
public App()
{
base.\u002Ector();
}
static void \u0021XamlIlPopulate([In] IServiceProvider obj0, [In] App obj1)
{
XamlIlContext.Context<App> context = new XamlIlContext.Context<App>(obj0, new object[1]
{
(object) \u0021AvaloniaResources.NamespaceInfo\u003A\u002FApp\u002Eaxaml.Singleton
}, "avares://DemoXaml/App.axaml");
context.RootObject = obj1;
context.IntermediateRoot = (object) obj1;
App app1;
App app2 = app1 = obj1;
context.PushParent((object) app2);
App app3 = app2;
app3.Name = "Dock Avalonia Demo";
Styles styles1 = app3.Styles;
FluentTheme fluentTheme = new FluentTheme();
fluentTheme.Mode = FluentThemeMode.Light;
styles1.Add((IStyle) fluentTheme);
Styles styles2 = app3.Styles;
StyleInclude styleInclude = new StyleInclude((IServiceProvider) context);
styleInclude.Source = new Uri("avares://Dock.Avalonia/Themes/DockFluentTheme.axaml", UriKind.RelativeOrAbsolute);
styles2.Add((IStyle) styleInclude);
Styles styles3 = app3.Styles;
Style style = new Style();
style.Selector = ((Selector) null).OfType(typeof (TextBlock));
Setter setter1 = new Setter();
setter1.Property = (AvaloniaProperty) Layoutable.HorizontalAlignmentProperty;
setter1.Value = (object) HorizontalAlignment.Center;
style.Add((ISetter) setter1);
Setter setter2 = new Setter();
setter2.Property = (AvaloniaProperty) Layoutable.VerticalAlignmentProperty;
setter2.Value = (object) VerticalAlignment.Center;
style.Add((ISetter) setter2);
styles3.Add((IStyle) style);
context.PopParent();
if (app1 is StyledElement styled)
NameScope.SetNameScope(styled, context.AvaloniaNameScope);
context.AvaloniaNameScope.Complete();
}
private static void \u0021XamlIlPopulateTrampoline([In] App obj0)
{
if (App.\u0021XamlIlPopulateOverride != null)
App.\u0021XamlIlPopulateOverride((object) obj0);
else
App.\u0021XamlIlPopulate(XamlIlRuntimeHelpers.CreateRootServiceProviderV2(), obj0);
}
}
} |
Problem was with ref assembly, in which "!XamlIlPopulate" was not generated and was not copied from the non-ref assembly. |
|
What does the pull request do?
Partial reimplementation of my previous PR with bunch of new features (mostly for internal use).
What is the current behavior?
There was no way to:
What is the updated/expected behavior with this PR?
It is possible now to:
AvaloniaRuntimeXamlLoader.LoadGroup
allows to compile and parse multiple files and test their combination.Checklist
Breaking changes
Comparing to previous master builds (but not preview), there are couple of binary breaking changes.
Also, in the public API some changes were made for the AvaloniaRuntimeXamlLoader. Some properties were moved from RuntimeXamlLoaderConfiguration to the RuntimeXamlLoaderDocument, as they were specific to a single file, while same configuration should be applicable to a group of files.
New
Load
method has following signature:Fixed issues
Fixes #9127