-
-
Notifications
You must be signed in to change notification settings - Fork 532
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
AOT Support for Spectre.Console #1690
AOT Support for Spectre.Console #1690
Conversation
…ty with NetStandard 2.0 and AOT
…incompatability with AOT
… better in AOT scenarios
…iate for AOT scenarios. Additionally adds a warning to CommandApp for users who may try it.
This is already a great start and should already help in alot of use cases. What im mostly surprised about is that Spectre.Console is apparently easier to get Native AOT on than Spectre.Console.Cli (im assuming thats due to reflection in the background?) Considering most users of Spectre.Console also use the cli for their projects i would consider that the next big target. Maybe using source generators instead of reflection (again, if thats the case) |
When this is merged i will try it out on my projects that i was getting errors on and i will come back with my results here |
Very excited to try this out! |
Very excited to merge this! 😁 |
I agree with this general approach. I tried really hard to get Spectre.Console.Cli to work with a source generator, but ran into too many problems that directly affected the surface area. The dependency injection approach is already really hard to make work without reflection. But even stuff like this: app.Configure(config =>
{
config.AddCommand<AddCommand>("add");
config.AddCommand<CommitCommand>("commit");
config.AddCommand<RebaseCommand>("rebase");
}) The By the time I got something kind-of working the API was just too different. It felt like a reboot. And at that point I figured I might as well try to reuse some code. My eventual solution was to build a "CLI" format for my serde system: https://github.com/dn-vm/dnvm/tree/main/src/Serde.CmdLine. Serde is a framework for expressing serializers and deserializers and uses a source generator. The model is intended to allow swapping in different formats. CLI parsing is, in some sense, a serialization/deserialization format. So I built a format for that. It's still very simplistic, but after I round off the edges I might create a NuGet package for it. |
This would be insanely cool if it would be able to work, however i think there would be some kind of way to do the thing in your example using for example roslyn source gens by grabbing the attributes of the Command specifying the options and settings and then the roslyn source gen would have to add code to the build manually setting the different options to their The roslyn source gen would have to generate some kind of line and add it to the source like: `Port = args.ParseThePortAndDoTheThings("--port ") So i dont think we would need a external lib for this, using some well defined roslyn generators these commands and settings can be set using some kind of functions injected at build time that contain all of the different properties and their respective cli strings |
I think at the end of the day to do AOT in Spectre.Console.Cli would either take considerable effort or a change in the API. Between DI, TypeConverters, MultiMap<>, dynamically creating arrays and even some magic in there for automatically instantiating things like Additionally, a while back, we split the Cli and Console app with the knowledge there were more "modern" libraries like System.CommandLine that integrate well with Spectre.Console that having the benefit of being developed after the introduction of things like assembly trimming have support designed in. I do think a third party that wanted to generate a source generator that scans for Settings and dumps a ton of |
Thats fair, so it seems this one is just gonna be: who wants to either put an unrealistic amount of effort to change the current Codebase or just rewrite it from scratch to native aot, so the options arent great here i guess. |
Once AOT for Spectre.Console is in, I will take a look at generating the command tree using source generators instead of doing it by reflection. I have some ideas. |
Redid the While I was in there I went ahead and added support for Spectre.Console.Json and Spectre.Console.ImageSharp, and I even added a blurb in the documentation's best practice section. |
373b838
to
4b2b284
Compare
FYI I’m totally willing to help anyone who wants to dive in the rabbit hole of writing a source generator. I just hit a wall and happened to have an alternative that I could use to unblock my app. FYI I’ve been using the rest of spectre console in dnvm as aot and it has worked great. |
…andling for stack frames.
4b2b284
to
f465619
Compare
I have nothing really to add here anymore. Pending a review, I say ready for merge. |
@phil-scott-78 I will be taking a look now. Not sure I will understand everything though 😁 |
Anything needing clarification or more comments to describe what's happening, I'm happy to expand! |
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.
It looks good to me. A question, though: Can we remove reliance on the other polyfill packages now that PolySharp
has been introduced?
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.
It looks good to me. A question, though: Can we remove reliance on the other polyfill packages now that PolySharp has been introduced?
Good question. I bet we could. Want me to try in this pr or a new one? |
@phil-scott-78 We can try it in a new PR. |
Merged it! |
Made another run at AOT support. Spectre.Console itself mostly worked already, but with a few rough spots and unexpected behaviors for edge cases. The biggest issue may have been if someone was using prompts and relying on TypeConverters. @agocke did some work to use the intrinsic ones that I've included here.
ExceptionHelper
is marked explicitly as not working, as is the entirety ofSpectre.Console.Cli
.TypeConverterHelper
based on the work by @agocke to support trimming and AOTEnumUtils
for better compatibility with NetStandard 2.0 and AOTRequiresDynamicCode
attribute to exception formatter to indicate incompatibility with AOT. Adds a fallback if someone tries to use it.TypeNameHelper
to work better in AOT scenariosCommandApp
for users who may try it.Outstanding work would be
This replaces the previous PR #1508 and closes #1332 and #1401.
I feel this is pretty solid, and ready for review and merge. I know @Armando-CodeCafe, @BlazeFace, @antoinebj and @TheExiledCat all have express interest recently in the feature so their input would also be appreciated.
Please upvote 👍 this pull request if you are interested in it.