DynamicExpresso
DynamicExpresso copied to clipboard
AOT support for .NET
It seems this library does not have AOT support, i tried a basic sample and the AOT tooling give me warnings and the generated exe throws an exception. Tried a trivial 3 lines sample on a Console app:
var interpreter = new Interpreter();
var result = interpreter.Eval("8 / 2 + 2");
Console.WriteLine($"result:{result}");
The build give me this:
Restored C:\Users\rodrigov\source\repos\AOTTest1\AOTTest1\AOTTest1.csproj (in 238 ms).
C:\Program Files\dotnet\sdk\7.0.300-preview.23179.2\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInfer
ence.targets(287,5): message NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-po
licy [C:\Users\rodrigov\source\repos\AOTTest1\AOTTest1\AOTTest1.csproj]
AOTTest1 -> C:\Users\rodrigov\source\repos\AOTTest1\AOTTest1\bin\Debug\net7.0\win-x64\AOTTest1.dll
Generating native code
C:\Users\rodrigov\.nuget\packages\dynamicexpresso.core\2.16.0\lib\netstandard2.0\DynamicExpresso.Core.dll : warning IL2
104: Assembly 'DynamicExpresso.Core' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libr
aries [C:\Users\rodrigov\source\repos\AOTTest1\AOTTest1\AOTTest1.csproj]
C:\Users\rodrigov\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.4\framework\System.Linq.Expressions.d
ll : warning IL3053: Assembly 'System.Linq.Expressions' produced AOT analysis warnings. [C:\Users\rodrigov\source\repos
\AOTTest1\AOTTest1\AOTTest1.csproj]
C:\Users\rodrigov\.nuget\packages\dynamicexpresso.core\2.16.0\lib\netstandard2.0\DynamicExpresso.Core.dll : warning IL3
053: Assembly 'DynamicExpresso.Core' produced AOT analysis warnings. [C:\Users\rodrigov\source\repos\AOTTest1\AOTTest1\
AOTTest1.csproj]
C:\Users\rodrigov\.nuget\packages\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.4\framework\Microsoft.CSharp.dll : wa
rning IL3053: Assembly 'Microsoft.CSharp' produced AOT analysis warnings. [C:\Users\rodrigov\source\repos\AOTTest1\AOTT
est1\AOTTest1.csproj]
Creating library bin\Debug\net7.0\win-x64\native\AOTTest1.lib and object bin\Debug\net7.0\win-x64\native\AOTTest1.
exp
AOTTest1 -> C:\Users\rodrigov\source\repos\AOTTest1\AOTTest1\bin\Debug\net7.0\win-x64\publish\
When running it give me this:
C:\Users\rodrigov\source\repos\AOTTest1>AOTTest1\bin\Debug\net7.0\win-x64\publish\AOTTest1.exe
Hello, World!
Unhandled Exception: System.NotSupportedException: 'System.Func`1[System.Int32]' is missing native code or metadata. This can happen for code that is not compatible with trimming or AOT. Inspect and fix trimming and AOT related warnings that were generated when the app was published. For more information see https://aka.ms/nativeaot-compatibility
at System.Reflection.Runtime.General.TypeUnifier.WithVerifiedTypeHandle(RuntimeConstructedGenericTypeInfo, RuntimeTypeInfo[]) + 0x166
at System.Reflection.Runtime.General.TypeUnifier.GetConstructedGenericTypeWithTypeHandle(RuntimeTypeInfo, RuntimeTypeInfo[]) + 0x3b
at System.Reflection.Runtime.TypeInfos.RuntimeTypeInfo.MakeGenericType(Type[]) + 0x44c
at System.Linq.Expressions.Compiler.DelegateHelpers.GetFuncType(Type[]) + 0xcf
at System.Linq.Expressions.Compiler.DelegateHelpers.MakeNewDelegate(Type[]) + 0x1e0
at System.Linq.Expressions.Compiler.DelegateHelpers.MakeDelegateType(Type[]) + 0xfc
at System.Linq.Expressions.Expression.Lambda(Expression, String, Boolean, IEnumerable`1) + 0x2d3
at System.Linq.Expressions.Expression.Lambda(Expression, Boolean, IEnumerable`1) + 0x33
at System.Linq.Expressions.Expression.Lambda(Expression, ParameterExpression[]) + 0x28
at DynamicExpresso.Lambda.<.ctor>b__3_0() + 0xfd
at System.Lazy`1.ViaFactory(LazyThreadSafetyMode) + 0xfe
at System.Lazy`1.ExecutionAndPublication(LazyHelper, Boolean) + 0x77
at System.Lazy`1.CreateValue() + 0xd4
at System.Lazy`1.get_Value() + 0x29
at DynamicExpresso.Lambda.InvokeWithUsedParameters(Object[]) + 0x34
at DynamicExpresso.Lambda.Invoke(IEnumerable`1) + 0x248
at DynamicExpresso.Lambda.Invoke(Parameter[]) + 0x26
at DynamicExpresso.Interpreter.Eval(String, Type, Parameter[]) + 0x4d
at DynamicExpresso.Interpreter.Eval(String, Parameter[]) + 0x64
at Program.<Main>$(String[]) + 0x9f
at AOTTest1!<BaseAddress>+0x45fa37
at AOTTest1!<BaseAddress>+0x45faca
This looks similar to #220, but this time it will be easier to investigate since it only uses the standard .NET tooling :)
I can't reproduce the failure. Can you share your csproj and the command you used to generate your exe?
I used Visual Studio 2022 Version 17.6.0 Preview 4.0 and .NET 8 preview 3 with the following csproj:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PublishAot>true</PublishAot>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DynamicExpresso.Core" Version="2.16.0" />
</ItemGroup>
</Project>
Program.cs:
using DynamicExpresso;
namespace ConsoleApp1;
internal class Program
{
static void Main(string[] args)
{
var interpreter = new Interpreter();
var result = interpreter.Eval("8 / 2 + 2");
Console.WriteLine($"result:{result}");
}
}
dotnet command:
dotnet publish -r win-x64 -c Release
I get a lot of warnings during publish:
C:\Program Files\dotnet\sdk\8.0.100-preview.3.23178.7\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.RuntimeIdentifierInference.targets(287,5): message NETSDK1057: You are using a preview version of .NET. See: https://aka.ms/dotnet-support-policy [C:\Users\chris\sour
ce\repos\DynamicExpresso\ConsoleApp1\ConsoleApp1.csproj]
ConsoleApp1 -> C:\Users\chris\source\repos\DynamicExpresso\ConsoleApp1\bin\Release\net7.0\win-x64\ConsoleApp1.dll
D:\NugetCache\microsoft.dotnet.ilcompiler\7.0.2\build\Microsoft.DotNet.ILCompiler.SingleEntry.targets(49,5): warning : Set PublishAot property to true and delete explicit 'Microsoft.DotNet.ILCompiler' package reference in your project file. Explicit 'Microsoft.DotN
et.ILCompiler' package reference can run into version errors. [C:\Users\chris\source\repos\DynamicExpresso\ConsoleApp1\ConsoleApp1.csproj]
Generating native code
D:\NugetCache\dynamicexpresso.core\2.16.0\lib\netstandard2.0\DynamicExpresso.Core.dll : warning IL2104: Assembly 'DynamicExpresso.Core' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries [C:\Users\chris\source\repos\DynamicExpre
sso\ConsoleApp1\ConsoleApp1.csproj]
D:\NugetCache\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.2\framework\System.Linq.Expressions.dll : warning IL3053: Assembly 'System.Linq.Expressions' produced AOT analysis warnings. [C:\Users\chris\source\repos\DynamicExpresso\ConsoleApp1\ConsoleApp1.csproj]
D:\NugetCache\dynamicexpresso.core\2.16.0\lib\netstandard2.0\DynamicExpresso.Core.dll : warning IL3053: Assembly 'DynamicExpresso.Core' produced AOT analysis warnings. [C:\Users\chris\source\repos\DynamicExpresso\ConsoleApp1\ConsoleApp1.csproj]
D:\NugetCache\runtime.win-x64.microsoft.dotnet.ilcompiler\7.0.2\framework\Microsoft.CSharp.dll : warning IL3053: Assembly 'Microsoft.CSharp' produced AOT analysis warnings. [C:\Users\chris\source\repos\DynamicExpresso\ConsoleApp1\ConsoleApp1.csproj]
Creating library bin\Release\net7.0\win-x64\native\ConsoleApp1.lib and object bin\Release\net7.0\win-x64\native\ConsoleApp1.exp
ConsoleApp1 -> C:\Users\chris\source\repos\DynamicExpresso\ConsoleApp1\bin\Release\net7.0\win-x64\publish\
but I still get the expected result when I execute the exe:
PS C:\Users\chris\source\repos\DynamicExpresso\ConsoleApp1> .\bin\Release\net7.0\win-x64\ConsoleApp1.exe
result:6
I think you are missing something important; you are running the dotenet .exe, not the native code executable. Please run the .exe coming from the 'native' folder under the publish.. it has a .exe that is fully contained and does not depend on any dotnet assembly or runtime. I use .net 8 with the hope this could be fixed but not, i basically run on the exact same problem. It has to do with the fact that using MakeGenericType API under AOT, it has all sort of problems for the trimming tooling on how to figure out how to get types you are planning to use. I have found a mitigation but it's not enough since it's almost impossible to anticipate which Func<T,T2,T3...> types will be used.
Ah right, I get the AOT error when running the native exe. I'll see if I can find a solution, but I'm not sure it's possible since DynamicExpresso tries to instantiate generic types.
I will open an issue with the .NET team related to this issue. In the meantime, it would be helpful to start paying attention to trimming warnings on DynamicExpresso library to prepare the library to be used in AOT scenarios that will become much more common after .NET7 and beyond. About the MakeGenericType, the problematic scenario is using a parameter Type into it and not a concrete type which AOT has no problem with. I have a working sample test were i trick the AOT tooling by forcing some common Func<T..> to be not trimmed. The good news is that the library did work well in native AOT after that manual step so it seems that we could be close. How about trying only object type lambdas foe each parameter instead of attempting the real type? i'm not familiar how the library would operate on the lambda invoke. My point is that the library could enforce maybe a set of Func<object, object..> combinations that will be enough to make the AOT tooling happy. This is instead of predicting Func<in, bool, number, string,..etc>