Skip to content
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 .NET #283

Open
rodrigovaras opened this issue Apr 16, 2023 · 5 comments
Open

AOT support for .NET #283

rodrigovaras opened this issue Apr 16, 2023 · 5 comments

Comments

@rodrigovaras
Copy link

rodrigovaras commented Apr 16, 2023

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
@metoule
Copy link
Contributor

metoule commented Apr 16, 2023

This looks similar to #220, but this time it will be easier to investigate since it only uses the standard .NET tooling :)

@metoule
Copy link
Contributor

metoule commented Apr 22, 2023

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

@rodrigovaras
Copy link
Author

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.

@metoule
Copy link
Contributor

metoule commented Apr 22, 2023

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.

@rodrigovaras
Copy link
Author

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>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants