-
Notifications
You must be signed in to change notification settings - Fork 1.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
[Question] Extract BamlRecordReader feasability #10165
Comments
@yowl I firmly believe that this task is feasible. In fact, I think it can be accomplished with just a simple Roslyn analyzer. If you need any assistance from me, I would be more than happy to help. |
Thanks for the offer of help! How did you envisage this working given the constraints of a Roslyn analyzer ? |
@yowl How about add the Xaml file to Additional file and then analyze it? |
In many cases we do not have xaml, just the dlls. The inputs to this process would be dlls and the output would be a trimmer xml file (or modifications to ItemGroups in msbuild, but that sounds more complicated). |
@yowl I do not know how to read the embed assembly resource from IAssemblySymbol. |
ICSharpCode.BamlDecompiler is an independent parser that could be used to analyze dependencies and emit trimmer metadata before it's read. No idea how feasible this idea is though. Specifically, BAML lacks information about bindings anyway, as WPF doesn't have any concept of compiled bindings like Avalonia/MAUI or xBind like UWP. |
Yes bindings are still a hole, but if |
Thank you @maxkatz6 @yowl I write the demo code about read the baml resource from assembly in IncrementalGenerator. You can find my code in https://github.com/lindexi/lindexi_gd/tree/ba3dba2934e3c56e6efadc9ea91ad3f2f25987b8/Roslyn/RerhabaikaKaloharfo using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Runtime.InteropServices.ComTypes;
using System.Xml.Linq;
using ICSharpCode.BamlDecompiler;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Util;
using Microsoft.CodeAnalysis;
namespace NowabehairFearkeqerche
{
[Generator(LanguageNames.CSharp)]
public class FooGenerator : IIncrementalGenerator
{
public void Initialize(IncrementalGeneratorInitializationContext context)
{
var xamlIncrementalValueProvider = context.CompilationProvider.Select((compilation, token) =>
{
var list = new List<XamlRecord>();
foreach (MetadataReference compilationReference in compilation.References)
{
if (!(compilationReference is PortableExecutableReference portableExecutableReference))
{
continue;
}
var assemblySymbol = compilation.GetAssemblyOrModuleSymbol(compilationReference) as IAssemblySymbol;
var testDemoProjectName = "DalljukanemDaryawceceegal";
if (assemblySymbol?.Name != testDemoProjectName)
{
continue;
}
var filePath = portableExecutableReference.FilePath;
if (filePath is null)
{
continue;
}
if (Path.GetDirectoryName(filePath) is var directory && Path.GetFileName(directory) == "ref")
{
filePath = Path.Combine(directory, "..", "..", "..", "..", "bin", "Debug",
"net9.0-windows", "DalljukanemDaryawceceegal.dll");
filePath = Path.GetFullPath(filePath);
}
var fileInfo = new FileInfo(filePath);
var xamlDecompiler = new XamlDecompiler(fileInfo.FullName, new BamlDecompilerSettings()
{
ThrowOnAssemblyResolveErrors = false
});
var peFile = new PEFile(fileInfo.FullName);
foreach (var resource in peFile.Resources)
{
if (!(resource.TryOpenStream() is Stream stream))
{
continue;
}
var resourcesFile = new ResourcesFile(stream);
foreach (var keyValuePair in resourcesFile)
{
if (keyValuePair.Key.EndsWith(".baml"))
{
if (keyValuePair.Value is Stream bamlStream)
{
var decompilationResult = xamlDecompiler.Decompile(bamlStream);
var xaml = decompilationResult.Xaml;
var xamlRecord = new XamlRecord(xaml, portableExecutableReference,
assemblySymbol);
list.Add(xamlRecord);
}
}
}
}
}
return list;
});
context.RegisterSourceOutput(xamlIncrementalValueProvider, (productionContext, provider) =>
{
});
}
}
struct XamlRecord
{
public XamlRecord(XDocument xaml, PortableExecutableReference portableExecutableReference,
IAssemblySymbol assemblySymbol)
{
Xaml = xaml;
PortableExecutableReference = portableExecutableReference;
AssemblySymbol = assemblySymbol;
}
public XDocument Xaml { get; }
public PortableExecutableReference PortableExecutableReference { get; }
public IAssemblySymbol AssemblySymbol { get; }
}
} |
|
Hi, I contribute to the NativeAOT-LLVM project which is a NAOT compiler for LLVM and WebAssembly. I am currently bringing up a WPF applicaation in the browser using Avalonia's XPF bridge and have a question. As you may know NAOT is an AOT compiler that uses roots to establish a dependency tree of required types and methods that need compiling. WPF presents a challenge in that a some types/properties (get/set methods) may only be used in Xaml or Baml. So it would be advantageous from the goal of gathering dependencies to read the Baml resources and root the necessary types and methods. To that end I was looking at BamlRecordReader.cs and wondering if it could be extracted from the PresentationFramework assembly. Most things are possible, but is this going to be really hard do you think?
Thanks!
The text was updated successfully, but these errors were encountered: