bilal-fazlani / commanddotnet

A modern framework for building modern CLI apps
https://commanddotnet.bilal-fazlani.com
MIT License
576 stars 29 forks source link

Native AOT is not supported #501

Closed lxy-iUnknown closed 1 day ago

lxy-iUnknown commented 1 week ago

Root cause: LibLog uses StackFrame.GetMethod to create logger from caller class, which is null in native aot environment. See: Native AOT StackFrame method info [API Proposal]: Diagnostic method information Solution: Replace with nameof

drewburlingame commented 4 days ago

Thanks for submitting this. The better change would be to replace LibLog with MS's logging extensions. I'm not opposed to that but it's not something I'll be able to take on soon.

Even with that work, I'm not sure CommandDotNet is AOT friendly given it relies heavily on reflection to generate the commands and none of that work is currently persisted with source generators. It's something that would be very useful if someone had the time to submit a PR for it.

lxy-iUnknown commented 3 days ago

Thanks for submitting this. The better change would be to replace LibLog with MS's logging extensions. I'm not opposed to that but it's not something I'll be able to take on soon.

Even with that work, I'm not sure CommandDotNet is AOT friendly given it relies heavily on reflection to generate the commands and none of that work is currently persisted with source generators. It's something that would be very useful if someone had the time to submit a PR for it.

Thanks for your reply. I've made a working AOT example. NativeAotSample.zip

Currently, Native AOT does not support method subsitution if its return type is not bool or int

https://github.com/dotnet/runtime/blob/756f7ebbbdcc0b8cb8b383ef3b6e6b50430f1922/src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/BodySubstitutionParser.cs#L167-L188

So I modified CommandDotNet binary by replacing "GetLogger(stackFrame.GetMethod().DeclaringType);" to "GetLogger(stackFrame.GetMethod()?.DeclaringType);"

https://github.com/damianh/LibLog/blob/7b1cf28df0dc111f49fde0a3b4927d889417ebfd/src/LibLog/LogProvider.cs#L153

DynamicDependencyAttribute and rd.xml are also necessary.

drewburlingame commented 2 days ago

Thanks @lxy-iUnknown is your sample in a public repo by chance? I'm leery of zip files.

when you modified the GetLogger call, did that change the type used for the logger name?

lxy-iUnknown commented 2 days ago

@drewburlingame I published to github recently. NativeAotSample I only modified the method body using dnSpyEx, not type name. Everything remain unchanged except for this method

drewburlingame commented 1 day ago

I removed usages of GetCurrentClassLogger which called the code you modified with dnSpyEx. It was simpler than removing LibLog. Given the high level of reflection used, I'm still not sure how AOT is safely removing code, but this should satisfy your use case.

https://www.nuget.org/packages/CommandDotNet/7.0.5